晚上给个朋友在51上调ADC0808芯片
共 4267字,需浏览 9分钟
·
2022-06-21 13:14
今天有个同学跟我说,自己在51上调试ADC芯片,但是显示一直不正常,然后晚上帮忙看了下,也做下记录,也不是很难的东西,不过还是要记录下比较好。
ADC0808
这个是一个8位的ADC芯片,输入0~5V,转成数字数字是0~255。
8位ADC可以把5V数据等分255份,这是关键
我们做个假设,如果我们输入 1250MV,通过公式计算,输出的数字量应该是
我们得到64这个数字量后,需要再转换成电压给显示出来
ADC0808的电路介绍
这个芯片关键是
上电时序(51引脚电平跳变)
时钟(定时器)
输入选择(下图)
转换结束OE(输入引脚判断)
代码程序
/** 功能:实现ADC一个通道的数据采集并把转换 处理结果送入LCD显示 **/
#include <reg52.h>
#include <intrins.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
#define lcd_out P1 //注意
#define adc_data_port P0 //注意/*定义相关端口*/
sbit RS = P2^0;
sbit RW = P2^1;
sbit E = P2^2;
sbit START =P2^3;
sbit EOC = P2^4;
sbit OE = P2^5;
sbit ADCCLK = P2^6;
sbit alertor = P2^7;
sbit ADDA = P3^0;
sbit ADDB = P3^1;
sbit ADDC = P3^2;
/*相关函数的声明*/
void check_busy (void);
void write_command(uchar com);
void write_data(uchar dat);
void LCD_initial(void);
void string(uchar ad,uchar *s);
void dis_char(uchar ad,uchar input);
void display_data(uchar input);
void lcd_test(void);
void delay(uint);
void adc_change(void);
void adc_channel(bit ac,bit ab,bit aa);
void time0_init();
uchar adc_data = 0;//存放ADC转换结果
unsigned long int voltage = 0;/**主程序部分**/
void main(void)
{
LCD_initial();
time0_init();
while(1)
{
adc_channel(0,0,0); //ADC0809通道IN0输入
adc_change();
display_data(adc_data);
delay(500);
}
}
//输入转换通道
void adc_channel(bit ac,bit ab,bit aa)
{
ADDC = ac;
ADDB = ab;
ADDA = aa;}//开始转换void adc_change(void){
OE=0;
START=0;
START=1;
START=0;
while(EOC==0);
adc_data_port=0xff;
OE=1;
adc_data=adc_data_port;
OE=0;
}
/*定时器0通过中断方式产生控制ADC的时钟信号*/
void time0_init()
{
TMOD=0x01;
TH0=(65536-200)/256;
TL0=(65536-200)%256;
ET0=1;
EA=1;
TR0=1;
}
//定时器0中断方式1
void timer0() interrupt 1
{
TH0=(65536-200)/256;
TL0=(65536-200)%256; //重载
ADCCLK= ~ADCCLK; //反转
}
//LCD显示信息
void display_data(uchar input)
{
//提取ADC转换后的
dis_char(0x0d,input/100 + 0x30);
dis_char(0x0e,input/10%10 + 0x30);
dis_char(0x0f,input%10 + 0x30);
//将对应二进制码转换成对应的电压值
voltage = input * 19.6078;
dis_char(0x4a, voltage/1000 + 0x30);
dis_char(0x4b, voltage%1000/100 + 0x30);
dis_char(0x4c, voltage%100/10 + 0x30);
dis_char(0x4d, voltage%10 + 0x30);
dis_char(0x4e, 'm');
dis_char(0x4f, 'v');
}
//1ms延时函数
void delay(uint j)
{
uchar i=250;
for(;j>0;j--)
{
while(--i);
i=249;
}
}
//查忙程序
void check_busy()
{
uchar dt;
do
{
dt=0xff;
E=0;
RS=0;
RW=1;
E=1;
dt=lcd_out;
}
while(dt&0x80);
E=0;
}
//写控制指令
void write_command(uchar com)
{
check_busy();
E=0;
RS=0;
RW=0;
lcd_out=com;
E=1;
_nop_();
E=0;
delay(1);
}
//写数据指令
void write_data(uchar dat)
{
check_busy();
E=0;
RS=1;
RW=0;
lcd_out=dat;
E=1;
_nop_();
E=0;
delay(1);
}
/***** 液晶屏初始化*****/
void LCD_initial(void)
{
write_command(0x38); //8位总线双行显示 5*7的点阵字符
write_command(0x0C); //开整体显示,光标关,无黑块
write_command(0x06); //光标右移
write_command(0x01); //清屏
delay(1);
string(0x00,"ADC0809 ch0=");//显示字符串
string(0x40,"Voltage:");
}
//输出字符串
void string(uchar ad,uchar *s)
{
write_command(ad+0x80); //ad是显示位置信息
while(*s>0)
{
write_data(*s++);
delay(100);
}
}
//输出字符
void dis_char(uchar ad,uchar input)
{
write_command(ad+0x80);
write_data(input);
delay(10);
}
发现的问题
刚开始的时候,我在51里面用了除法,但是总是发现显示的结果有误差。
如下这段代码
//LCD显示信息void display_data(uchar input){
//提取ADC转换后的
dis_char(0x0d,input/100 + 0x30);
dis_char(0x0e,input/10%10 + 0x30);
dis_char(0x0f,input%10 + 0x30);
//将对应二进制码转换成对应的电压值
voltage = input * 19.53125;
dis_char(0x4a, voltage/1000 + 0x30);
dis_char(0x4b, voltage%1000/100 + 0x30);
dis_char(0x4c, voltage%100/10 + 0x30);
dis_char(0x4d, voltage%10 + 0x30);
dis_char(0x4e, 'm');
dis_char(0x4f, 'v');}
之前写成这样,显示一直有问题,我猜测是有数据溢出了,但是我把变量声明成了unsigned long int还是有问题,所以我百思不得其解。
//LCD显示信息void display_data(uchar input){
//提取ADC转换后的
dis_char(0x0d,input/100 + 0x30);
dis_char(0x0e,input/10%10 + 0x30);
dis_char(0x0f,input%10 + 0x30);
//将对应二进制码转换成对应的电压值
voltage = input * 5000 / 256;
dis_char(0x4a, voltage/1000 + 0x30);
dis_char(0x4b, voltage%1000/100 + 0x30);
dis_char(0x4c, voltage%100/10 + 0x30);
dis_char(0x4d, voltage%10 + 0x30);
dis_char(0x4e, 'm');
dis_char(0x4f, 'v');}
因为手里没有环境,是修改了发给朋友测试的,要不然我真想看看是什么原因,有同学知道的也帮忙说下