基于单片机简易数字电压表的设计

更新时间:2024-06-01 11:20:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

目录

1. 摘要及关键词-------------------------------------------3 2. 总体设计方案-------------------------------------------3 3. 硬件电路及仿真设计------------------------------------10 4. 程序设计及调试----------------------------------------12 5. 本人承担的小组工作以及设计体会------------------------13 6. 参考文献----------------------------------------------13 7. 元器件清单及程序清单----------------------------------13

摘要:

本次设计主要由三个模块组成:A/D转换模块,数据处理模块及显示模块。A/D转换主要由芯片ADC0809来完成,它负责把采集到的模拟量转换为相应的数字量在传送到数据处理模块。数据处理则由芯片AT89C52来完成,其负责把ADC0809传送来的数字量经过一定的数据处理,送到LCD1602液晶显示模块进行显示;此外,它还控制着ADC0809芯片工作。 关键词:

数字电路 单片机 ADC0809 LCD1602 总体方案的设计: 本次设计的要求如下:

1. 可以选择测量8路1-5V的8路电压值: 2. 可轮流显示或单路选择显示(可选);

3. 测量显示的最小分辨率为0.01V,测量的误差正负0.02V; 4. 具有电压过低,过高声光报警功能,报警限可独立设置。 设计思路:

根据设计的要求,进行器件的选择。芯片控制选取STC89C52单片机,由于要控制8路,故选取ADC0809的数模转换,显示部分选用目前很流行的LCD1602的液晶显示,最后采用8个开关控制8个通道,所以选取74LS148。下面进行逐一叙述: STC89C52单片机芯片管脚如下

2

STC89C52的管脚图

STC89C52是一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash 存储器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。 具有以下标准功能: 8k字节Flash,512字节RAM, 32 位I/O 口线,看门狗定时器,内置4KB EEPROM,MAX810复位电路,三个16 位 定时器/计数器,一个6向量2级中断结构,全双工串行口。另外 STC89X52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU 停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。最高运作频率35Mhz,6T/12T可选。 复位电路设计

单片机在启动运行时都需要复位,使CPU和系统中的其他部件都处于一个确定的初始状态,并从这个状态开始工作。MCS-51单片机有一个复位引脚RST,采用施密特触发输入。当震荡器起振后,只要该引脚上出现2个机器周期以上的高电平即可确保时器件复位[1]。复位完成后,如果RST端继续保持高电平,MCS-51就一直处于复位状态,只要RST恢复低电平后,单片机才能进入其他工作状态。单片机的复位方式有上电自动复位和手动复位两种,下图是51系列单片机统常用的上电复位和手动复位组合电路,只要Vcc上升时间不超过1ms,它们都能很好的工作[1]。

3

复位电路

时钟电路设计

单片机中CPU每执行一条指令,都必须在统一的时钟脉冲的控制下严格按时间节拍进行,而这个时钟脉冲是单片机控制中的时序电路发出的。CPU执行一条指令的各个微操作所对应时间顺序称为单片机的时序。MCS-51单片机芯片内部有一个高增益反相放大器,用于构成震荡器,XTAL1为该放大器的输入端,XTAL2

[1]

为该放大器输出端,但形成时钟电路还需附加其他电路。

本设计系统采用内部时钟方式,利用单片机内部的高增益反相放大器,外部电路简,只需要一个晶振和 2个电容即可,如下图所示。

时钟电路

ADC0809:

ADC0809是美国国家半导体公司生产的CMOS工艺8通道,8位逐次逼近式A/D模数转换器。其内部有一个8通道多路开关,它可以根据地址码锁存译码后的信号,只选通8路模拟输入信号中的一个进行A/D转换。是目前国内应用最广泛的8位通用A/D芯片。

下图是内部电路结构及外部管脚图:

4

1.主要特性

1)8路输入通道,8位A/D转换器,即分辨率为8位。 2)具有转换起停控制端。 3)转换时间为100μs(时钟为640kHz时),130μs(时钟为500kHz时) 4)单个+5V电源供电

5)模拟输入电压范围0~+5V,不需零点和满刻度校准。 6)工作温度范围为-40~+85摄氏度 7)低功耗,约15mW。

2.内部结构

ADC0809是CMOS单片型逐次逼近式A/D转换器,内部结构如图所示,它由8路模拟开关、地址锁存与译码器、比较器、8位开关树型A/D转换器、逐次逼近寄存器、逻辑控制和定时电路组成。 3.外部特性(引脚功能)

ADC0809芯片有28条引脚,采用双列直插式封装,如图所示。下面说明各引脚功能。

IN0~IN7:8路模拟量输入端。 2-1~2-8:8位数字量输出端。

ADDA、ADDB、ADDC:3位地址输入线,用于选通8路模拟输入中的一路 ALE:地址锁存允许信号,输入,高电平有效。

START: A/D转换启动脉冲输入端,输入一个正脉冲(至少100ns宽)使其启动(脉冲上升沿使0809复位,下降沿启动A/D转换)。

5

程序设计及调试: 开始 初始化 调用A/D转换子程序 调用显示子程序 结束 初始化程序 所谓初始化,是对将要用到的MCS_51系列单片机内部部件或扩展芯片进行初始工作状态设定,初始化子程序的主要工作是设置定时器的工作模式,初值预置,开中断和打开定时器等[9]。 A/D转换子程序

A/D转换子程序用来控制对输入的模块电压信号的采集测量,并将对应的数值存入相应的内存单元,其转换流程图如图13所示。 开始 启动转换 A/D转换结束? 输出转换结果 数值转换 显示 结束

11

图13 A/D转换流程图

3 显示子程序

跟据LCD1602液晶的显示方式,先对其进行初始化,输入设置方式,在显示数值的时候要先写地址符号。

Write_LCD_Command(0x80);//设置显示的初始位置

LCD_Display(display_buffer[0]); //显示测得的数据

本人在小组中的工作及设计体会:

由于我承担小组长的职位,在设计的时候兼顾整体的方案。根据本小组成员的需要及个人所长,工作分配如下:

XXX(我):仿真电路图的设计及程序的设计

XX:仿真电路图的设计及电路图的布线 XXX:元器件的采购及电路图的焊接

设计体会:

本次设计很大程度考验了一个团队的合作能力,一个人并不能擅长做所有的东西,而对于设计,其关键就在于设计的思路,有步骤的设计可以省去很多不必要的麻烦,我觉得做这样的课程设计,不仅仅是考验我们的设计能力,或者说是写程序能力,而是我们将成品做出来后,它并没有按照我们的设定工作,更大程度的考验我们解决问题的能力。比如这次我们的设计,在仿真成功后,电路板焊接完毕,连线完毕,将程序输入到单片机里工作时就出了差错,检查了很久的连线都没有检查出来,然后就想到了测电位的方法来判断,当时就得出了结论:单片机没有工作。省去了大量的不必要的检查导线的问题,最后查出复位开关焊接出错了,也就很容易的改正过来了!

参考文献:

1.MCS-51单片机原理、系统设计与应用(万福君等著 清华大学出版社) 2.51单片机C语言教程(郭天祥著 电子工业出版社)

元器件清单:

STC89C52单片机*1 LCD1602液晶 *1 杜邦线导线若干 电阻1K *9 ADC0809 *1 按键 *1 晶振12M *1 74LS148 *1 排针若干 点解电容10uf *1 104电容 *2

12

程序清单:

#include #include #include #define dat_port P0

#define uchar unsigned char #define uint unsigned int

#define delay4us() {_nop_();_nop_();_nop_();_nop_();} sbit AB3=P3^0;//对74HC148进行判断 sbit AB2=P3^1;//报警设置

sbit RS=P2^0;//RS=1 数据 RS=0 命令 sbit RW=P2^1;//RW=1 读取 RW=0 写入 sbit E=P2^2;//E 使能信号 sbit EOC=P2^4; sbit OE=P2^5; sbit START=P2^3; sbit CLOCK=P2^6;

void Refresh_show(); void delay50us(uint m) {

uint n,k;

for(n=m;n>0;n--) for(k=25;k>0;k--); }

void Write_LCD_Command(uchar cmd);//向LCD写入命令

void Write_LCD_Data(uchar dat); //向LCD写入一个字节的数据函数 void Initialize_LCD1602(); //液晶初始化函数

void LCD_Display(uchar *str);//在LCD上显示字符串

//---------------忙检查-------------------// uchar LCD_Busy_Check() {

uchar LCD_Status; RS = 0; RW = 1; E = 1;

delay50us(4);

13

LCD_Status = P0;

E = 0;

return LCD_Status; }

//--------------向LCD写入命令--------------------// void Write_LCD_Command(uchar cmd) {

while((LCD_Busy_Check()& 0x80)==0x80); //忙等待 RS = 0; RW = 0; E = 0;

P0 = cmd; delay4us(); E = 1;

delay4us(); E = 0; }

//-----------向LCD写入一个字节的数据函数-----------------*/ void Write_LCD_Data(uchar dat) {

while((LCD_Busy_Check()&0x80)==0x80); RS = 1; RW = 0; E = 0; P0 = dat; delay4us(); E = 1;

delay4us(); E = 0; }

//-----------LCD初始化-----------------*/ void Initialize_LCD1602() //液晶初始化函数 {

Write_LCD_Command(0x38);delay50us(10); //功能设置,数据长度为8位,双行显示,5×7点阵字体

Write_LCD_Command(0x0C);delay50us(10); // 显示开,关光标

Write_LCD_Command(0x06);delay50us(10); //字符进入模式:屏幕不动,字符后移

14

Write_LCD_Command(0x01); delay50us(10);//清屏 }

//-----------在LCD上显示字符串-----------------*/ void LCD_Display(uchar *str) {

uchar i;

for(i=0;i

Write_LCD_Data(str[i]); delay50us(100); }

}

unsigned long dat_adc0808; uchar display_buffer[][16]={ {\ {\ };

uint adc0808_init() // AD初始化 {

START=0; START=1; START=0;

while(EOC==0); OE=1;

delay50us(20); dat_adc0808=P1; OE=0;

return dat_adc0808; }

void Refresh_show() //刷新显示 {

uint t=dat_adc0808*500.0/255; // if(t>400||t<100)//报警的上下限设置 AB2=1; else

15

AB2=0;

display_buffer[1][3] = t/100+'0'; //整数位

display_buffer[1][5] = t/10+'0'; //两个小数位 display_buffer[1][6] = t+'0'; }

void main() {

TMOD=0x02; TH0=0x14; TL0=0x00; EA=1;

ET0=1; TR0=1;

Initialize_LCD1602(); delay50us(10);

Write_LCD_Command(0x80);//设置显示的初始位置

LCD_Display(display_buffer[0]); //显示测得的数据 while(1) {

if(AB3==1)

{

Write_LCD_Command(0xc0);//设置显示的初始位置

LCD_Display(display_buffer[1]); //显示测得的数据 }

else{

adc0808_init();

Refresh_show(); //更新测的电压数据

Write_LCD_Command(0xc0);//设置显示的初始位置 LCD_Display(display_buffer[1]); //显示测得的数据 }

} }

void Timer0_INT() interrupt 1 using 1 {

CLOCK=!CLOCK; }

16

AB2=0;

display_buffer[1][3] = t/100+'0'; //整数位

display_buffer[1][5] = t/10+'0'; //两个小数位 display_buffer[1][6] = t+'0'; }

void main() {

TMOD=0x02; TH0=0x14; TL0=0x00; EA=1;

ET0=1; TR0=1;

Initialize_LCD1602(); delay50us(10);

Write_LCD_Command(0x80);//设置显示的初始位置

LCD_Display(display_buffer[0]); //显示测得的数据 while(1) {

if(AB3==1)

{

Write_LCD_Command(0xc0);//设置显示的初始位置

LCD_Display(display_buffer[1]); //显示测得的数据 }

else{

adc0808_init();

Refresh_show(); //更新测的电压数据

Write_LCD_Command(0xc0);//设置显示的初始位置 LCD_Display(display_buffer[1]); //显示测得的数据 }

} }

void Timer0_INT() interrupt 1 using 1 {

CLOCK=!CLOCK; }

16

本文来源:https://www.bwwdw.com/article/pbk6.html

Top