仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
基本功能 利用51单片机作为主控芯片,模拟量输入范围直流0v-5v。模拟量经A/D(ADC0809)模数转换芯片,把模拟量转换为数字量输入到单片机的P0口,再由单片机控制LCD1602液晶显示模拟量输入的电压值。 1.1.2主要技术参数 测量电压范围:0v至5v A/D转换器:ADC0809(8位模数转换器)。 显示方式: LCD1602液晶 1.2设计原理 此次设计的是数字电压表,要求的电压范围是0~5v。系统设计主要包括四个部分:分别是电源模块、AD模数转换部分、51单片机最小系统部分、数码管显示部分。首先由单片机初始化ADC0809模数转换芯片和共阴数码管显示,当外接被测电压后,ADC0809将模拟电压信号转换为数字信号输入到单片机的I/O口,通过单片机处理后将电压的大小显示在LCD1602液晶上面。
硬件设计与原理 以AT89C51单片机为核心,起着控制作用。系统包括LCD1602液晶显示电路、复位电路、时钟电路、模数转换电路电路。设计思路分为五个模块:复位电路、晶振电路模块、AT89C51、LCD1602液晶显示电路、模数转换器电路这五个模块。
软件设计的组成 该系统由延时子函数、LCD1602液晶忙检测子函数、LCD1602液晶写命令/写数据子函数、汉字显示子函数、LCD1602液晶显示字符串子函数、LCD1602液晶初始化子函数、ADC0809转换子函数、主函数和数据定义这几部分组成。
自动档程电压表的单片机源程序如下:
- #include <AT89X52.H>
- #define LEDDATA P0
- #define v20_on {s3=0;s2=0;s1=1;} //宏定义不同量程,不同的开关状态
- #define v2_on {s3=0;s2=1;s1=0;}
- #define v02_on {s3=1;s2=0;s1=0;}
- unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
- unsigned char dispbuf[8]={0,0,0,0,0,0,0,0};
- unsigned char getdata;
- unsigned long temp;
- unsigned char i,k,l,m;
- unsigned char code mytable0[]=" Welcome to use ";
- unsigned char code mytable1[]="Auto Voltmeter!";
- unsigned char code line0[]=" Voltmeter "; //初始化显示
- unsigned char code line1[]=" Value: V ";
- //引脚定义
- sbit lcdrs=P2^0;
- sbit lcden=P2^1;
- sbit s3=P3^7;
- sbit s2=P3^6;
- sbit s1=P3^5;
- sbit OE=P3^0;
- sbit EOC=P3^1;
- sbit ST=P3^2;
- void delay(unsigned int z) //延时子函数 z*1ms
- {
- unsigned int x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- void write_com(unsigned char c) //写命令子函数
- {
- lcdrs=0; //低电平选择为 写指令
- lcden=0;
- LEDDATA=c; //把指令写入P0口
- delay(5); //参考时序图
- lcden=1; //开使能
- delay(5); //读取指令
- lcden=0; //关闭使能
- }
- void write_data(unsigned char d) //写数据子函数
- {
- lcdrs=1; //高电平选择为 写数据
- LEDDATA=d; //把数据写入P0口
- delay(5); //参考时序图
- lcden=1; //开使能
- delay(5); //读取数据
- lcden=0; //关闭使能
- }
- void initialize() //LCD初始化函数
- {
- unsigned char num;
- lcden=0;
- write_com(0x38); //设置16x2显示,5x7点阵显示,8位数据接口
- write_com(0x0c); //00001DCB,D(开关显示),C(是否显示光标),B(光标闪烁,光标不显示)
- write_com(0x06); //000001N0,N(地址指针+-1)
- write_com(0x01); //清屏指令 每次显示下一屏内容时,必须清屏
- write_com(0x80+0x10); //第一行,顶格显示
- for(num=0;num<17;num++)
- {
- write_data(mytable0[num]);
- delay(10);
- }
- write_com(0x80+0x50); //第二行,从第一格开始显示
- for(num=0;num<15;num++)
- {
- write_data(mytable1[num]);
- delay(10);
- }
- for(num=0;num<16;num++)
- {
- write_com(0x1c); //0001(S/C)(R/L)**; S/C:高电平移动字符,低电平移动光标; R/L:高电平左移,低电平右移
- delay(300);
- }
- delay(1000);
-
- write_com(0x01); //清屏指令 每次显示下一屏内容时,必须清屏
- write_com(0x80);
- for(num=0;num<14;num++)
- {
- write_data(line0[num]);
- delay(10);
- }
- write_com(0x80+0x40);
- for(num=0;num<15;num++)
- {
- write_data(line1[num]);
- delay(10);
- }
- }
- void value(unsigned char add,unsigned char dat)
- {
- write_com(0x80+0x47+add);
- if(l==3&&add==2||l!=3&&add==1)
- {
- write_data(0x2e);
- }
- else
- {
- write_data(0x30+dat);
- }
- }
- main()
- {
- initialize();
- while(1)
- _20v:
- {
- v20_on;
- ST=0;
- ST=1;
- ST=0;
- while(EOC==0);
- OE=1;
- getdata=P1;
- OE=0;
- if(getdata<21)
- {
- goto _2v;
- }
- l=3;
- temp=getdata;
- temp=(temp*1000/51)/2;
- goto disp;
- _2v:
- v2_on;
- ST=0;
- ST=1;
- ST=0;
- while(EOC==0);
- OE=1;
- getdata=P1;
- OE=0;
- if(getdata<21)
- {
- goto _02v;
- }
- else if(getdata>204)
- {
- goto _20v;
- }
- l=2;
- temp=getdata;
- temp=(temp*1000/51)/2;
- goto disp;
- _02v:
- v02_on;
- ST=0;
- ST=1;
- ST=0;
- while(EOC==0);
- OE=1;
- getdata=P1;
- OE=0;
- if(getdata>204)
- {
- goto _2v;
- }
- l=1;
- temp=getdata;
- temp=(temp*1000/51)/2;
- m=temp%10;
- if(m>5){temp=temp/10+1;}
- else{temp=temp/10;}
- goto disp;
- disp: for(i=0;i<=3;i++)
- {
- dispbuf[i]=temp%10;
- temp=temp/10;
- }
- if(l==3)
- {
- for(i=4;i>=3;i--)
- dispbuf[i]=dispbuf[i-1];
- }
- else
- {
- dispbuf[4]=dispbuf[3];
- }
- for(k=0;k<5;k++)
- {
- value(k,dispbuf[4-k]);
- }
- if(l==2){goto _2v;}
- else if(l==1){goto _02v;}
- }
- }
复制代码
Keil代码与Proteus8.13仿真下载:
基于51单片机数字电压表的设计.7z
(3.8 MB, 下载次数: 155)
|