标题: AT89C2051内部比较器做AD转换器ADC [打印本页]
作者: wudawei 时间: 2014-12-31 00:11
标题: AT89C2051内部比较器做AD转换器ADC
放假研究恒温烙铁,继昨晚研究完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();
- }
- }
复制代码
作者: 51hei电控2112312 时间: 2015-1-1 23:51
GOOD!!!
作者: szyybyf 时间: 2016-3-29 21:23
先下载看一下,不知道可不可用
作者: 新乡家电维修 时间: 2016-9-10 19:58
试过了吗,你们谁试过,精度如何
作者: 新乡家电维修 时间: 2017-2-15 13:01
利用定时器计时加横流充电,精度很高的,我制作过。
很容易达到4位精度
作者: 1305115329 时间: 2017-9-1 02:48
用ISIS 7 Professional 仿真后怎么只显示四个 7777
作者: rayin 时间: 2020-11-15 09:56
谢谢楼主分析代码,值得学习
作者: zmc419 时间: 2022-9-26 16:06
好象有人说模型中的89c2051无比较器,而后,有人做了个模型
作者: shuiquan3 时间: 2022-9-28 20:38
太棒了,我一直想制作一个
作者: zydl123 时间: 2022-10-3 13:03
学习了,谢谢你的付出
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |