晚上给个朋友在51上调ADC0808芯片

嵌入式Linux

共 4267字,需浏览 9分钟

 ·

2022-06-21 13:14

今天有个同学跟我说,自己在51上调试ADC芯片,但是显示一直不正常,然后晚上帮忙看了下,也做下记录,也不是很难的东西,不过还是要记录下比较好。

ADC0808

这个是一个8位的ADC芯片,输入0~5V,转成数字数字是0~255。

8位ADC可以把5V数据等分255份,这是关键

我们做个假设,如果我们输入 1250MV,通过公式计算,输出的数字量应该是

我们得到64这个数字量后,需要再转换成电压给显示出来

ADC0808的电路介绍

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');}

因为手里没有环境,是修改了发给朋友测试的,要不然我真想看看是什么原因,有同学知道的也帮忙说下

正确显示但有误差


正确显示但有误差


有个需要讨论的问题是
8位ADC芯片,我们在计算的时候,是使用256 还是255呢?



如果大家在做ADC芯片的调试的时候,记得注意哦
8位对应的是 2的8次方,也就是256,但是256表示的是我们把一个数据分成了255份。
当然,如果描述不正确,可以指正出来,我在调试的时候,把256修改成255之后,计算误差立竿见影的减小了。


浏览 85
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报