一、A-D转换器ADC0832的应用 1.功能原理 ADC0832 是美国国家半导体公司生产的一种8位逐次比较型COMS双通道A-D转换器。该器件有8和14引脚两种封装,采用5V电源供电,模拟电压输入范围为0~5V,内部时钟250kHz时转换速度为32μs。封装图见图7所示。 图7 ADC0832封装 由于ADC0832采用串行通信,占用单片机I/O资源少,一般用于简单的模拟电压检测系统中。引脚功能见表1。 表1 ADC0832引脚功能 ADC0832 与单片机的连接应为4条信号线,分别是/CS、CLK、DO、DI。由于DO端与DI端在通信时并不是同时有效,且与单片机的接口是双向的,所以应用中可以将ADC0832的DO和DI 线并在一起接单片机的I/O。见图8所示。 图8 ADC0832仿真电路 ADC0832未工作时,/CS端应为高电平,此时芯片被禁用,CLK 和DO/DI 的电平可任意。当要进行A-D转换时,须先将使能端/CS置于低电平,并且保持直到转换完全结束。开始转换工作时,由单片机向ADC0832的CLK 输入时钟脉冲,DO/DI端则使用输入通道功能选择的信号。在第1个时钟脉冲的下降沿DI端必须是高电平,表示启始信号。在CLK第2、3个脉冲下降沿DI端应输入两位数据,用于选择通道。当此两位数据分别为1、0时,只对CH0进行单通道转换;当两位位数据为1、1时,只对CH1进行单通道转换;当2位数据为0、0时,将CH0作为正输入端IN+,CH1作为负输入端IN-进行输入;当2位数据为0、1时,将CH0作为负输入端IN-,CH1作为正输入端IN+。 CLK第3个脉冲的下降沿来到之后,DI端的输入电平就失去作用,此后DO/DI端则开始利用数据输出DO进行转换数据的读取。从第4个脉冲下降沿开始,由DO端输出8位转换数据的最高位,随后每一个脉冲下降沿,DO端输出一位数据。直到第11个脉冲时送出最低位数据,完成一次A-D转换。 2. ADC0832应用 由于ADC0832操作简单,因此ADC0832驱动只需依照该器件的工作情况设计即可。在图8所示的仿真电路中,调节电位器OP1可以产生一个模拟的0~5V电压源,输入ADC0832的CH0端口,ADC0832转换后的数据范围为0~255,由3位数码管输出。ADC0832的DI与DO线与后接单片机的P3.2接口,/CS接P3.0接口,CLK接P3.1接口。为了得到CH0通道转换得到的数据,程序中需要在CLK第2、3个下降沿来到时向DI发送1、0,然后才能接收ADC0832的转换数据,每次转换结束时让/CS 无效。 本例程序分主程序和子程序两部分。子程序为ADC0832驱动程序,主程序主要显示转换的数据,用来验证子程序的正确性。 (1)ADC0832驱动程序 ADC0832驱动程序包含对ADC0832的初始化函数、读取ADC0832数据函数,在读取数据的函数中,要对所用的A-D通道进行选择。ADC0832的驱动程序如下: /*预处理*/ #include #include #define uchar unsigned char #define nop _nop_() sbit CS = P3^0; sbit CLK = P3^1; sbit DIDO = P3^2; /****对ADC0832初始化****/ void dac0832_init(void) { CS = 1;nop; CLK = 1; CS = 0; } /*****对转换CH0通道的模拟信号*****/ uchar dac0832_ch0(void)//包含11个CLK下降沿 { uchari,dat1; dac0832_init(); DIDO= 1;CLK = 0;nop;CLK = 1;nop;//SCK第1个下降沿来到时,DI = 1启动DAC0832 DIDO= 1;CLK = 0;nop;CLK = 1;nop;//SCK第2个下降沿 DIDO= 0;CLK = 0;nop;CLK = 1;nop;//SCK第3个下降沿,发送1、0选择通道ch0 DIDO= 1;//释放总线 for(i= 0;i <>第4个下降沿到第11个下降沿, { CLK = 0;nop; if(DIDO)dat1 =dat1 | 0x01; CLK = 1;nop; dat1 = dat1<> } return(dat1); CS= 1; } (2)主程序 主程序需要显示A-D转换器对模拟信号转换后的数据,因此要用到数码管动态显示程序,具体程序如下: /*预处理*/ #include #include #include'ADC0832.c' #define uchar unsigned char code uchar seven_seg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; uchar cp1,cp2,dat_ad; /*T0初始化*/ void timer0_init(void) { TMOD = 0x01; TH0 = 0xec; TL0 = 0x78; TR0 = 1; EA = 1; ET0 = 1; } /*T0中断服务*/ void timer0_isr(void) interrupt 1 //中断服务函数 { TH0 = 0xec; TL0 = 0x78; cp1++; if(cp1 >= 100) //0.5秒 { cp1 = 0; dat_ad =dac0832_ch0();//0.5秒让ADC0832转换一次 } P0 = 0xff; switch(cp2) { case0:P0 = seven_seg[dat_ad % 10];P2 =0x01;break; case1:P0 = seven_seg[dat_ad % 100 / 10];P2 = 0x02;break; case2:P0 = seven_seg[dat_ad / 100];P2 = 0x04;break; } cp2++; if(cp2 >= 3) cp2 = 0; } /*主函数*/ void main(void) { timer0_init(); dac0832_init(); while(1); } 在子程序的基础上,改变CLK第2、3下降沿到来时输入的DI数值,可以实现CH1通道数据转换。作为单通道模拟信号输入时,ADC0832的输入电压是0~5V, 8位分辨率,电压精度为19.53mV。如果由IN+与IN-输入时,可将电压值设定在某一个较大范围之内,从而提高转换的宽度。值得注意的是,在进行IN+与IN-的输入时,如果IN-的电压大于IN+的电压,则转换后的结果始终为00H。 二、A-D转换器TLC549的应用 1. TLC549工作原理 TLC549有片内系统时钟,该时钟与I/O_CLOCK是独立工作的,无须特殊的速度或相位匹配。TLC549工作时序如图9所示。 图9 TLC549工作时序图 当CS为高时,数据输出(DATA _OUT)端处于高阻状态,此时I/O_CLOCK不起作用。这种CS控制作用允许在同时使用多片TLC549时,共用I/O_CLOCK,以减少多路A-D转换器并用时占用的单片机I/O资源。TLC549一次转换操作过程如下: (1)将CS置低。内部电路在测得CS下降沿后,再等待两个内部时钟上升沿和一个下降沿后,然后确认这一变化,最后自动将前一次转换结果的最高位(D7)位输出到DATA_OUT端上。 (2)前四个I/O_CLOCK周期的下降沿依次移出第2、3、4和第5位(D6、D5、D4、D3),片上采样保持电路在第4个I/O_CLOCK下降沿开始采样模拟输入。 (3)接下来的3个I/O_CLOCK周期的下降沿移出第6、7、8(D2、D1、D0)个转换位。 (4)最后,片上采样保持电路在第8个I/O_CLOCK周期的下降沿将移出第6、7、8(D2、D1、D0)个转换位。保持功能将持续4个内部时钟周期,然后开始进行32个内部时钟周期的A-D转换。第8个I/O_CLOCK后,CS必须为高电平,或I/O_CLOCK保持低电平,这种状态需要维持36个内部系统时钟周期,以等待保持和转换工作的完成。如果CS为低时I/O_CLOCK上出现一个有效干扰脉冲,则微处理器/控制器将与器件的I/O时序失去同步;若CS为高时出现一次有效低电平,则将使引脚重新初始化,从而脱离原转换过程。 在36个内部系统时钟周期结束之前,实施步骤(1)~(4),可重新启动一次A-D转换,正在进行的转换终止,此时的输出是前一次的转换结果而不是正在进行的转换结果。 若在特定的时刻采样模拟信号,应使第8个I/O_CLOCK时钟的下降沿与该时刻对应,因为芯片虽在第4个I/O_CLOCK时钟下降沿开始采样,却在第8个I/O_CLOCK的下降沿开始保存。 2.TLC549应用子程序 (1)测试电路 TLC549可方便地与具有串行外围接口(SPI)的单片机或微处理器配合使用,也可与MCS-51系列通用单片机连接使用。为了验证TLC549驱动程序的可靠性,可以在ADC0832应用电路显示部分基础上连接TLC549,TLC549与MCS-51系列单片机的接口如图10所示。其中TLC549的CS、DATA_OUT(SDO)、I/O_CLOCK分别连接单片机的P3.4、P3.5、P3.7接口。模拟电压利用一个电位器OP1产生,当调节电位器中心抽头的位置时,模拟电压变换范围我0~5V,经过TLC549转换后的8位数据通过串行传输方式给单片机,单片机显示数据范围为0~255,为了得到一个电压数字检测目的,本例中使数码管显示电压值,共通过程序计算得到检测结果。 图10 TLC549与AT89C51单片机的接口电路 (2)TLC549子程序 TLC549程序依照TLC549的时序和操作过程设计,包含器件初始化函数和数据转换函数,具体程序如下: /*预处理*/ #include #define uchar unsigned char sbit sd = P3^5; //数据线 sbit cs = P3^4; //片选 sbit scl = P3^7; //I/O口时钟 /*对TLC549初始化*/ void tlc549_init(void) { cs= 1; //初始化,启动 scl = 0; cs = 0; } /*对TLC549数据转换*/ uchar tlc549_ad(void) //TLC549处理 { uchar i,dat_temp = 0; tlc549_init(); for(i = 0;i < 8;i++)="">读取采集数据,读取的是上一次采集数据 { scl= 1; dat_temp= dat_temp <> if(sd)dat_temp|= 0x01; scl= 0; } cs = 1; return(dat_temp); } (3)主程序 /*预处理*/ #include #include'TLC549.c' #define uchar unsigned char #define uint unsigned int code uchar seven_seg[] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; uchar cp1,cp2; uint dat_ad; /*T0初始化*/ void timer0_isr(void) interrupt 1 //timer0中断服务函数 { TL0= (65536 - 5000) % 256; TH0= (65536 - 5000) / 256; cp1++; if(cp1>= 100) //0.5秒 { cp1= 0; dat_ad= tlc549_ad(); dat_ad= dat_ad * 1.96;//数据255对应模拟电压5V } P0= 0xff;//仿真时用于消隐 switch(cp2) { case0: P0 = seven_seg[dat_ad % 10];P2 = 0x01; break; case1: P0 = seven_seg[dat_ad / 10 %10];P2 = 0x02; break; case2: P0 = seven_seg[dat_ad / 100]&0x7f;P2= 0x04; break;//加上小数点 } cp2++; if(cp2>= 3) cp2= 0; } /*T0中断服务函数*/ void timer0_init (void) //timer0中断初始化函数 { TMOD= 0x01; TL0= (65536 - 5000)%256; TH0= (65536 - 5000)/256; ET0= 1; EA= 1; TR0= 1; } /*主函数*/ void main(void) //主程序 { timer0_init(); tlc549_init(); while(1); } 由于TLC549只有1路A-D转换器,因此程序相比DAC8032简单一些。以上两种A-D转换芯片都是串行接口,减少了器件与MCU之间的连线数,同时占用了较少的单片机I/O资源,缺点是比同类并行A-D转换器速度慢。A-D转换器的时序比较简单,因此程序设计有较大的灵活性。 三、D-A转换器TLC5615的应用 1.TLC5615工作时序 TLC5615的工作时序如图11所示。从图中可以看出,只有当片选端CS为低电平时,串行输入数据才能被移入16位TLC5615移位寄存器,期间每一个SCLK时钟的上升沿将 DIN的一位数据移入移位寄存器。注意,先发送数据的最高位。10位数据发送完毕后,CS的上升沿将16位移位寄存器的10位有效数据锁存于10位DAC寄存器,供DAC电路进行转换;当片选端CS为高电平时,数据禁止发送。注意,CS的上升和下降都必须发生在SCLK为低电平期间。 图11 TLC5615工作时序 TLC5615有两种工作方式。第一种为单片工作方式,16位移位寄存器分为高4位虚拟位、低2位填充位以及10位有效位。单片TLC5615工作时,只需要向16位移位寄存器按先后发送10位有效数据位和低2位填充位,2位填充位数据任意。单芯片应用时,发送数据需要12个SCLK脉冲。 第二种方式为级联方式,将一片TLC5615的DOUT接到下一片TLC5615的DIN,需要向16位移位寄存器按先后输入高4位虚拟位、10位有效位和低2位填充位,由于增加了高4位虚拟位,所以需要16个SCLK脉冲。 2.应用程序 (1)仿真测试电路 图12所示为TLC5615与单片机的连接电路,通过编辑Ptoteus仿真电路,可以验证TLC5615的应用程序。图12中TLC5615的/CS、DIN、SCLK分别连接单片机的P3.4、P3.6、P3.7接口。TLC5615转换输出的模拟电压信号可以通过电压表测试。基准电压REFIN接电源电压5V的一半,当TLC5615接收10位数据全为1时,理论上,OUT端输出电源电压5V,但实际应用时最高输出4.7V。即当TLC5615输入数据超过961时,输出电压将不再增加。因此在设计TLC5615应用程序时需要调整输入数据范围。 图12 TLC5615与单片机的连接电路 (2)应用程序 下面编写TLC5615应用程序来完成一个随时间变化的数据转换,同时数据在数码管上显示出来。具体程序如下: /*预处理*/ include #include #define uchar unsigned char #define uint unsigned int const uchar seven_seg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; uchar j; uint moni,dat,i; sbit din = P1^5; sbit scl = P1^1; sbit cs = P1^6; tlc5615_init(void) { cs = 1; scl = 0; cs = 0; } /* TLC5615转换函数*/ void tlc5615(uint dat) //由于TLC5615是十位转换,定义一个16位的变量 { uchar i; dat <= 6;="">=>两个字节有十六位,去掉高六位剩下十位有效位 tlc5615_init();//初始化 for(i = 0;i < 12;i="">要送的只有十位数但是后面要跟着多加两位零才能将一个数据送出去 { din = (bit)(dat& 0x8000); scl = 1; //前面一句亦可用DA= CY来代替,但后面的顺序要调换才行 dat <=>=> scl = 0; } cs = 1; scl = 0; } /* T0初始化函数*/ void timer0_init(void) { TMOD = 0x01; TL0 = (65536-2000) % 256; TH0 = (65536-2000) / 256; TR0 = 1; ET0 = 1; EA = 1; } /* T0中断服务函数*/ void timer0_isr() interrupt 1 //T0的中断处理函数,用于显示输出的电压值 { TL0 = (65536-2000) % 256; TH0 = (65536-2000) / 256; i++; if(i >= 500)//0.5秒 { i = 0; tlc5615(dat); if(dat >= 962) dat = 0; moni = dat * 0.489; dat = dat + 10; } P0 = 0xff; switch(j) { case 0 : P0 =seven_seg[moni %10];P2 = 0xfe;break; case 1 : P0 =seven_seg[moni / 10 % 10];P2 = 0xfd;break; case 2 : P0 =seven_seg[moni / 100] & 0x7f;P2= 0xfb;break; } j++; if(j >= 3) j = 0; } /*主函数*/ void main() { timer0_init(); while(1); } A-D、D-A转换器类型很多,由于准确度要求较高,此类器件价格长期居高不下。为了提高性价比,个别单片机芯片把A-D、D-A转换器集成在内部,如STC单片机内集成了8通道的A-D转换器,从而增加器件的性价比。在A-D、D-A转换器应用中,由于它们多数没有涉及芯片指令,程序设计只需按时序发送或接收数据即可,特别是并行接口A-D、D-A器件的程序设计更加简单,这为数字系统设计带来很大的方便。 由于篇幅所限,本文只提供了三个实例,更多内容请关注公众号:机械工业出版社E视界。 公众号中回复“1217”即可获取下载链接,查看该部分内容的全部实例。 |
|