功能:按鍵8個,測頻計數(shù),交流電壓 ,直流電壓,及相應(yīng)保護判斷亮燈指示,用ST7920-12864液晶顯示
硬件:測頻計數(shù)用到 單運放遲滯比較器、555波形陡處理、 CD4013做的D觸發(fā)器;交流電壓用到
LM358單運放半波整流,輸出加一級RC濾波.調(diào)節(jié)運放可以調(diào)節(jié)電壓、AD轉(zhuǎn)換芯片TLC1543(0-5V)。
直流電壓就沒嘛說的,電阻分壓就行了。
按鍵用74HCT245雙向數(shù)據(jù)芯片,蠻好。
繼電器控制,液晶并口數(shù)據(jù)線,保護燈,按鍵都是用P0口,用74HC573鎖存切換,AD轉(zhuǎn)換口用P1口。計數(shù)用T0 INT0 INT1 ,其他的控制腳接P2口,所以沒有做單片機口擴展,那樣到更麻煩些
補充:燈光顯示和繼電器的74HC573控制腳接到反向器74HC04,加大驅(qū)動能力。
備注:由于硬件電路做的簡單,所以,程序繁瑣,待優(yōu)化中。。。。。。。。。。。。。
以下是部分程序預(yù)覽,完整的源代碼下載:http://www.zg4o1577.cn/ziliao/file/cepin1.rar
/********關(guān)于多周期測頻法,精度與晶振和閘門時間有關(guān)。晶振越大,閘門時間越長,都可以提高精度。**********/ #include <stc89c52.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int #define LCD12864_IO P0 #define CLERADISPLAY LCD12864_command(0x01); int a1=0,a2=0,a3=0,a4=0,a5=0,a6=0;//存儲電壓值的每一位,設(shè)計a4,a5是小數(shù)位. const uchar num[]="0123456789. "; //AD轉(zhuǎn)換控制腳 sbit CLK = P1^0; //TLC1543 18P sbit ADDRESS = P1^1; //17P sbit SDATA = P1^2; //16P sbit CS = P1^3; //15P /********************************************************************/ sbit LCD12864_RS=P2^5; // 12864-st7920 4P RS sbit LCD12864_RW=P2^6; //RW(5P) sbit LCD12864_EN=P2^7; //E(6P) /********************************************************************/ void LCD12864_busy(void); void LCD12864_command(unsigned char command); void LCD12864_data(unsigned char dat); void LCD12864_address(unsigned char row,unsigned char line); void LCD12864_string(unsigned char row,unsigned char line,unsigned char *s); void LCD12864_picture(unsigned char *gImage); void LCD12864_init(void); void LCD12864_char (unsigned char row,unsigned char line,unsigned char a); unsigned char LCD12864_ReadData(); void LCD12864_Drawpoint(uchar X,uchar Y); void LCD12864_LineX(unsigned char X0, unsigned char X1, unsigned char Y); void LCD12864_LineY( unsigned char X, unsigned char Y0, unsigned char Y1); void LCD12864_DrawPicture( unsigned char code *pic); void clrgdram(); /********************************************************************/ // double DAT[7]={115.0, 115.1, 115.2, 285.0,1500.0, 400.0,3100.0}; // U V W E N F CINT // 控制腳 sbit CONTRL=P1^7; //測頻控制腳 sbit SCANF =P2^0; //鍵盤掃描控制腳 sbit LED1 =P2^1; //狀態(tài)顯示控制腳1 sbit LED2 =P2^2; //狀態(tài)顯示控制腳2 sbit SHUCHU=P2^3; //繼電器輸出控制腳 // bit FLAG; //測頻標志位 bit xunhuanflag;//顯示方式標志位 bit outflag; //允許輸出標志 bit eding;//額定狀態(tài)標志 // 按鍵存儲 bdata uchar key; //鍵值存儲 sbit key0=key^0;//停機 sbit key1=key^1;//啟動按鈕 sbit key2=key^2; //顯示方式(高循環(huán)) sbit key3=key^3; //自檢 sbit key4=key^4;//燈檢 sbit key5=key^5;//復(fù)位 sbit key6=key^6;//應(yīng)急 (高應(yīng)急) sbit key7=key^7;//油壓(高有油壓) uint t1h,t1l,t2h,t2l;//測頻變量 double cnt1,cnt2; double AD; //定義為float 類型,可以防止下面做四則運算時每一步的值超出 范圍 unsigned long int X; /****************************************************************/ uint rd1543(uchar address);//AD轉(zhuǎn)換程序 void voltage(); //電壓檢測 void init(); //初始化 void zhuansu(); //計算轉(zhuǎn)速 void reset();//測頻計數(shù)定時復(fù)位 uchar scanf(); //鍵盤掃描 void keychuli(); //按鍵處理程序 void baohu(); void display(unsigned long int sx); //顯示函數(shù) void displayFX(unsigned long int sx); /*************************************************************/ void delayus(uint); void delayms(uint); void delays(uint m); //延時秒 unsigned char code Bmp019[]= { /*------------------------------------------------------------------------------ ; 若數(shù)據(jù)亂碼,請檢查字模格式設(shè)置,注意選擇正確的取模方向和字節(jié)位順序。 ; 源文件 / 文字 : C:\Documents and Settings\Administrator\桌面\888.bmp字模 ; 寬×高(像素): 128×64 ; 字模格式/大小 : 單色點陣液晶字模,橫向取模,字節(jié)正序/1024字節(jié) ; 數(shù)據(jù)轉(zhuǎn)換日期 : 2010-7-26 20:46:48 ------------------------------------------------------------------------------*/ /**************************** 0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 上半屏行坐標,表示的是多少列 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 下半屏行坐標,每組8列,每列16位,共128位, 0x80 0x81 0x82 0x83 ........ 0x9f //列坐標,共32個,表示的是行數(shù) ,分兩個半屏,每個32行,共64行 //Y坐標 只是用來確定具體坐標,在哪一行 功能:圖形模式下,顯示(X,Y)點 輸入:X(0~127) Y(0~63) 相對屏幕坐標 輸出:無 點亮某一點的操作步驟: 1.求出水平坐標X對應(yīng)的地址和是哪一位 0x80-----0x8f (范圍0-15) X/16求地址 X%16求該地址哪一位 2.求垂直坐標Y對應(yīng)的地址和上下半屏 0x80------0x9f(范圍0-63) Y本身就是8位地址,Y=63-Y ,Y--(0-31) 3.寫入行列地址(Y是行X是列),0x80+Y ,0X80+X/16 4.讀要顯示的數(shù)據(jù) DAT 5.區(qū)分上下半屏(X%16<=7&&X%16>=0是上半屏)寫入數(shù)據(jù)每一位 DAT|0x80 ;DAT<<1 注意:這個函數(shù)顯示某一點時,可能會把上次顯示的處于同一地址的其他位的點擦掉,所以先保存所有數(shù)據(jù),最后顯示,就連貫起來了 *******************************/ /*******************************************************************/ /**************************************************************/ //------------------清整個GDRAM空間---------------------------- /**************************************************************/ void clrgdram() { unsigned char x,y ; for(y=0;y<64;y++) for(x=0;x<16;x++) { LCD12864_command(0x34); LCD12864_command(y+0x80); LCD12864_command(x+0x80); LCD12864_command(0x30); LCD12864_data(0x00); LCD12864_data(0x00); } } /******************************************/ /*******8========================================================================== 功能:圖形模式下,顯示(X,Y)點 輸入:X(0~127) Y(0~63) 輸出:無 0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 上半屏行坐標,表示的是多少列,X地址 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 下半屏行坐標,X地址 (水平地址 ) 0x80 (垂直地址) 0x81 0x82 0x83 ........ 0x9f //列坐標,共32個,表示的是行數(shù) ,分兩個半屏,每個32行,共64行 ====================================================================**********/ void LCD12864_Drawpoint(uchar X,uchar Y) { uchar i= 0, j = 0,ok=0; uchar temp1 = 0x00,temp2 = 0x00; LCD12864_command(0x34); //8位,擴充指令,繪圖關(guān) LCD12864_command(0x36); //8位,擴充指令,繪圖開 i = X/16; //計算出X字節(jié)地址(0X80-0X8F) j = X%16; //計算出該字節(jié)的具體位(0-15) //Y = 63 - Y; if(Y>=0 && Y<=31)//判斷上下半屏 { ok=1; } else if(Y>=32 && Y<=63)//下半屏 { Y = Y - 32;//Y只有0-31共32個 地址 i = i + 8;//X地址進入下半屏 (0X88-0X8F) ok=1; } if(ok) { //讀數(shù)據(jù)操作 LCD12864_command(0x80+Y); //第一步:設(shè)置Y坐標,讀數(shù)據(jù)先寫地址,寫GDRAM時先寫垂直地址(0X80-0X9F) LCD12864_command(0x80+i); //第二步:設(shè)置X坐標 LCD12864_ReadData(); //第三步:空讀取一次 temp1 =LCD12864_ReadData(); //第四步:讀取高字節(jié),先讀高字節(jié) temp2 =LCD12864_ReadData(); //第五步:讀取低字節(jié) //圖形模式下的寫數(shù)據(jù)操作 LCD12864_command(0x80+Y); //第一步:設(shè)置Y坐標 LCD12864_command(0x80+i); //第二步:設(shè)置X坐標 if(j>=0 && j<=7) //判斷是高字節(jié) { LCD12864_data(temp1|(0x80>>j)); //第三步:寫高字節(jié)數(shù)據(jù) LCD12864_data(temp2); //第四步:寫低字節(jié)數(shù)據(jù) } else if(j>7 && j<=15) //判斷是低字節(jié) { j = j - 8; LCD12864_data(temp1); LCD12864_data(temp2|(0x80>>j)); //改變字節(jié)里的位 } } } /******************************************/ //畫線 /********************************************/ //畫水平線 void LCD12864_LineX(unsigned char X0, unsigned char X1, unsigned char Y) { unsigned char Temp ; if( X0 > X1 ) { Temp = X1 ; //交換X0 X1值 X1 = X0 ; //大數(shù)存入X1 X0 = Temp; //小數(shù)存入X0 } for( ; X0 <= X1 ; X0++ ) LCD12864_Drawpoint(X0,Y); } //畫垂直線 void LCD12864_LineY( unsigned char X, unsigned char Y0, unsigned char Y1) { unsigned char Temp ; if( Y0 > Y1 )//交換大小值 { Temp = Y1 ; Y1 = Y0 ; Y0 = Temp ; } for(; Y0 <= Y1 ; Y0++) LCD12864_Drawpoint( X, Y0) ; } /******************************************/ /**************畫圖************************/ void LCD12864_DrawPicture( unsigned char code *pic) { unsigned char i, j, k ; LCD12864_command(0x34);//開擴充指令 LCD12864_command(0x36);//開繪圖功能 for( i = 0 ; i < 2 ; i++ )//分上下兩屏寫 { for( j = 0 ; j < 32 ; j++)//垂直地址遞加 ,行掃方式 { LCD12864_command( 0x80 + j ) ;//寫Y坐標(Y的范圍: 0X80-0X9F ) if( i == 0 ) //寫X坐標 { LCD12864_command(0x80);//上半屏 } else { LCD12864_command(0x88);//下半屏開始地址 } for( k = 0 ; k < 16 ; k++ ) //寫一整行數(shù)據(jù) { LCD12864_data( *pic++ );//前面只寫入首地址,后面依次寫入數(shù)據(jù),地址會自動遞增 } } } LCD12864_command( 0x30);//恢復(fù)到一般模式 } // // 初始化設(shè)置 /*******************************************************************/ void LCD12864_init(void) { CLERADISPLAY // clear DDRAM LCD12864_command(0x30); // 8 bits unsigned interface,basic instrument LCD12864_command(0x02); // cursor return LCD12864_command(0x0c); // display,cursor on LCD12864_command(0x03); LCD12864_command(0x06); CLERADISPLAY // clear DDRAM } // //顯示函數(shù) void display(unsigned long int sx) { a1=sx/100000; a2=sx%100000/10000; a3=sx%10000/1000;//千位 a4=sx%1000/100;//百位 a5=sx%100/10;//十位 a6=sx%10;//個位 LCD12864_command(0x90); //指定顯示位置 LCD12864_data(num[a1]); //從最高位開始顯示 LCD12864_data(num[a2]); LCD12864_data(num[a3]); LCD12864_data(num[a4]); LCD12864_data(num[a5]); LCD12864_data(num[10]);//小數(shù)點 LCD12864_data(num[a6]); } void displayFX(unsigned long int sx) { a1=sx/100000; a2=sx%100000/10000; a3=sx%10000/1000; a4=sx%1000/100; a5=sx%100/10; a6=sx%10; LCD12864_command(0x98); //指定顯示位置 LCD12864_data(num[a1]); //從最高位開始顯示 LCD12864_data(num[a2]); LCD12864_data(num[a3]); LCD12864_data(num[a4]); LCD12864_data(num[a5]); LCD12864_data(num[a6]); } /********************************* 主函數(shù)入口 /********************************************/ //主函數(shù)入口 // main() { uchar ii=0; CONTRL=0; Mcu_init(); CLERADISPLAY delays(1); LCD12864_char(1,2,'A'); LCD12864_string(1,4,"shaozhanyu"); delays(2); clrgdram(); CLERADISPLAY delays(1); clrgdram(); delays(1); LCD12864_LineX(8,113,25); clrgdram(); CLERADISPLAY delays(2); clrgdram(); LCD12864_LineY(55,29,57); delays(2); clrgdram(); delays(1); LCD12864_DrawPicture(Bmp019); delays(3); Mcu_init(); CLERADISPLAY LCD12864_string(3,1,"N F U V W E"); LCD12864_char(2,1,'D'); LCD12864_string(4,1,"計數(shù)"); LCD12864_string(1,3,"少占魚做"); display(123456); /***************8888 P0=0x10;//怠速,準備打開K5繼電器,關(guān)閉其他輸出繼電器 SHUCHU=0;//打開輸出閘門 SHUCHU=1;//關(guān)閉閘門 outflag=0;//輸出標志位 ******************/ AD=0.0; keychuli(); //掃描并處理按鍵 delayms(5200); ///初始化 init(); while(1) { while(!FLAG); //等待頻率測出 keychuli(); //掃描并處理按鍵 LCD12864_string(1,3,"開始轉(zhuǎn)換"); delayms(300); voltage(); //采樣電壓 LCD12864_string(1,3,"轉(zhuǎn)換完成"); delayms(400); baohu();//判斷采樣數(shù)據(jù)保護 for(;ii<6;ii++) { display(DAT[ii]); LCD12864_string(1,3,"顯示下組"); delayms(1200); // keychuli(); if(xunhuanflag==0) //定點 {display(DAT[ii]); break; } } if(ii==6) ii=0; display(DAT[ii]); displayFX(DAT[6]); LCD12864_string(1,3,"下輪復(fù)位"); delayms(1000); init(); } } /*************************************/ //初始化函數(shù) void init() { /******T1定時器模式,外部INT1控制開啟,T0計數(shù)器不允許中斷,外部控制 INTO開啟,外部中斷0允許(EX0=1), 定時器T2中斷允許 (ET2=1) ************/ CONTRL=0; FLAG=0; EX0=0; ET2=0; //三個定時器方式設(shè)置 TMOD=0x9d; //T0T1方式控制 T2MOD=0x00; T2CON=0x00;//定時器2,16位定時方式,自動重裝。 TH0= 0x00; // T0高8位 TL0= 0x00; // T0低8位 TH1= 0x00; // T1高8位 TL1= 0x00; // T1低8位 EXEN2=0; TH2=256/256; TL2=256%256; RCAP2H=256/256; RCAP2L=256%256; //中斷設(shè)置 5 EX0=1;//允許外部0輸入中斷(INT0引腳) ET2=1; //開定時中斷2 IT0=1; //外部中斷0邊沿觸發(fā),下降沿到來觸發(fā) //優(yōu)先級設(shè)置 PX0=1; //預(yù)置T0,T1 TR1=1;//先允許T1定時,因T1的GATE=1,還要等外部INT1高電平才計數(shù) TR0=1;//先允許T0計數(shù) ,同T1一樣,等待INTO高電平 TR2=1;//啟動T2定時,不用外部控制,直接啟動 EA=1; //開全局中斷 CONTRL=1; //初始化完成...... } /********************************** void reset() { CONTRL=0; FLAG=0; TL0=0x00; TH0=0x00; TL1=0x00; TH1=0x00; TF2=0; TH2=256/256; TL2=256%256; TR1=1;//先允許T1定時,因T1的GATE=1,還要等外部INT1高電平才計數(shù) TR0=1;//先允許T0計數(shù) ,同T1一樣,等待INTO高電平 TR2=1;//啟動T2定時,不用外部控制,直接啟動 EA=1; //開全局中斷 CONTRL=1; } *******************************/ //鍵盤掃描 uchar scanf() { uchar value; P0=0xff; delayms(1); SCANF=0;//打開鍵掃閘門 value=P0; delayms(2); value=P0; SCANF=1; return value; } /********************************/ //鍵處理 void keychuli() { uchar k; //關(guān)于指示燈,交流和頻率是一組,直流和其他項是一組 /***************************************/ /******************/ key=scanf(); /******************/ //啟動鍵判斷 if(key1==0&&key7==0&&DAT[4]==0)//啟動位 ,油壓和轉(zhuǎn)速為0 { for(k=0;k<3;k++)//三次啟動循環(huán) { P0=0x04;//準備 輸出K6繼電器 SHUCHU=0;//打開閘門 delays(3);//隔三秒響應(yīng)一次停機鍵 //響應(yīng)停機鍵 key=scanf(); if(key0==0&&key7==1&&DAT[4]>500)//停機開關(guān)狀態(tài),油壓高,轉(zhuǎn)速達到500,其他繼電器都停止工作 ,所以 ,P0=0x08 { P0=0x03;//準備 輸出K0繼電器 SHUCHU=0;//打開輸出閘門 SHUCHU=1;//關(guān)閉閘門 outflag=0;//輸出標志位 } if(key1==0&&key7==1&&DAT[4]>430) //每啟動一次都判斷是否成功,成功直接跳出 break ; //判斷啟動成功,立即跳出啟動for 循環(huán) delays(3);//沒有啟動成功,繼續(xù)啟動3秒 key=scanf(); if(key1==0&&key0==0&&key7==1&&DAT[4]>500)//停機,油壓高,轉(zhuǎn)速達到500,其他繼電器都停止工作 ,所以 ,P0=0x08 { P0=0x03;//準備 輸出K0繼電器 SHUCHU=0;//打開輸出閘門 SHUCHU=1;//關(guān)閉閘門 outflag=0;//輸出標志位 } if(key1==0&&key7==1&&DAT[4]>430) //每啟動一次都判斷是否成功,成功直接跳出 break ; delays(3); key=scanf(); if(key0==0&&key7==1&&DAT[4]>500)//停機,油壓高,轉(zhuǎn)速達到500,其他繼電器都停止工作 ,所以 ,P0=0x08 { P0=0x03;//準備 輸出K0繼電器 SHUCHU=0;//打開輸出閘門 SHUCHU=1;//關(guān)閉閘門 outflag=0;//輸出標志位 } if(key1==0&&key7==1&&DAT[4]>430) //每啟動一次都判斷是否成功,成功直接跳出 break ; P0=0x00;//停止啟動 SHUCHU=0; SHUCHU=1; delays(9); }//for啟動循環(huán)結(jié)束 SHUCHU=1;//關(guān)閉閘門 /**********************/ //啟動失敗判斷 if(key7==0) //油壓低 if(DAT[4]<440) { P0=0x01;//點亮啟動失敗燈 LED1=0;//開啟573輸入 LED1=1;//關(guān)閉使能,74HC573鎖定狀態(tài) outflag=0;//輸出標志位清0,表示輸出未允許 } } //停機鍵判斷 /********************/ if(key0==0&&key7==1&&DAT[4]>500)//停機,油壓高,轉(zhuǎn)速達到500,其他繼電器都停止工作 ,所以 ,P0=0x08 { P0=0x03;//準備 輸出K0繼電器 SHUCHU=0;//打開輸出閘門 SHUCHU=1;//關(guān)閉閘門 outflag=0;//輸出標志位 } /*****************/ //應(yīng)急鍵判斷 if(key6==1)//應(yīng)急/正常,高電位應(yīng)急 { eding=1;//應(yīng)急標志 } else if(key6==0) //進入怠速 { eding=0;//怠速標志 } if(eding==0)//對怠速的處理 { P0=0x08;//怠速,準備打開K5繼電器,關(guān)閉其他輸出繼電器 SHUCHU=0;//打開輸出閘門 SHUCHU=1;//關(guān)閉閘門 outflag=0; } if(eding==1&&outflag==0)//對額定的處理 { P0=0x00;//額定,準備關(guān)閉K5繼電器,進入額定,其他繼電器都停止工作 ,所以 ,P0=0x00 SHUCHU=0;//打開輸出閘門 SHUCHU=1;//關(guān)閉閘門 delayms(2); if(DAT[0]>110&&DAT[1]>110&&DAT[2]>110&&DAT[5]>390)//三相交流大于110 ,頻率大于390 { P0=0x30;//準備合閘(交流,直流 內(nèi)控制 ) SHUCHU=0; SHUCHU=1; outflag=1;//合閘后,輸出標志位置1 } } /******************************/ //循環(huán)鍵 if(key2==1) //處理循環(huán)定點顯示標志位 xunhuanflag=1; else if(key2==0) xunhuanflag=0; /**********保護函數(shù)*******************/ void baohu() { if(outflag==1) { //立即保護值 if((DAT[0]<80||DAT[1]<80||DAT[2]<80) || (DAT[0]>180||DAT[1]>180||DAT[2]>180) || DAT[5]>445||DAT[5]<320)//立即斷閘保護 { { P0=0x00;//準備斷閘(交流,直流 內(nèi)控制 ) SHUCHU=0; SHUCHU=1; outflag=1;//合閘后,輸出標志位清0 } if((DAT[0]>180||DAT[1]>180||DAT[2]>180)&&DAT[5]>445) {P0=0x05; /*******************************/ //轉(zhuǎn)速計算 ,頻率計算 void zhuansu() { t1h=TH0; t1l=TL0; t2h=TH1; t2l=TL1; cnt1=t1l+(t1h<<8); cnt2=t2l+(t2h<<8); DAT[6]=cnt1/cnt2*1000000.200;//計數(shù)值 DAT[4]=cnt1/cnt2*1000000.200/124.00*600.00; //計算轉(zhuǎn)速,信號頻率就是單片機計數(shù)頻率的整數(shù)倍 ,這里這樣寫是怕cnt1 cnt2 超出范圍 //注意這里: cnt1 cnt2 的類型不能是 uint 否則第一步計算除法會得0 , 如果你要先乘1000000.0,也不行。因為超出了uint 范圍 DAT[5]=DAT[4]*16.00/60.000;//電壓頻率計算 } /******************************/ //外部中斷0,調(diào)用轉(zhuǎn)速計算 void interint0() interrupt 0 //using ** //外部中斷0處理 { EA=0; zhuansu();//調(diào)用轉(zhuǎn)速函數(shù) FLAG=1; /***注意:因為TO T1是外部引腳控制的,所以,這時外部低電平,自動停止。不用軟件停止**/ } void intertimer2() interrupt 5 //using ** //T2定時中斷處理 { TR2=0; CONTRL=0;//關(guān)閉閘門信號 } /*******************************/ //AD轉(zhuǎn)換程序 /************************************************/ //常測數(shù)據(jù)函數(shù) void voltage() //電壓測量 { uchar i; AD=0.00; X=0; for(i=0;i<20;i++) { AD+=rd1543(0x08); //讀取AD值 } // AD=AD/20; X=AD*46.0001*50.00/1023.00;//轉(zhuǎn)換成電壓值 ,分辨率是10位 DAT[0]=X; AD=0.00; delayus(2); // for(i=0;i<20;i++) { AD+=rd1543(0x08); //讀取AD值 } // AD=AD/20; X=AD*46.0001*50.00/1023.00;//轉(zhuǎn)換成電壓值 ,分辨率是10位 DAT[1]=X; // AD=0.00; delayus(2); // for(i=0;i<20;i++) { AD+=rd1543(0x08); //讀取AD值 } // AD=AD/20; X=AD*46.0001*50.00/1023.00;//轉(zhuǎn)換成電壓值 ,分辨率是10位 DAT[2]=X; // AD=0.00; delayus(2); // /********* for(i=0;i<20;i++) { AD+=rd1543(0x07); //讀取AD值 } // AD=AD/20; X=AD*50.000/1023.000*28.500/4.000; DAT[3]=X; // **********/ } /***********************************************/ //TLC1543輸入模擬電壓范圍: 0-4.9152 V //TLC1543AD 10個時鐘方式 方式1 。 LC1543 有四位精度 。 輸入 0.0024v 時,AD值為0000000001 //0.0048時,還為1。 0.0072為 2 也就是0.0048 為一個 寬度 0.0048*AD 就是電壓值 . uint rd1543(uchar addr) { uint date_out=0; uchar k; // uchar j; CLK=0; CS=0; ADDRESS=(bit)(addr&0x08); //用這種愚蠢的方法比用FOR循環(huán)快的多 。 CLK=1; CLK=0; addr=addr*2; //用乘法比用左移快 ADDRESS=(bit)(addr&0x08); CLK=1; CLK=0; addr=addr*2; //用乘法比用左移快 ADDRESS=(bit)(addr&0x08); CLK=1; CLK=0; addr=addr*2; //用乘法比用左移快 ADDRESS=(bit)(addr&0x08); CLK=1; CLK=0; addr=addr*2; //用乘法比用左移快 // for (j=0;j<6;j++) //填充6 個CLOCK // { CLK=1;CLK=0; //這里不用循環(huán),省時間 CLK=1;CLK=0; CLK=1;CLK=0; CLK=1;CLK=0; CLK=1;CLK=0; CLK=1;CLK=0; CLK=0; // } CS=1; delayus(8); //等待AD 轉(zhuǎn)換 CS=0; for(k=0;k<10;k++) { SDATA=1; //非P0口作為數(shù)據(jù)總線使用時,讀入數(shù)據(jù)前要賦值1,特別 CLK = 1; //是既用于寫有用于讀的情況下. date_out<<=1; if(SDATA) date_out += 1; //這樣寫法比下面的方法速度快(5us) // date_out=date_out|SDATA;//用時6US CLK = 0; } return(date_out); }