放假研究恒溫烙鐵,繼昨晚研究完1602液晶驅動后,今天繼續研究利用AT89C2051內部的電壓比較器做廉價的ADC轉換器,查閱了一些資料,基本上有這么一些方法: 1、常規RC電路,對電容充電時間進行計算,通過查表得到AD值。這種AD簡單,但分辨率低,僅8位左右。 2、常規RC電路,對電容充電時間進行計算,通過直接的自然對數反對數運算得到AD值,這種AD電路簡單,分辨率高,但程序的運算量很大。2051這種低端單片機不適合此法。 3、中國歐軟采用的辦法:外置恒流源,以得到線性的充電曲線,這樣單片機的運算工作就會簡單很多了。 電路圖:
 焊接好的電路板: 

程序:
- #include <reg51.h>
- sbit CMP_R=P3^6;
- sbit ADC = P1^1;
- unsigned char sled1,sled2,sled3,sled4,sztj;//串行LED掃描數據,狀態機
- unsigned char temp,temp1,temp2;
- unsigned int advalue;
- bit timer1overflow;
- unsigned char code sledsg[]={0x28,0xEB,0x32,0xA2,0xE1,0xA4,0x24,0xEA,0x20,0xA0,
- 0x60,0x25,0x3C,0x37,0x23,0x34,0x74,0x61,0x65,0x3D,
- 0x67,0x68,0x27,0x70,0x77,0x35,0x29,0xF7,0x7F,0xff};//LED段碼
- void init(void) //初始化函數,就是開機首先要做的事情,init是自己起的名字
- {
- TMOD=0x11; //兩個定時器工作于方式1
- PX0=1; //計時定時器中斷優先
- TR0=1; //定時器0啟動
- ET0=1;
- ET1=1;
- EA=1;
- } //這段程序啟動了芯片中的兩個定時器
- void sledscan(void) //時速LED模塊掃描子程序,定時器調用
- {
- unsigned char datemp;
- switch(sztj) //切換狀態機
- {
- case 0: //第一狀態
- P3=0XFF; //關閉顯示
- datemp=sledsg[sled3];
- P1=0X01;
- P1=P1|(datemp&0xfc);
- P3=P3&(datemp|0xfc);
- P3=P3&0x7f;
- sztj=1; //轉移狀態
- break; //狀態結束
- case 1: //第二狀態
- P3=0XFF; //關閉顯示
- datemp=sledsg[sled4];
- P1=0X01;
- P1=P1|(datemp&0xfc);
- P3=P3&(datemp|0xfc);
- P3=P3&0xdf;
- sztj=2; //轉移狀態
- break; //狀態結束
- case 2: //第三狀態
- P3=0XFF; //關閉顯示
- datemp=sledsg[sled1];
- P1=0X01;
- P1=P1|(datemp&0xdc);
- P3=P3&(datemp|0xfc);
- P3=P3&0xef;
- sztj=3;
- break;
- case 3:
- P3=0XFF; //關閉顯示
- datemp=sledsg[sled2];
- P1=0X01;
- P1=P1|(datemp&0xfc);
- P3=P3&(datemp|0xfc);
- P3=P3&0xf7;
- sztj=0;
- break;
- default:
- sztj=0; //異常時捕獲狀態機
- break;
- }
- }
- void timer0 (void) interrupt 1 using 2 //定時器中斷程序,定時時間到,自動運行此程序
- {
- TH0=(65536-10000)/256; //這兩行的數值代表每10000us運行一次此程序
- TL0=(65536-10000)%256; //置定時值,每次時間到都要重新置定時值
- sledscan(); //掃描時速LED模塊,122個周期
- }
- void timer1 (void) interrupt 3 using 1 //定時器中斷程序,定時時間到,自動運行此程序
- {
- TR1=0;
- timer1overflow=1;
- TH1=0XFF;
- TL1=0XFF;
- }
- void delay()
- {
- while(--temp)
- while(--temp1)
- while(--temp2);//等待電容放電完畢
- }
- void main()
- {
- init();
- while(1)
- {
- P3=0XFF;//關閉顯示
- advalue=0;//變量復位
- ET0=0;//關閉中斷,防止中斷干擾
- TL1=0X00;
- TH1=0X00;
- TR1=1;
- ADC=1;//開始給電容充電
- while(CMP_R&&(!timer1overflow));//等待比較器結果
- timer1overflow=0;
- TR1=0;
- ADC=0;
- ((unsigned char *)&advalue)[0]=TH1;
- ((unsigned char *)&advalue)[1]=TL1;
- advalue=advalue+1000;
- sled1=advalue/10000;//轉成十進制
- sled2=advalue%10000/1000;
- sled3=advalue%1000/100;
- sled4=advalue%100/10;
- ET0=1;
- temp=4;
- delay();
- }
- }
復制代碼
|