模拟信号经过A/D转换成数字信号后,才能通过软件进行处理,所有这些都是通过A/D转换器(ADC)来实现的。模数转换对应于数模转换。数模转换是模数转换的逆过程。模拟)到数字(Digital)转换电路将模拟信号转换为相应的数字信号,送至微机进行处理。这是一个完整的信号链,而模数转换过程就是我们经常接触到的ADC电路。
模数转换原理:
ADC的转换原理根据ADC的电路形式不同。 ADC电路通常由两部分组成,它们分别是:采样、保持电路和量化、编码电路。其中,量化和编码电路是最核心的部件,任何ADC转换电路都必须包含这种电路。 ADC电路的形式有很多种,通常可以分为两大类:
间接法:将采样保持模拟信号转换为与模拟量成正比的时间或频率两个模拟信号如何同时输入到单片机,再转换为数字量。这通常是时钟脉冲计数器,也称为计数器类型。其工作特点是:工作速度低,转换精度高,抗干扰能力强。
直接法:将参考电压与采样保持信号进行比较,从而将其转换为数字量。其工作特点是:工作速度快,转换精度容易保证。
模数转换的过程:
有四个阶段,即采样、保持、量化和编码。
采样是将连续时间信号转换为离散时间信号的过程。采样后,时间连续、数值连续的模拟信号变成时间离散、数值连续的信号,称为采样信号。采样电路相当于一个模拟开关,模拟开关周期性工作。理论上,在每个周期中,模拟开关的闭合时间接近于0。在模拟开关闭合的那一刻(采样时刻),我们“采样”了一个模拟信号的“样本”。
量化是将连续数字信号转换为离散数字信号的过程。理论上,量化后,我们可以将时间离散、数值连续的采样信号转化为时间离散、数值离散的数字信号。
我们知道,在电路中,数字量通常用二进制代码表示。因此,量化电路后面有一个编码电路,将数字信号的数值转换成二进制码。
但是量化和编码总是需要一定的时间才能完成,所以在量化电路前面还有一个保持电路。保持是将时间离散的、数值连续的信号变为时间连续的、数值离散的信号的过程。在量化和编码过程中,保持电路充当恒压源,在量化器输入端的采样时刻“保持”信号电压。虽然逻辑保持器是一个独立的单元,但工程保持器总是与采样器一起完成。两者统称为采样保持。
关于8位串行A/D转换器ADC0832:
ADC0832是8针双列直插双通道A/D转换器,可分别转换两个模拟信号实现模数转换,可用于单端输入模式和差分模式. ADC0832采用串行通讯方式,通过DI数据输入端进行通道选择、数据采集和数据传输。 8位分辨率(更高分辨率可达256级),可以适应一般的模拟转换要求。其内部电源输入和参考电压的复用,使得芯片的模拟电压输入在0~5V之间。具有双数据输出,可作为数据校验,减少数据错误,转换速度快,稳定性强。独立芯片使能输入,多设备连接和处理器控制更方便。
ADC0832 特性:
· 8 位分辨率;
·双通道A/D转换;
· 输入输出电平兼容TTL/CMOS;
· 5V电源供电时输入电压在0~5V之间;
· 工作频率250KHZ,转换时间32μS;
· 一般功耗只有15mW;
· 8P、14P—DIP(双列直插)、PICC封装; 0°C至+70°C,工业级芯片温度范围为-40°C至+85°C;
ADC0832管脚图
p>
芯片接口说明:
· CS_片选使能,低电平芯片使能。
· CH0 模拟量输入通道0,或用作IN+/-。
· CH1 模拟输入通道1,或用作IN+/-。
· GND 芯片参考零电位(地)。
·DI数据信号输入,选择通道控制。
·DO数据信号输出,转换后的数据输出。
· CLK 芯片时钟输入。
· Vcc/REF电源输入和参考电压输入(复用)
ADC0832的工作原理:
一般情况下,ADC0832与单片机的接口应该是4条数据线,即CS、CLK、DO、DI。但是,由于DO和DI端子在通信时不是同时使用的,而且与单片机的接口是双向的,所以当I/O口资源紧张时,DO和DI可以在一条数据线上并行使用。 ADC0832不工作时,其CS输入端应为高电平,此时芯片禁用,CLK和DO/DI的电平可以任意。进行A/D转换时,必须将CS使能端置于低电平并保持低电平,直到转换完成。此时芯片开始转换,同时处理器向芯片时钟(CLK)输入端输入时钟脉冲,DO/DI端通过DI端输入通道选择的数据信号功能。在一个时钟脉冲下沉之前,DI 端必须为高电平,表示一个启动信号。在二、第三个脉冲下沉前,需向DI端子输入两位数据,选择通道功能。
表1:通道地址设置表
如表1所示,当两位数据为“1”、“0”时,仅对CH0进行单路转换。当两位数据为“1”、“1”时,仅对CH1进行单路转换,当两位数据为“0”和“0”时,以CH0作为正输入端IN+,CH1作为负输入端IN-进行输入。当这两位数据分别为“0”和“1”两个模拟信号如何同时输入到单片机,以CH0作为负输入端IN-,CH1作为正输入端IN+进行输入。第三个脉冲下降后,DI端的输入电平失去输入功能,然后 DO/DI 端开始使用数据输出 DO 读取转换后的数据,从第 4 个脉冲的下降沿开始,从 DO 端输出转换数据的最高位 Data7,然后 DO 端输出每个脉冲下降沿的下一位数据。直到第11个脉冲,最低位数据Data0被送出,完成一个字节的数据输出。也是从这个位表示输出下一个相反字节的数据,即从第 11 个字节的下降沿输出 Data0。然后输出8位数据,在第19个脉冲完成数据输出,也标志着一次A/D转换的结束。最后将CS置为高电平,关闭芯片,直接处理转换后的数据。时序说明请参考图4。
作为单通道模拟信号输入时,ADC0832的输入电压为0-5V,8位分辨率下的电压精度为19.53mV,即(5/256)@ > V. 如果用IN+和IN-作为输入输入,电压值可以设置在一定的较大范围内,从而增加转换的宽度。但值得注意的是,当IN+和IN的输入- 执行,如果IN-电压大于IN+电压,则转换后的数据结果始终为00H。
ADC0832的工作时序
ADC0832软硬件设计实例
经过以上理论学习,你应该对模数转换有了一定的了解。接下来根据以上指导,将ADC0832实际应用,加深印象。本例的作用是在LED数码管上显示通道1采样的电压,通过改变通道1的输入电压来观察输出读数。
硬件示意图
软件流程图
STC单片机相关程序:
#include //定义的系统头文件和全局变量
#包括
#define uchar unsigned char
#define uint unsigned int
#define DogReset() WDT_CONTR=0x35
// T1 时序 0.1ms.用作系统计时,
#define vT01ms 2
#define vT10ms 10
#define vT100ms 10
#define vT01S 100 // 1 秒 = 10 毫秒 * 100
#define vT0HVal 0xfe //0xff //0xfe / /0xf6
#define vT0LVal 0x33 //0x9c //0x0c //0x4c
uchar 码 display_AD_channel_ID[2] = {0x00, 0x01};
静态无符号字符数据 CS;
uchar 数据 AD_channel_result[2][5]; //每个通道的A/D转换结果。前面是频道号;后面是转换后的值
uint cT01ms;
uchar cT10ms;
uchar cT100ms;
uchar cT01s;
uchar THTL;
位OutFlag;
void delay_ms(register uint Count){
注册uchar T;
for(;Count 》0;Count–){
对于(T=0;T<80;T++){
_nop_(); _nop_(); _nop_(); _nop_() ; _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
}
DogReset() ;
}
}
void send_char_com(unsigned char OutData){
SBUF = 输出数据; //输出字符
while(!TI); //空语句判断字符是否发送出去
TI = 0; //清除TI
}
void send_string_com(uchar *str, uchar strlen){
uchar i;
for(i=strlen;i>0;i–){
send_char_com(*str);
p>
str++;
DogReset();
}
}
uchar Ad_Change(uchar 频道){
uint AD_Result_Temp = 0 ;
//——————— put P1.0– P1.1 设置为适合的模式广告转化
/// P1 = 0xff; //将P1口置高,准备A/D转换
ADC_CONTR = ADC_CONTR|0x80; //1000, 0000 打开A/D转换电源
P1M0 = 0x03; //0000, 0011 P1.x口用于A/D转换,先设为开漏
P1M1 = 0x03; //0000, 0011P1.0–P1.1 设置为先开漏。断开内部上拉电阻
delay_ms (20); //20
ADC_CONTR = ADC_CONTR&0xE0; //1110, 0000 清除ADC_FLAG、ADC_START位及低3位
ADC_CONTR = ADC_CONTR|(display_AD_channel_ID[channel]&0x07); //设置当前通道号
delay_ms(1); //延迟使输入电压稳定
ADC_DATA = 0; //清除A/D转换结果寄存器
ADC_LOW2 = 0;
ADC_CONTR = ADC_CONTR|0x08; //0000 , 1000ADCS=1, 开始转换
做{ DogReset();}
while((ADC_CONTR & 0x10)==0); //0001 , 0000 等待A/D转换结束
ADC_CONTR = ADC_CONTR&0xE7; //1110, 0111 清除ADC_FLAG位,停止A/D转换
AD_Result_Temp = ((AD_Result_Temp|ADC_DATA) “< 2)|(ADC_LOW2&0x03);
//保存并返回AD转换结果
//—————————- 转换成串口可以显示的字符
AD_channel_result[通道][0] = AD_Result_Temp/1000+0x30;
AD_channel_result[通道][1] = (AD_Result_Temp00)/100+0x30;
AD_channel_result[channel][2] = (AD_Result_Temp0)/10+0x30;
p>
AD_channel_result[通道][3] = AD_Result_Temp+0x30;
//———— 串口监视器
// send_char_com (ADC_DATA); //////发送转换后的值,这里只有高8位,需要考虑值的转换
// send_char_com(ADC_LOW2); ///// /发送转换后的值,这里只有低2位,需要考虑值的转换
// send_string_com(AD_channel_result[频道], 4);
delay_ms(10); //
返回(ADC_DATA);
}
uchar AD_Filter(void){
uchar i;
uchar cTemp[32];
uchar cAverage;
for(i=32;i”0;i–){
cTemp[i]=Ad_Change(0);
cAverage=((cAverage+cTemp[i])”>1);
}
return(cAverage);
}
void InitCom(unsigned char BaudRate){
开关(波特率){
案例 1:THTL = 64;休息; //波特率300
案例 2:THTL = 160;休息; //600
案例 3:THTL = 208;休息; //1200
案例 4:THTL = 232;休息; //2400
案例 5:THTL = 244;休息; //4800
案例 6:THTL = 250;休息; //9600
案例 7:THTL = 253;休息; //19200
案例 8:THTL = 255;休息; //57600
默认值:THTL = 208;休息; //1200
}
}
void Chip_initial(void){
IE=0;
//定时器控制字初始化
TMOD=0x21; // 定时器1为模式2,定时器0为模式1
TCON=0x50; // 设置外部中断类型
p>
T2CON=0x0d; // 选择定时器1作为波特率发生器,T2作为捕捉模式
// ET2=1;
ET0=1 ; // 启用定时器 0、定时器 2 中断
//外部中断设置
EX0=0; // FFSK中断最初是关闭的,当有载波Enable时重新启动
EX1=0;
IT1=1; // 外部中断0、1都是下降沿触发
IT0=1;
//启动定时器0
TH0=vT0HVal; // 启动定时器 0
TL0=vT0LVal;
TR0=1 ;
InitCom(6)@>; //设置波特率为9600 1-7 波特率300-19200
SCON = 0x50; //串口模式1,允许接收
TH1 = THTL;
TL1 = THTL;
PCON = 0x80; //波特率倍增控制,SMOD位
RI = 0; //清除收发标志
TI = 0;
TR1 = 1; //启动定时器
IP=0x02; //PT2=1
IPH=0x02; //PT2H=1, PT0H=1
EA=1;
delay_ms(10) ; // 延迟是为了避免定时器0不能产生中断的问题
}
void Para_initial(void){
OutFlag=0;
p>
cT01ms = vT01ms;
cT10ms = vT10ms;
// cT100ms = vT100ms;
cT01s = vT01S;
CS = 0; //设置CS为0,不选择任何音源,如果为1,选择第一个声道
}
void system_initial(void){
Chip_initial();
para_initial();
DogReset(); // 针对STC89C58RD+.06-04-06修改
}
空主(空){
system_initial();
而(1){
DogReset();
如果(OutFlag){
p>
OutFlag=0;
send_char_com(AD_Filter());
}
}
}
void Trint0(void) 使用 1{ 中断 1{
TR0=0; // 时基 1mS
TH0=vT0HVal;
TL0=vT0LVal;
TR0=1;
TF0=0;
如果(!(–cT01ms)){
cT01ms=vT01ms;
if(!(–cT10ms)){
cT10ms=vT10ms;
if(!(–cT01s)){
cT01s=vT01S;
OutFlag=1;
}
}
}
}
void ComInINT (void) 中断 4 {
if (RI) { //判断是不接受结束符
开关(SBUF){
案例 0x61: CS = 1;休息; //根据SBUF设置CS接收’abcde’,方便调试
案例 0x62: CS = 2;休息;
案例 0x63: CS = 3;休息;
案例 0x64: CS = 4;休息;
案例 0x65: CS = 0;休息;
}
P1 = 255; //P1口均为高电平,4-7反低不选择音源,0-3为高电平读键
RI = 0; //RI被清除
}
}
请登录后发表评论
注册
社交帐号登录