单片机 数字电压表(ADC0809)
一、简述
采用模数转换的芯片ADC0809实现设计数字电压表。例子中设计的数字电压表可以测量0~5V范围内的输入电压值,并且通过4位LED数码管显示采集的电压值,例子测量三个模拟值:4.995、2.5、0.005。
ADC0809是可以将我们要测量的模拟电压信号量转换为数字量从而可以进行存储或显示的一种转换器件。
文件打包:链接: https://pan.baidu.com/s/1F2E135Jw7TG3EmUVx3xKGg 提取码: 5ttz
二、效果
三、工程文件
1、Keil工程
2、仿真电路图
四、源文件
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
uchar code led[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数码管显示0-9的电平码
uint volt,vtime; //电压值测定值
uchar addr;//测量地址位
sbit LW1=P2^3; //对应第4个数码管
sbit LW2=P2^2; //对应第3个数码管
sbit LW3=P2^1; //对应第2个数码管
sbit LW4=P2^0; //对应第1个数码管
sbit LW5=P1^4;//指示当前显示的是第几个转换值
sbit CLK=P2^4; //时钟信号
sbit START=P2^5; //转换启动开关
sbit EOC=P2^6; //转换结束标志
sbit OE=P2^7;//定义ADC0809各脚
/**********************************************************/
//函数名:delay(uint x)
//功能:延时程序 改变测量地址
//调用函数:
//输入参数:x
//输出参数:
//说明:程序的延时时间为x乘以0.5ms 每5s改变测量地址位
/**********************************************************/
void delay(uint x)
{uchar y,z;for(y=x;y>0;y--)for(z=250;z>0;z--);//该步运行时间约为0.5msvtime++;if(vtime==1000){vtime=0;addr++;if(addr==3) //本例子一共有3个测量输入值,轮流读取这3个值并转换显示addr=0;//以上语句实现测量地址位的改变 }
}
/**********************************************************/
//函数名:ADC()
//功能:数模转换程序
//调用函数:
//输入参数:
//输出参数:
//说明:将转换好的测定值保存在变量volt中
/**********************************************************/
void ADC()
{EA=1;//开中断//确保进入正常AD转换状态?START=0;START=1;START=0;//ad开始转换 while(EOC==0); //等待转换结束OE=1; //输出数据标志为真EA=0;//关中断volt=P3;//获取转换值保存到volt中,(P3为转换后数据)volt=volt*196;//转换值处理 (例子的满量程为5V,转换分辩率为8位即最大值是255,5/255=196mV,即1代表196mV)OE=0;//输出转换结束 (要在获取转换值之后)
}
/**********************************************************/
//函数名:display()
//功能:4位数码管显示
//调用函数:delay(uint x)
//输入参数:
//输出参数:
//说明:将处理后的电压值显示在4位数码管上
/**********************************************************/
void display()
{P0=0xff;//消隐 (相当于全部灭灯,清除上次显示效果)LW1=0;P0=~led[volt/10000]&0x7f;//带小数点1伏显示位delay(2);P0=0xff;LW1=1;LW2=0;P0=~led[(volt/1000)%10];//100毫伏显示位delay(2);P0=0xff;LW2=1; LW3=0;P0=~led[(volt/100)%10];//10毫伏显示位delay(2);P0=0xff;LW3=1;LW4=0;P0=~led[(volt/10)%10];//1毫伏显示位delay(2);P0=0xff;LW4=1;LW5=0;P0=~led[addr+1];//显示电压测量位delay(2);LW5=1;//指示当前显示的是第几个转换值
}
/**********************************************************/
//主程序
/**********************************************************/
void main()
{EA=1;//开总中断 TMOD=0x01;//设定定时计数工作方式//为定时器初赋值TH0=0XFF;TL0=0XB4;ET0=1;//开定时器0中断 TR0=1;//开启定时器0while(1){P1=addr;//装入测量地址LW5=1;ADC();//调用模数转换程序display();//调用显示程序}
}
/**********************************************************/
//函数名:timer() interrupt 1
//功能:定时中断0响应程序
//调用函数:
//输入参数:
//输出参数:
//说明:为ADC提供时钟信号
/**********************************************************/
void timer() interrupt 1
{//初值重置TH0=0XFF;TL0=0XF0;CLK=~CLK;//取反 产生时钟信号
}
五、总结
ADC0809是一种有8路模拟输入、8位并行数字输出的逐次逼近式A/D器件。
1、主要技术指标和特性
(1) 分辨率:8位;
(2) 转换时间:取决于芯片的时钟频率,转换1次所需时间;
(3) 单一电源:+5V;
(4) 模拟输入电压范围:单级性为0~+5V。
2、引脚介绍
管脚功能说明:
IN0-IN7:模拟量输入通道。就是说它可以分时地分别对八个模拟量进行测量转换。
ADDA-C:地址线。也就是通过这三根地址线的不同编码来选择对哪个模拟量进行测量转换。
ALE:地址锁存允许信号。在低电平时向ADDA-C写地址,当ALE跳至高电平后ADDA-C上的数据被锁存
START:启动转换信号。当它为上升沿后,将内部寄存器清0。当它为下降沿后,开始A/D转换。
D0-D7:数据输出口。转换后的数字数据量就是从这输出给S52的。
OE:输出允许信号,是对D0-D7的输出控制端,OE=0,输出端呈高阻态,OE=1,输出转换得到的数据。
CLOCK:时种信号。ADC0809内部没有时钟电路,需由外部提供时钟脉冲信号。
EOC:转换结束状态信号。EOC=0,正在进行转换。EOC=1,转换结束,可以进行下一步输出操作
Vref(+)、Vref(-):参考电压。参考电压用来与输入的模拟量进行比较,作为测量的基准。一般Vref(+)=5v ,Vref(-)=0V。
3、时序图与工作过程
时序图:
工作过程:
①在IN0-IN7上可分别接上要测量转换的8路模拟量信号。可只接一路。
②将ADDA-ADDC端给上代表选择测量通道的代码。如000(B)则代表通道0;001(B)代表通道1;111则代表通道7。
③将ALE由低电平置为高电平,从而将ADDA-ADDC送进的通道代码锁存,经译码后被选中的通道的模拟量送给内部转换单元。
④给START一个正脉冲。当上升沿时,所有内部寄存器清零。下降沿时,开始进行A/D转换;在转换期间,START保持低电平。
⑤EOC为转换结束信号。在上述的A/D转换期间,可以对EOC进行不断测量,当EOC为高电平时,表明转换工作结束。否则,表明正在进行A/D转换。
⑥当A/D转换结束后,将OE设置为1,这时D0-D7的数据便可以读取了。OE=0,D0-D7输出端为高阻态,OE=1,D0-D7端输出转换的数据。
说明:ADC0809的转换工作是在时钟脉冲的条件下完成的,因此首先要在CLOCK端给它一个时钟信号,说明书上给出了可以接入的脉冲信号频率是在10KHz-1280KHz,典型值是640KHz。我们这里取值50KHz。
时序图上的teoc时长为:从START上升沿开始后的8个时钟同期再加2微秒。这一点得注意,因为当START脉冲刚结束进入转换工作时,EOC还没有立即变为低电平而是过了8个时钟周期后才进入低电平的,所以再给出START脉冲后最好延时一会再进行EOC的检测。
一个通道的转换时间一般为64个时钟周期,如时钟频率为640KHz时,时钟周期为1.5625微秒,一个通道的转换时间则为1.5625×64=100微秒,那么1秒种就可以转换1000000÷100=10000次。
4、计算定时器初值:
信号频率取值50KHz,晶振频率是12MHz。
12MHz时钟频率下,12MHz = 12000KHz = 12000000Hz,一个时钟振荡周期就是1/12000000秒,亦即1/12微秒,标准MCS51系列单片机的一个机器周期是12个时钟振荡周期,也就是12 * (1/12) = 1微秒。
要输出50KHz的矩形方波 周期 T = (1/50K)s 等宽 也就是占空比50% 高电平时间是(0.5/50K)s = 0.01 ms = 10us
然而,实际上仿真时这个频率是太快了(不知道是否是计算方法错了),编程中没有使用该初值。
六、Proteus相关操作
1、电压探针元件(显示电压)
2、自定义电源电压
-------------------------------------------------以下是回复 Rainynightsunset 这位兄弟---------------------------
下载打包文件之后:
========================以下回复 木子Jasmine 这位兄弟======================
手动复位效果 (使用轮询方式检测按键有没有按下,因为外部中断引脚被使用了)
测试代码以及仿真文件:链接: https://pan.baidu.com/s/1zC8uhzlbIFRBOkOWuWzAWQ 提取码: wr39
===================以下回复 Leon. 这位兄弟=======================
将程序中的addr最值修改为8,如下:
在仿真上,添加5个模拟输入
效果:(注:想要查看电压,请加上电压探针元件)
============== ===== 以下回复 馨心愢忞 ========================
简单的测量20v(采用分压法:先把电压除以4再进行转换,得到转换的值后再乘以4)
测试例子:链接: https://pan.baidu.com/s/10RzT9lFVbB8db4CO7at_0A 提取码: zwem
测试效果:
分压测量20V说明:
=======================以下回复 yikai0511和validatetoken==============================
以下例子是:按键设置最高电压,当前电压大于等于最高电压时蜂鸣器报警以及LED亮,测试环境为Win10
电压为20V的可以自己设置的,上下限值同时设置暂时没弄好(感觉引脚不够用,需要复用引脚)
例子打包:链接: https://pan.baidu.com/s/1RY18AeWCCsXXqlgUBeTv_w 提取码: pdf7
仿真截图:
效果: