放假研究恒温烙铁,继昨晚研究完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();
- }
- }
复制代码
|