实验目的:
用AT89C51+ADC0808,通过ADC获取电压,显示到数码管上。
原理图如下:
(关于ADC0808的clock部分,本人另一篇文章中提到,C51虽然可以实现,但资源有限,只能勉强工作,在这里改为100KHz的时钟模拟信号,同时ADC部分也不再说明,有需要参考的朋友请看此处:C51单片机——ADC0808控制PWM)
代码:
数码管显示部分,需注意以下几点:
1.整数做乘除,会直接丢掉小数点后面的数,需要其中有一个数是小数。
比如:以ADC的50%电压来说,ADC应该是255*50%=127,转换电压,应该是5/255*127,结果会等于0;如果是5*127/255,则等于2;如果是5.0*127/255,则等于2.49019。
2.P0,P2口换数据前需要清零,不然会重叠上一部分的数据,导致显示异常。
3.因这里的电压范围是0~5伏,我就默认最高位后面加小数点了,另外放了个带小数点的表。
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit CLK = P2^4;
sbit ST = P2^5;
sbit EOC = P2^6;
sbit OE = P2^7;
uint ADC_temp,v_temp;
float voltage; //电压值浮点数存储
uchar code num[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //共阴极0~9
uchar code num_dot[] = {0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF}; //带小数点的共阴极0~9
void delay10ms(uint n)
{
uchar i,j;
for(;n>0;n--)
{
for(i=0;i<18;i++)
{
for(j=0;j<184;j++){;}
}
}
}
void ADC_read() //ADC0808取值
{
ST = 0;
OE = 0;
ST = 1;
ST = 0;
while(!EOC) {}
OE = 1;
ADC_temp = P1;
OE = 0;
}
void dis_voltage()
{
uchar i;
voltage = ADC_temp*5.0/255; //转换为对应的电压值
v_temp = voltage; //取整数部分
P0 = 0x00; //清零
P2 |= 0x0f; //P2位数口置1
P0 = num_dot[v_temp]; //最高位带小数点
P2 &= ~0x01;
delay10ms(1);
for(i=1;i<4;i++)
{
voltage = voltage*10;
v_temp = voltage;
P0 = 0x00; //清零
P2 |= 0x0f; //P2位数口置1
P0 = num[v_temp%10]; //取小数部分
P2 &= ~(0x01 << i);
delay10ms(1);
}
}
void main(void)
{
while(1)
{
ADC_read();
dis_voltage();
}
}