一、前言介绍
- 这个博客主要说明ADC0804的使用
- 数码管的动态显示作为辅助功能,方便观察
- 利用滑变和5V电源来获得一个输入电压值,输入到ADC0804的输入端
二、ADC0804芯片的介绍
1、A/D转换概念
即模数转换,输入模拟量(比如电压信号),输出一个与模拟量对应的数字量(常为二进制形式)。例如参考电压VREF为5V,采用8位的模数转换器时,当输入电压为0V时,输出的数字量为0000 0000,当输入的电压为5V时,输出的数字量为1111 1111.当输入的电压从0V到5V变化时,输出量从0000 0000到1111 1111变化。这样每一个输入电压值对应一个输出数字量,即实现模数转换。
2、分辨率概念
分辨率是指使输出数字量变化1时的输入模拟量,也就是使输出数字量变化一个相邻数码所需输入模拟量的变化值。
分辨率与A/D转换器的位数有确定的关系,可以表示成FS/2^n。FS表示满量程输入值,n为A/D转换器的位数。例如对于5V的满量程,采用4位的ADC时,5V/16=0.3125V(也就是说当输入的电压值每增加0.3125V,输出的数字量增加1);采用8位的ADC时,分辨率为5V/256=19.5mV(也就是说当输入的电压每增加19.5mV,则输出的数字量增加1);当采用12位的ADC时,分辨率则为5V/4096=1.22mv(也就是说当输入的电压每增加1.22mV,则输出的数字量增加1)。显然位数越多,分辨率越高。
3、ADC0804引脚功能
- CS:芯片片选信号,低电平有效。即CS = 0时,该芯片才能正常工作,高电平时芯片不工作。在外接多个ADC0804芯片时,该信号可以作为选择地址使用,通过不同的地址信号使用不同的ADC0804芯片,从而可以实现多个ADC通道的分时复用。
- WR:启动ADC0804进行ADC采样,该信号低电平有效,即WR信号由低电平变成高电平时,触发一次ADC转换。
- RD:低电平有效,即RD=0时,ADC0804把转换完成的数据加载到DB口,可以通过数据端口DB0~DB7读出本次的采样结果。
- VIN(-)和VIN(+):模拟电压输入端,单边输入时模拟电压输入接VIN(+)端,VIN(-)端接地。双边输入时VIN(+)、VIN(-)分别接模拟电压信号的正端和负端。当输入的模拟电压信号存在“零点漂移电压”是,可在VIN(-)接一等值的零点补偿电压,变化时自动从VIN(+)中减去这一电压。
- VREF/2:参考电压接入引脚,该引脚可外接电压也可悬空,若外接电压,则ADC的参考电压为该外接电压的两倍,如不接,则VREF与VCC公用电源电压,此时ADC电压即为电源电压VCC的值。
- CLKIN和CLKR:外接RC振荡电路产生模数转换器所需的时钟信号,时钟频率CLK=1/1.1RC,一般要求频率范围100KHz~1460KHz。
- AGND和DGND:分别接模拟地和数字地。
- INTR:转换结束输出信号,低电平有效,当一次A/D转换完成后,将引起INTR=0,实际应用时,该引脚应与微处理器的外部中断输入引脚相连(如51单片机的INT0,INT1脚),当产生INTR信号有效时,还需等待RD=0才能正确读出A/D转换结果,若ADC0804单独使用,则可以将INTR引脚悬空。
- DB0~DB7:输出A/D转换后的8位二进制结果。
4、ADC0804的时序
https://wenku.baidu.com/view/823c5913964bcf84b9d57b78.html
三、仿真图
四、程序
- 输入一个电压
- 模拟电压转换后放大100倍
- 通过数码管显示(四位一体共阴极)
#include <reg52.h>
#include <intrins.h>
unsigned char code dxcode[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char dispbuf[4];
sbit adcs = P2^4;
sbit adrd = P2^5;
sbit adwr = P2^6;
sbit intr = P2^7;
sbit CLK = P3^3;
sbit P20=P2^0;
sbit P21=P2^1;
sbit P22=P2^2;
sbit P23=P2^3;
sbit P17=P1^7;
void TimeInitial();
void Delay(unsigned int i);
void Display();
void main()
{
int intnum = 0; //转换电压值
unsigned char x = 0; //存储P0口的数值
TimeInitial();
while(1)
{
adcs = 0; //芯片有效
adwr = 0; //启动ADC0804进行ADC采集
_nop_(); //延时片刻
adwr = 1; //高电平变低电平触发一次ADC转换
while(intr); // ADC转换完成后intr = 0
P0 = 0xff;
adcs = 0;
adrd = 0; //rd为低电平将转换结果加载到DB口
_nop_();
x = P0; //读取结果
adrd = 1;
intnum = x * (1.0/255)*500; //读取的电压扩大100倍
dispbuf[0] = 0;
dispbuf[1] = intnum % 10;
dispbuf[2] = intnum / 10 %10;
dispbuf[3] = intnum / 100;
Display();
}
}
void Display()
{
P1 = dxcode[dispbuf[3]];
P20 = 0;
P21 = 1;
P22 = 1;
P23 = 1;
Delay(10);
P1 = 0x00;
P1 = dxcode[dispbuf[2]];
P20=1;
P21=0;
P22=1;
P23=1;
Delay(10);
P1=0x00;
P1=dxcode[dispbuf[1]];
P17=1;
P20=1;
P21=1;
P22=0;
P23=1;
Delay(10);
P1=0x00;
P1=dxcode[dispbuf[0]];
P20=1;
P21=1;
P22=1;
P23=0;
Delay(10);
P1=0x00;
}
//定时器产生振荡信号给ADC提供时钟信号
void TimeInitial()
{
TMOD=0x10; //定时器方式1
TH1=(65536-200)/256;
TL1=(65536-200)%256;
EA=1;
ET1=1;
TR1=1;
}
void Delay(unsigned int i)
{
unsigned int j;
for(;i>0;i--)
{
for(j=0;j<125;j++)
{;}
}
}
void t1(void) interrupt 3 using 0
{
TH1=(65536-200)/256;
TL1=(65536-200)%256;
CLK=~CLK;
}
参考https://wenku.baidu.com/view/823c5913964bcf84b9d57b78.html