从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832

说在前面

上篇已经把流水灯、矩形键盘、电子时钟已经总结完了,今天来总结89E51的LCD1602液晶、ADC0809、DAC0832的相关内容

    • 说在前面
    • 一、基本原理介绍
    • 二、原器件介绍
    • 三、设计及接线
    • 四、流程框图
    • 五、程序
    • 六、项目设计总结
    • 七、最后找了两张实物图

一、基本原理介绍

  1. adc0809
    模数转换器即A/D转换器,或简称ADC,通常是指一个将模拟信号转变为数字信号的电子元件。通常的模数转换器是把经过与标准量比较处理后的模拟量转换成以二进制数值表示的离散信号的转换器。故任何一个模数转换器都需要一个参考模拟量作为转换的标准,比较常见的参考标准为最大的可转换信号大小。而输出的数字量则表示输入信号相对于参考信号的大小。
    模数转换器的种类很多,按工作原理的不同,可分成间接ADC和直接ADC。间接ADC是先将输入模拟电压转换成时间或频率,然后再把这些中间量转换成数字量,常用的有双积分型ADC。直接ADC则直接转换成数字量,常用的有并联比较型ADC和逐次逼近型ADC。
    并联比较型ADC:采用各量级同时并行比较,各位输出码也是同时并行产生,所以转换速度快。并联比较型ADC的缺点是成本高、功耗大。
    逐次逼近型ADC:它产生一系列比较电压VR,但它是逐个产生比较电压,逐次与输入电压分别比较,以逐渐逼近的方式进行模数转换的。它比并联比较型ADC的转换速度慢,比双分积型ADC要快得多,属于中速ADC器件。
    双积分型ADC:它先对输入采样电压和基准电压进行两次积分,获得与采样电压平均值成正比的时间间隔,同时用计数器对标准时钟脉冲计数。它的优点是抗干扰能力强,稳定性好;主要缺点是转换速度低。
    通过SST89E5162D单片机采集adc0809转换后的数字信号再将其送入lcd1602进行显示。使用C语言进行程序编写,确保程序正确后,通过keil进行程序烧录、性能调试,实现对可调电阻的电压值进行测量。

  2. DA转换输出正弦波、方波和三角波
    计算机处理的信息为数字量,被控制对象往往是采用一些连续变化的模拟量进行控制。 因此计算机输出和被控对象之间必须设置数字 /模拟转换,把数字量转换成模拟量,才能把 计算机与被控制对象连接起来。
    DAC0832结构和原理
    该功能由 SST89E5162D单片机及 DAC0832和UA741两部分组成。其中 DAC0832芯片为电流输出方式的转换芯片。所以它的输出必须接有实现从电流到电压的转换的运放电路。

二、原器件介绍

  1. ADC0809A/D是8路8位逐次逼近式A/D,每一个通道转换时间需要66到73个时钟脉冲,约100US。ADC0809是由多路模拟开关,通道地址锁存与译码器,8位A/D转换器以及三态输出数据锁存器等组成。
    ADC0809转换过程一般为先将任意一数写入需要转换的通道的地址启动该通道开始转换,当转换完成后EOC引脚会有一个信号传给单片机,如果EOC此时连接的是单片机控制口P3.2即外部中断0的触发口,则程序中会自动跳入外部中断0的中断程序,中断程序主要便是将所转换好的A/D值传给单片机,这样完成了一次A/D转换。ADC0809引脚图和逻辑框图:
    从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第1张图片从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第2张图片

  2. DAC0832是 8 位双缓冲 D/A转换器。 片内带有数据锁存器, 可与微处理器直接接口。 电流 输出,建立时间 1uS ,单电源 +5V~+15V, V REF 输入端电压 -10V<=VREF <=+1V,分辨率 8位, 功耗 20mW 。其管脚图为:
    从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第3张图片
    管脚说明:DI0~DI7:数据输入线。ILE:数据允许锁存信号,高电平有效;/CS:输入寄存器选择信号,低电平有效。/WR1为输入寄存器的写选通信号。输入寄存器的锁存信号/LE1由ILE 、/CS、/WR1的逻辑组合产生。当ILE 为高电平、/CS为低电平、/WR1输入负脉冲时,在/LE1产生正脉冲;/LE1为高电平,输入锁存器的状态随数据输入线的状态变化,/LE1的负跳变将数据线上的信息锁入输入寄存器。/XFER: 数据传送信号,低电平有效。/WR2为DAC寄存器的写选通信号。DAC寄存器的锁存信号/LE2,由/XEFR、/WR2的逻辑组合产生。当/XFER为低电平,/WR2输入负脉冲,则在/LE2产生正脉冲;/LE2为高电平是时,DAC寄存器的输出和输入寄存器的状态一致,/LE2负跳变,输入寄存器的内容打入DAC寄存器。VREF:基准电源输入引脚。Rfb :反馈信号输入引脚,反馈电阻在芯片内部。IOUT1、IOUT2:电流输出引脚。电流IOUT1、IOUT2的和为常数,IOUT1、IOUT2随DAC寄存器的内容线性变化。VCC:电源输入引脚。AGND:模拟信号地DGND:数字地。
    当 XFER 为低电平, WR2输入负脉冲时,则在 LE2产生正脉冲; LE2为高电平时, DAC 寄存器的输入与输出寄存器状态一致, LE2的负跳变, 输入寄存器内容存入 DAC 寄存器。 根据 对 DAC0832的输入锁存器和 DAC 寄存器的不同的控制方法, DAC0832 有如下三种工作方式:
    (1)单缓冲方式------此方式适用于只有一路模拟量输出或几路模拟量非同步输出的情形。方法是控制输入寄 存器同时接收数据,或者只用输入寄存器而把 DAC 寄存器接成直通方式
    (2)双缓冲方式------此方式适用于多个 DAC0832同时输出的情形。方法是先分别使这些 DAC0832的输入寄存 器接收数据,再控制这些 DAC0832同时传送数据到 DAC 寄存器以实现多个 D/A转换
    同步输出。
    (3)直通方式------此方式适用于连续反馈控制线路中。方法是:数据不通过缓冲器,即 WR1,WR2,
    XFER, CS 均接地, ILE 接高电平。此时必须通过 I/O 接口与微处理器连接,以匹配微处理器与 D/A 的转换。
    DAC0832的输出是电流型的。在控制系统中,通常需要电压信号,电流信号可以通过 运算放大器转换为电压信号。实验箱电路原理图如图 15-3所示。其中, 3J3:DAC0832的 8 位数字输入。 3J4:DAC0832 的一级放大模拟输出。 3J5:DAC0832 的二级放大模拟输出。 3J6, 3J7:将短路帽置于不同位置,表示在不同电阻、电容接法下输出滤波情况

  3. 1602LCD主要用来显示一些简单的字符,如字母与数字,当显示复杂的字符如汉字效果则不那么好。1602LCD引脚主要有RW,RS,E以及8位数据口,1602LCD的引脚图。LCD1602的四个时序图:当要读取LCD的状态时RW=1, RS=0,E=1;当要读取LCD的数据时RW=1,RS=1,E=1;当要向LCD中写入指令时RW=0,RS=0,E=1,随后E跳变为0;当要向LCD中写入数据时RW=0,RS=1,E=1,随后E跳变为0。
    从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第4张图片
    1602LCD读数据与读状态时序从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第5张图片
    1602LCD写数据与写指令时序
    从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第6张图片
    1602LCD液晶本身自带字符发生器,所以要写入一个字符只需知道它在字符发生器中的编号,一般都为该字符的ASCII码,图(2-4)为1602LCD字符对照表。此外1602LCD还有8个用户自定义字符区域,从00H到07H,00H对应范围是40H到47H,01H对应的是48H到55H,以此类推,07H对应的是78H到7FH,用户可往这些区域里写入字模,要用时直接调用00H到07H便可。
    液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,1602的内部显示地址。
    1602LCD字符对照表
    从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第7张图片
    1602LCD内部显示地址从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第8张图片

  4. UA741是高增益运算放大器,用于军事,工业和商业应用.这类单片硅集成电路器件提供输出短路保护和闭锁自由运作。这些类型还具有广泛的共同模式,差模信号范围和低失调电压调零能力与使用适当的电位
    引脚说明: 1和5为偏置(调零端),2为反相输入端,3为同相输入端,4接地,6为输出,7接电源 8空脚
    从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第9张图片

三、设计及接线

从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第10张图片

  1. AD转换LCD显示接口说明:
    LCD1602 D0-D7接单片机P1.0-P1.7
    RS-P2.0/RW-P2.1/EN-P2.2
    ADC0832 八位输出口接单片机P0.0-P0.7
    ST-P3.3/EOC-P3.2/OE-P3.4

  2. DA转换接口说明:
    DA数据口接单片机P1.0-P1.7
    CLK-ALE

四、流程框图

从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第11张图片
从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第12张图片
从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第13张图片

五、程序

  1. AD转换程序


1.        
#include<reg51.h>

#define uint unsigned int

#define uchar unsigned char

sbit sta=P3^3;

sbit eoc=P3^2;

sbit oe=P3^4;

sbit lcdrs=P2^0;

bit lcdrw=P2^1;

bit lcdoe=P2^2;

uchar code table1[]="Voltage!";

uchar code table2[]="(V)";

uchar tt0;

void delay(uint x)

{

uchar t;

while(x--) for(t=0;t<120;t++);

}

void timer0() interrupt 1

{

TH0=(65536-1000)/256;

TL0=(65536-1000)%256;

}

void write_com(uchar com)

{

lcdrs=0;

lcdoe=0;

P1=com;

lcdoe=1;

delay(5);

lcdoe=0;

delay(5);

}

void write_dat(uchar dat)

{

lcdrs=1;

lcdoe=0;

P1=dat;

lcdoe=1;

delay(5);

lcdoe=0;

delay(5);

lcdrw=0;

write_com(0x38);

write_com(0x0c);

write_com(0x06);

write_com(0x01);

write_com(0x84);

   for(i=0;i<8;i++)

   {

   write_dat(table1[i]);

   delay(5);

   }

   write_com(0x80+0x49);

   for(i=0;i<3;i++)

   {

   write_dat(table2[i]);

   delay(5);

   }

}

void display(uchar dat)

{

int votc; 

  votc=dat; 

 votc=dat*4640.0/256.0; 

 write_com(0x80+0x44); 

 write_dat(votc/1000+'0'); 

 write_com(0x80+0x45); 

 write_dat('.'); 

 write_com(0x80+0x46); 

 write_dat(votc/100%10+'0'); 



 write_com(0x80+0x47); 

 write_dat(votc/10%10+'0'); 

  write_com(0x80+0x48); 

 write_dat(votc%10+'0'); 

{

init_lcd();

TH0=(65536-1000)/256;

TL0=(65536-1000)%256;

TMOD=0x01;

EA=1;

ET0=1;

TR0=1;

while(1)

{

sta=0;

sta=1;

sta=0;

while(eoc==0);

oe=1;



display(P0);

oe=0;

}

}

  1. DA转换程序


#include<reg51.h> 

#include <absacc.h> 

#define uint unsigned int 

#define uchar unsigned char 

void  daly3(); 

void  daly2(); 

void  daly1(); 

void delay39us(); 

void delay10ms(); 

int k; 

uchar code sin[]={0x80,0x83,0x86,0x89,0x8D,0x90,0x93,0x96,0x99,0x9C,0x9F,0xA2,0xA5,0xA8,0xAB,0xAE,


    0xB1,0xB4,0xB7,0xBA,0xBC,0xBF,0xC2,0xC5,0xC7,0xCA,0xCC,0xCF,0xD1,0xD4,0xD6,0xD8,


    0xDA,0xDD,0xDF,0xE1,0xE3,0xE5,0xE7,0xE9,0xEA,0xEC,0xEE,0xEF,0xF1,0xF2,0xF4,0xF5,


    0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,


    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFD,0xFD,0xFC,0xFB,0xFA,0xF9,0xF8,0xF7,0xF6,


    0xF5,0xF4,0xF2,0xF1,0xEF,0xEE,0xEC,0xEA,0xE9,0xE7,0xE5,0xE3,0xE1,0xDF,0xDD,0xDA,


    0xD8,0xD6,0xD4,0xD1,0xCF,0xCC,0xCA,0xC7,0xC5,0xC2,0xBF,0xBC,0xBA,0xB7,0xB4,0xB1,


    0xAE,0xAB,0xA8,0xA5,0xA2,0x9F,0x9C,0x99,0x96,0x93,0x90,0x8D,0x89,0x86,0x83,0x80,


    0x80,0x7C,0x79,0x76,0x72,0x6F,0x6C,0x69,0x66,0x63,0x60,0x5D,0x5A,0x57,0x55,0x51,


    0x4E,0x4C,0x48,0x45,0x43,0x40,0x3D,0x3A,0x38,0x35,0x33,0x30,0x2E,0x2B,0x29,0x27,


    0x25,0x22,0x20,0x1E,0x1C,0x1A,0x18,0x16,0x15,0x13,0x11,0x10,0x0E,0x0D,0x0B,0x0A,


    0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,


    0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,


    0x0A,0x0B,0x0D,0x0E,0x10,0x11,0x13,0x15,0x16,0x18,0x1A,0x1C,0x1E,0x20,0x22,0x25,


    0x27,0x29,0x2B,0x2E,0x30,0x33,0x35,0x38,0x3A,0x3D,0x40,0x43,0x45,0x48,0x4C,0x4E,


    0x51,0x55,0x57,0x5A,0x5D,0x60,0x63,0x66,0x69,0x6C,0x6F,0x72,0x76,0x79,0x7C,0x7E};


void delay(uchar t)  

{ 

while(t--); 

} 

void zheng() 

{ 

 uint i; 

 for(i=0;i<=255;i++)  

 { 

   P1=sin[i]; 

delay39us(); 

 } 

} 

void fang() 

{  

P1=0; 

delay10ms(); 

P1=0xff; 

delay10ms(); 

} 

void sanjiao() 

{ uint i; 

for(i=0;i<255;i++)    

{ 

  P1=i; 

   daly2(); 

}   

for(i=255;i>0;i--)    

 { 

  P1=i; 

   daly2(); 

  } 

} 

void key() 

{  

    P0=0xf0; 

if(P0==0xe0) 

{delay(100); 

 if(P0==0xe0) 

  k=1;     

} 

else if(P0==0xd0) 

{delay(100); 

 if(P0==0xd0) 

  k=2;   

} 

else if(P0==0xb0) 

{delay(100); 

 if(P0==0xb0) 

  k=3;  

} 

  else k=0; 

} 

void main() 

{   

   while(1) 

  { 

    key(); 

if(k==1) 

  while(1) 

  { 

  zheng(); 

   key(); 

if(k!=0) 

break; 

  } 

else if(k==2) 

while(1) 

  { 

  fang(); 

   key(); 

if(k!=0) 

break; 

  } 

else if(k==3) 

 while(1) 

  { 

  sanjiao(); 

   key(); 

if(k!=0) 

break; 

  }      

  } 

 } 

void  daly1() 

{ 

{ 

 unsigned char a,b,c; 

 for(a=0;a<5;a++) 

 for(b=0;b<10;b++) 

 for(c=0;c<220;c++); 

}   

} 

void  daly2() 

   {   

unsigned char a; 

   for(a=10;a>0;a--); 

} 

void daly3()  

{ 

      unsigned char a;


       for(a=200;a>0;a--);


} 

 

void delay39us(void)     

{ 

   unsigned char a; 

   for(a=9;a>0;a--); 

} 

void delay10ms(void)     

{ 

   unsigned char a,b,c; 

   for(c=5;c>0;c--) 

       for(b=4;b>0;b--)


           for(a=248;a>0;a--);


}

六、项目设计总结

  1. 遇到的问题(这是以前做实验的时候遇到的问题,然后记录下来了)
    (1)LCD显示时在第一行“VOLTAGE!”出现单个字符乱码并不能显示测量读数
    故障原因及解决办法:代码中第一行的显示位为8个字符,在程序中设定为9个,更改数值即可;AD转换数据输出口与程序控制口不一致,更改即可
    (2)电路工作不稳定
    故障原因及解决办法:在焊接电路时没有合理安排布线问题,清查电路,排除电路粘连、虚焊等问题
    (3) LCD显示时在二行电压数值显示位置出现单个字符乱码。
    故障原因及解决办法:AD采样数值换算相应量程过程出现错误,在程序中更改换算公示即可
    (4) DAC0832模数转换的实验出现的方波正弦波频率未达到要求
    故障原因及解决办法:通过频率控制字,当频率控制字为1时,每次相位累加过程只是自加1,一个波形周期里面取了512个点,形成最后的波形。当频率控制字变为10时,每次相位累加都会变为nco=nco+10,相当于从原始的波形周期中等间隔取512/10个点,组合成一个新波形,频率自然比原来增加了10倍。频率调低的过程同理
    (5) DAC0832模数转换的实验,我了解到对于要实现的目的,首先要熟悉编程器件的状态工作特性,并且按照其工作时序图,合理安排不同端口赋值的顺序,最终才能顺利的完成数字量-模拟量的转换。其次在编程过程中,对于正弦波的输出,我直接应用了sin函数,结果总是出来不了正弦的波形,后来发现keil中的数给端口是不能为负的,然后我将其乘上一个数再加一个比它大的数,最终解决了这个小问题。

七、最后找了两张实物图

(前一个的图没找到、、、)

从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第14张图片
从51开始的单片机之旅(二)----LCD1602液晶、ADC0809、DAC0832_第15张图片

下一篇就总结模电的几个实验,能写得这么多是当时做的准备工作和课后总结的效果,我们每一次实验结束都要自己进行总结和讨论,我觉得这是一个很好的学习方式,看千遍不如做一遍,这个是真理,如果感觉这文章对你有所帮助,请在评论区留个爪

你可能感兴趣的:(单片机)