单片机数字电压表程序
基于单片机的数字电压表代码
while((LCD_Busy_Check()& 0x80)==0x80);//忙等待
RS = 0;
RW = 0;
E = 0;
P0 = cmd;
delay4us();
E = 1;
delay4us();
E = 0;
}
//-----------向LCD写入一个字节的数据函数-----------------*/
#define uint unsigned int
sbit START=P2^3;
sbit EOC=P2^4;
sbit OE=P2^5;
void delay50us(uint m);//延时
uint adc0808_init(); // AD初始化
Байду номын сангаасvoid Refresh_show();
#endif
主程序:
#include <reg52.h>
#include <intrins.h>
#include <string.h>
#include "LCD1602.h"
#include "ADC0808.h"
//---------------忙检查-------------------//
uchar LCD_Busy_Check()
void Write_LCD_Data(uchar dat)
{
while((LCD_Busy_Check()&0x80)==0x80);
RS = 1;
RW = 0;
E = 0;
P0 = dat;
delay4us();
E = 1;
《单片机》教学课件数字电压表例程(C51)
读0809数据
delaynms(2); qianwei=0;
baiwei=1;
P1=table[bai]; delaynms(2); shiwei=1;
baiwei=0;
输出位码 输出段吗
P1=table[shi];
delaynms(2); sable[ge];
delaynms(2); gewei=0;
数字电压表例程
1
程序内容
一 二 三 四
初始化 0809转换 数据处理 七段动态显示
2
0809与单片机接口电路
3
源程序
#include <reg51.h>
#include <absacc.h> #include <intrins.h> #define uchar unsigned char
定义表数据 带小数点/不
while(j--) {for(i=0;i<250;i++) {_nop_(); _nop_(); _nop_(); _nop_(); } }
}
5
/**********显示函数************/
void display(uchar x)
{ unsigned int temp;
uchar ge,shi,bai,qian;
temp=x*196;
//提取电压千位百位十位个位
qian=temp/10000;
bai=temp%10000/1000; shi=temp%10000%1000/100; ge=temp/100%10;
利用除法 提取千百十
用单片机设计数字电压表
.目录摘要 (3)引言 (4)一、系统方案选择和论证 (4)1.设计要求 (4)2.系统基本方案 (4)二、系统硬件设计与实现 (5)1. 系统硬件概述 (5)2.主要单元电路的设计 (5)三、系统的软件设计 (11)3.1 系统软件概述 (11)3.2 数字电压表总程序流程图 (11)3.3 子程序的设计 (11)四、系统测试 (19)4.1 测试仪器与设备 (19)4.2 指标测试与误差分析 (19)4.3 测试结果分析与结论 (19)五、总结 (20)5.1 作品总结 (20)5.2 自我总结 (20)六、致谢词、 (20)七、参考文献 (20)附录一:系统电路图 (21)附录二:系统程序清单 (22)简易数字电压表摘要:在电子高科技技术高速发展的今天,很多电子产品应运而生。
简易数字电压表是一种实时测试电压变化量的数码智能产品。
该系统由 AT89S52 单片机系统、A/D转换模块、LED 动态显示模块、电源模块、量程选择模块和报警系统组成。
该系统能完成电压量的采集、A/D转换、手动量程切换、实时显示采集到电压量以及声光报警等功能。
该系统成本低,功能实用,性能可靠,使用方便,功耗低,很受市场的欢迎和青睐。
关键词:AT89S52 数码产品 LED 动态扫描A/D转换功能实用引言现今社会科学技术高速发展,电子技术日新月异,随之而来的电子产品更是如雨后春笋,它们很好的服务于人们的生活和生产。
信息化时代人们离不开电子产品,并且对电子产品的要求也越来越高。
数字电压表的应用很广泛,它在水电行业,教学领域以及人们日常生活中都拥有很广阔的市场。
一、系统方案选择和论证:1、设计要求1.1 基本要求:①电压测量范围0~5V;②能用数码管显示电压值;③测量精度达0.1V;④要求系统具备复位功能;⑤自制直流稳压电源;⑥系统具备自检功能。
1.2 发挥部分:①电压测量范围5~20V;②同时采集8路信号分时显示;③电压表具备20V 超量程报警功能;④测量精度:0~5V 内可调可达0.02V,5~20V 可达0.1V;⑤电压表具备抑制脉冲干扰的能力;⑥尽可能减少芯片的使用节约成本;⑦其他发挥。
单片机课程设计报告:电压表(附程序)
——电压表【课题】电压表【设计要求】设计一个量程可变的数字电压表,用3个LED数码管显示,电压表量程为0~200mV(显示0~200mV)、200mV~2V(显示0.2V~2V)。
【设计原理】一、实验电路图二、工作原理如上图所示,实验中主要用到的芯片有运算放大器、继电器、ADC0832、8951单片机及其外围设备。
电压表的量程为两档,0~200mV 和200mV~2V。
其相对应的运放的放大增益是25倍和2.4倍,这样即使是最大的输入其通过运放后的输出电压都会小于5V,其通过限幅电路后电压均为其真实值。
然后模拟输入电压由AD0832输入,经过模数转换后送给单片机。
由p0口输出字形,同时由p1.4的电平控制74LS573的锁存和直通状态。
P1.5、p1.6、p1.7控制字位。
P1.2控制继电器的工作状态,当P1.2低电平时,三极管工作在截止状态,继电器线圈无电流通过,继电器处于常闭状态,那么相对应的运放的放大增益为25倍。
而当P1.2为高电平时,三极管工作在饱和状态,继电器线圈有电流通过,产生电磁力将继电器的开关吸到常开状态,其对应的放大增益即变为2.4倍。
对于一个模拟输入,现将其放大2.4倍,然后由AD 输入并相应转化,如果它的输出要是小于0.5V ,也就是19H ,则选择此档位是不精确的,也说明此时的输入电压介于0~200mV 之间。
那么我们就需要让P1.2置低电平,将相应的放大倍数改成25以提高转换精度。
若其满足相应的条件则直接将其转换成BCD 码并直接送数显示即可。
实验中用到了模数转换器ADC0832,其引脚图如右图所示,ADC0832是8位逐次逼近型A /D 转换器, 单一正5V 电源供电,CS 为片选, CLK 提供串行输入/输出时钟信号,DO用于串行数字输出,CHO 和CHl 为双通道模拟输入端, 它可用软件设定为单端或差分输人。
在差分方式中,通道口地址的选择由DI 逐位输入,GND 是数字、模拟公共地,cc V (REP V )为芯片电源、参考电压公共端。
单片机数字电压表(带仿真图C程序)
基于51单片机数字电压表本模块采用ADC0832模数转换芯片,LCD1602液晶显示,测量范围0-5V,精度误差0.01V看了很多网上的课程设计或者毕业论文,得出以下几点:1.数字电压表的方案有很多种,有的采用ADC0809,或者ADC0808等,他们都是8温AD,并口传输数据,具有速率高的优点。
但是硬件复杂,与单片机电路繁琐,焊接起来比较麻烦。
所以本设计采用ADC0832,同样8位AD,特点是串口传输数据,硬件接口简单,且精度误差一致,速率也比较快,对于要求不高的系统非常适合。
2.显示电路,网上采用LED显示居多,本设计采用LCD1602液晶显示,具有硬件搭设简单,显示美观等优点3.本设计方便移植,只需将LCD1602三个控制端口,ADC0832 四个控制端口修改即可。
注意LCD1602数据传输接口是单片机的P0口,如下图,需要接上拉电阻4.程序采用C代码编写,亲测直接可以使用,若需仿真文件,请用E-mail联系邮系。
邮箱:gnsywb@5.网上很多设计数据转换程序有误,不够正确。
在转换过程中,中间变量需设置为int 类型,虽然8位AD输出最高位255,但是余数转换过程中会大于255。
若设计char型,会造成显示输出有误。
void convert(uchar a){ uint temp; //特别注意这里需定义int型(余数将大于255)dis[0]=a/51; //取个位temp=a%51;temp=temp*10; dis[1]=temp/51; //取小数点后第一位temp=temp%51;temp=temp*10; dis[2]=temp/51; //取小数点后第二位}具体电路图如下:1.利用电压表与测量显示电压对比附录:C程序/******************************************** 功能:单片机数字电压表ADC0832+LCD16021,测量范围0-5V2,2路输入电压,可自行设定3,测量精度误差0.01V,LCD液晶显示编写者:小子在西藏gnsywb@编写日期:2012-11-5*********************************************/ #include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned charsbit lcdrs=P2^4;sbit lcdrw=P2^5;sbit lcden=P2^6; //1602控制端口sbit DI=P3^4;sbit DO=P3^4; //DI和DO与单片机共接口sbit Clk=P3^3;sbit CS=P3^5;//ADC0832控制端口uchar dis[3]={0x00,0x00,0x00}; //显示缓冲区uchar date=0; //AD值uchar CH; //ADC0832通道值/*****************************************AD0832转换程序******************************************/uchar ADC0832(uchar CH){uchar i,dis0,dis1;Clk=0; //拉低时钟DI=1; //初始化_nop_();CS=0; //芯片选定_nop_();Clk=1; //拉高时钟_nop_();if(CH==0) //通道选择{Clk=0; //第一次拉低时钟DI=1; //通道0的第一位_nop_();Clk=1; //拉高时钟_nop_();Clk=0; //第二次拉低时钟,ADC0832 DI接受数据DI=0; //通道0的第二位_nop_();Clk=1;_nop_();}else{Clk=0;DI=1; //通道1的第一位_nop_();Clk=1;_nop_();Clk=0;DI=1; //通道1的第二位_nop_();Clk=1;_nop_();}Clk=0; //第三次拉低时钟,此前DI两次赋值决定通道DI=1; //DI开始失效,拉高电平,便于DO数据传输for(i= 0;i<8;i++) //读取前8位的值{_nop_();dis0<<= 1;Clk=1;_nop_();Clk=0;if (DO)dis0|=0x01;elsedis0|=0x00;}for (i=0;i<8;i++) //读取后8位的值{dis1>>= 1;if (DO)dis1|= 0x80;elsedis1|= 0x00;_nop_();Clk=1;_nop_();Clk=0;}if(dis0==dis1) //两次结束数据比较,若相等date=dis0; //则赋值给dat_nop_();CS=1; //释放ADC0832DO=1; //拉高输出端,方便下次通道选择DI端有效Clk=1; //拉高时钟return date;}/***********************************************数据转换程序功能:将0-255级换算成0.00-5.00的电压数***********************************************/void convert(uchar a){uint temp; //特别注意这里需定义int型(余数将大于255)dis[0]=a/51; //取个位temp=a%51;temp=temp*10;dis[1]=temp/51; //取小数点后第一位temp=temp%51;temp=temp*10;dis[2]=temp/51; //取小数点后第二位}/***************************************** LCD1602驱动程序******************************************/ void delay(uchar z){uint x,y;for(x=z;x>0;x--)for(y=122;y>0;y--);}void write_cmd(uchar cmd)//lcd1602写命令函数{lcdrs=0;lcdrw=0; //选择指令寄存器lcden=1;P0=cmd; //写数据delay(5);lcden=0; //使能拉低lcden=1;}void write_date(uchar date)//lcd1602写数据函数{lcdrs=1;lcdrw=0; //选择数据寄存器lcden=1;P0=date; //写数据delay(5);lcden=0; //使能拉低lcden=1;}void init_lcd1602()//lcd1602初始化{write_cmd(0x01); //清屏write_cmd(0x38); //功能设置write_cmd(0x0c); //显示设置write_cmd(0x06); //输入方式从左到右delay(1);}/***************************************** 显示函数*****************************************/ void display(void){uchar i;write_cmd(0x80);for(i=0;i<3;i++){if(i==1) write_date('.'); //第二位显示小数点write_date (0x30+dis[i]);delay(5);}write_date('V'); //最后一位后显示字符'V'}/************************************************ 主函数***************************************************/ void main(void){CH=0; //选择通道0或1init_lcd1602();//液晶1602显示初始化while(1) //主循环{date=ADC0832(CH);//启动ADC0832转换并接受数据delay(1);convert(date); //数据转换成BCD码display(); //显示数值}}。
单片机课程设计 数字电压表
一目的和意义 (2)二任务和要求 (2)1、设计任务 (2)2、设计要求 (2)三设计思路 (2)四、系统结构框图与工作原理 (2)1、系统结构框图 (2)2、工作原理 (3)五、硬件介绍 (3)1、单片机系统 (3)2、ADC0808主要特性 (5)ADC0808的外部引脚特征: (5)3、ADC0808的内部结构及工作流程 (7)六、复位电路和时钟电路 (8)1、复位电路设计 (8)2、时钟电路设计 (8)七LED显示系统设计 (9)1、 LED基本结构 (9)2、LED显示器的选择 (9)3、 LED译码方式 (9)4、LED显示器与单片机接口间的设计 (10)八、A/D转换电路和测量电路的设计 (11)九、程序设计 (12)1、程序设计总方案 (12)2、系统子程序设计 (12)十、使用说明与调试结果 (14)十一、总结 (15)参考文献 (16)附一系统原理图 (17)附二程序清单 (18)一目的和意义《单片机原理与接口技术》课程设计是在完成《单片机原理及其接口技术》的理论教学之后安排的一个实践教学环节。
《单片机原理与接口技术》课程设计是学习单片机理论的重要实践环节。
在单片机课程基础上,通过本课程设计的学习使学生增进对单片机的感性认识,加深对单片机理论方面的理解;使学生了解和掌握单片机应用系统软件的软硬件设计工程、方法及实现,强化单片机应用电路的设计与分析能力。
提高学生在单片机应用方面的实践技能和科学作风,培养学生综合运用理论知识解决问题的能力。
二任务和要求1、设计任务基于MCS-51系列单片机AT89C51,设计一个能测量0~5V直流电压的数字电压表2、设计要求(1)选用A/D转换器ADC0808,测定0——+5V范围内的直流电压值。
(2)采集的数据送四位数码管实时显示。
(3)实现多路电压循环测量和循环显示。
三设计思路1、根据设计要求,选择AT89C51单片机为核心控制器件。
2、A/D转换采用ADC0808实现,与单片机的接口为P0口和P2口。
单片机制作的电压表程序
单片机制作的电压表#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsfr ADC_CONTR=0xBC; //A/D转换功能允许寄存器sfr ADC_RES=0xBD; //A/D转换结果寄存器sfr ADC_RESL=0xBE; //A/D转换结果寄存器低sfr AUXR1=0xA2; //辅助寄存器1sfr P1_ASF=0x9D; //A/D转换控制寄存器sbit ADIO=P1^7; //1.7口接测量电压sbit U3_DS=P1^5;sbit U3_STCP=P1^4;sbit U3_SHCP=P1^3;sbit U4_DS=P1^2;sbit U4_STCP=P1^1;sbit U4_SHCP=P1^0;uchar key_val[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G'} uchar codekey_code[]={0x77,0x7B,0x7D,0x7E,0xB7,0xBB,0xBD,0xBE,0xD7,0xDB,0xDD,0xDE,0xE7,0xEB,0xE uchar key,count;void delay(unsigned int n);//74HC595void U3_595(unsigned char num){unsigned char count1;for (count1=0;count1<=7;count1++){if ((num&0x80)==0x80)//最高位为1,则向SDATA_595发送1{U3_DS=1;}else{U3_DS=0;}U3_SHCP=0;U3_SHCP=1;num<<=1;//左移}U3_STCP=0;U3_STCP=1;}void U4_595(unsigned char num)//发送指令到RS,RW,E(4,5,6位) {unsigned char count2;for (count2=0;count2<=7;count2++){if((num&0x80)==0x80){U4_DS=1;}else{U4_DS=0;}U4_SHCP=0;U4_SHCP=1;num<<=1;}U4_STCP=0;U4_STCP=1;}//LCD延时子程序 n=1时延时1msvoid delay(unsigned int n){unsigned char i;for(;n>0;n--)for(i=0;i<125;i++)_nop_();}//写指令到LCDvoid wcmd(unsigned char cmd){U4_595(0x0F);U3_595(cmd);U4_595(0x4F);U4_595(0x0F);}//写要显示的数据到LCDvoid wdat(unsigned char dat){U4_595(0x1F);//低4位全为1屏蔽8段数码管U3_595(dat);U4_595(0x5F);U4_595(0x1F);}//初始化LCDvoid init(){wcmd(0x38);//设置8位总线双行显示,5*7点阵 delay(20);wcmd(0x0C);//开显示,开光标,不闪烁delay(20);wcmd(0x06);//读写字符时地址加1delay(20);wcmd(0x01);//清屏delay(20);wcmd(0x82);}//键盘扫描子程序uchar keyscan(void){unsigned char hang,lie,keycode;char i;P0=0xf0;hang=P0;if((hang&0xf0)!=0xf0) //有键按下? {delay(5); //去抖动hang=P0;if((hang&0xf0)!=0xf0) //有键按下{P0=0x0f;lie=P0;keycode=hang|lie; //获得键码for(i=15;i>=0;i--){if(keycode==key_code[i]) //查找键码{key=i;return(key);}}}}elsereturn (key);}void keydown() //判断按键按下和显示程序{P0=0xf0;if((P0&0xf0)!=0xf0){while(P0!=0xf0)keyscan(); //获得键码wcmd(0xCF); //设置键值显示位置wdat(key_val[16-key]);}}void ADC_POWER_ON() //开ADC电源,第一次使用要打开内部模拟电源{ADC_CONTR=0x80;delay(10);}void SET_P1ASF(unsigned char channel) //设置模拟功能口{unsigned char i,final=0x01;for(i=0;i<=channel;i++)final<<=1;P1_ASF=final;}void SET_ADC_CHANNEL(unsigned char channel) //设置A/D转换通道{channel|=0xc0;ADC_CONTR=channel;delay(100);}float GET_ADC_RESULT(){unsigned char flag=0x10,temp=0x00;ADC_RES=0x00;ADC_RESL=0x00;AUXR1=0x04;//设置10位ADADC_CONTR|=0x08;//启动A/D转换_nop_();_nop_();_nop_();_nop_();do {temp=flag&ADC_CONTR;} while (temp==0x00);ADC_CONTR=ADC_CONTR&0xc7; //清零ADC_FLAG ADC_START 位return 256*ADC_RES+ADC_RESL;}void main(){float v;unsigned temp,temp1,temp2;init();ADC_POWER_ON();while(1){key=keyscan();keydown();if(16-key==1) //量程5V{SET_P1ASF(6);SET_ADC_CHANNEL(6);v=GET_ADC_RESULT();v=v*5/1024;temp=v;wcmd(0x82);delay(5000);wdat(0x30+temp);temp1=(v-temp)*10;wdat(46);//小数点wdat(0x30+temp1);temp2=(v-temp)*100-temp1*10; wdat(0x30+temp2);wdat(86);//Vwdat(32);//空白}if(16-key==2) //量程5-20V{SET_P1ASF(6);SET_ADC_CHANNEL(6);v=GET_ADC_RESULT();v=4*v*5/1024;temp=v/10;wcmd(0x82);delay(5000);wdat(0x30+temp);temp1=(int)v%10;wdat(0x30+temp1);wdat(46);//小数点temp2=v*10;wdat(0x30+temp2%10);temp2=v*100;wdat(0x30+temp2%10);wdat(86);//V}if(16-key==3) //量程20-100V {SET_P1ASF(6);SET_ADC_CHANNEL(6);v=GET_ADC_RESULT();v=19.8*5*v/1024;temp=v/10;wcmd(0x82);delay(5000); wdat(0x30+temp);temp1=v-temp*10;wdat(0x30+temp1);wdat(46);//小数点temp2=v*10;wdat(0x30+temp2%10);temp2=v*100;wdat(0x30+temp2%10);wdat(86);//V}}}。
单片机课程设计数字电压表参考程序
/************************************************************************ADC0809数据电压表,采用数码管显示,显示000~255* 硬件连接:START,ALE接P2.0,EOC-P2.1 OE-P2.2 CLK -P2.3,CH0接模拟电压输入TEST0*ADDA、ADDB、ADDC接P2.4, P2.5,P2.6,*数据D0--D7依此对应连接P1.0-P1.7*数码管段码接P0口*数码管位码接P3口******************************************************************************* */#include <reg52.H>#define uint unsigned int#define uchar unsigned char#define DIGI P0 //宏定义,将P0口定义为数码管#define SELECT P3 //宏定义,将P3定义为数码管选择口sbit START = P2^0;sbit EOC = P2^1;sbit OE = P2^2;sbit CLK = P2^3;sbit ADDA = P2^4; // ADDA接P2.4sbit ADDB = P2^5; // ADDB接P2.5sbit ADDC = P2^6; // ADDC接P2.6uchar getdata; //定义变量接受AD转换的8位二进制void delay() //延迟函数{ uint ii=200; //若发现数码管闪烁,调节这里即可while(ii--);}uchar disbuffer[8]={0,1,2,3,4,5,6,7}; //定义显示缓冲区void display( ){ uchar i=0,temp,i1;uchar codevalue[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//0~F的字段码表uchar select[]={0x01,0x02,0x04,0x00,0x00,0x00,0x00,0x00};//位选码for(i=0;i<3;i++) //8个数码管轮流显示{ temp= disbuffer[i];i1 = codevalue[temp];DIGI = i1; //选择第i个数码管SELECT = select[i]; //显示idelay();} }/************************************************///定时器初始化void init(){TMOD= 0x12;// 定时器0工作方式2,定时器1工作方式1TH0=246;TL0=246;TH1=(65536-20000)/256;TL1=(65536-20000)%256;EA=1;ET0=1;ET1=1;TR1=1;TR0=1;}/***********************************************///软件延时产生ADC0809的时钟void clk() interrupt 1{CLK=(~CLK);}void displayint(void) interrupt 3 //定时/计数器1中断,数码管显示{TH1=(65536-20000)/256;TL1=(65536-20000)%256;display( );}/************************************************///AD转换函数unsigned char ADC(){char value;ADDA =0;ADDB =0;ADDC =0;START=0;START=1; //地址锁存START=0; //开始转换while(EOC==0);//等待转换结束OE=1;value=P1;OE=0;return value;}/************************************************/void main(){uint temp1;init();while(1){getdata = ADC();//输出转换得到的数据temp1=getdata; //暂存转换结果disbuffer[2]=getdata/100; /*将转换结果转换为10进制数放显示缓冲区*/temp1=temp1- disbuffer[2]*100;disbuffer[1]=temp1/10;temp1=temp1- disbuffer[1]*10;disbuffer[0]=temp1;}}1.在它的基础上,显示用LCD1602或12864;2.在它的基础上,加按键选择实现多路数字电压表。
基于单片机的数字电压表设计c语言
#include<reg52.h>#include<intrins.h>sbit st=P2^4;sbit eoc=P3^7;sbit oe=P2^5;sbit ale=P2^3;sbit key1=P3^6;sbit key2=P3^5;unsigned charseg_code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; unsigned char seg_ale[]={0xf8,0xf9,0xfa,0xfb};unsigned char num[4];/************延时函数**********************/void delay_us(unsigned int delayus){while(delayus--);}void delay_ms(unsigned int delaytime){unsigned int i;unsigned char j;for(i=0;i<delaytime;i++)for(j=0;j<110;j++);}/********************************************//************ADC转换函数*********************/void adc_convert(void){double temp1;unsigned int temp2,temp3;st=0;_nop_();st=1;_nop_();st=0;oe=0;while(eoc==0);oe=1;_nop_();temp1=P0;_nop_();temp1*=492; //基准电压 4.9 Vtemp1/=255;temp2=(unsigned int)temp1%1000;num[2]=(unsigned char)(temp2/100);temp3=(unsigned int)temp2%100;num[1]=(unsigned char)(temp3/10);num[0]=temp3%10;delay_us(1);oe=0;}/*******************************************//**************显示函数*********************/ void dis(void){unsigned char i,b;b=0x01;for(i=0;i<4;i++){if(i==2)P1=seg_code[num[i]]&0x7f;else if(i==3)P1=seg_code[num[i]]&0x7f;elseP1=seg_code[num[i]];P3=~b;b<<=1;delay_ms(5);}}/*******************************************//****************主函数*********************/void main(void){unsigned char i,automatic;unsigned char keynum;int j;for(i=0;i<4;i++)num[i]=0;keynum=0;for(;;){/**************按键扫描******************************/ if(key1==0){delay_ms(1);dis();delay_ms(1);dis();delay_ms(1);dis();delay_ms(1);dis();delay_ms(1);dis();delay_ms(1);dis();delay_ms(1);dis();if(key1==0){if(keynum<3)keynum++;elsekeynum=0;}}if(key2==0) //自动加按键{delay_ms(1);dis();delay_ms(1);dis();delay_ms(1);dis();delay_ms(1);dis();delay_ms(1);dis();if(key2==0){if(automatic==0)automatic=1;elseautomatic=0;}}/***********************************************//****************开启四通道自动切换*************/ if(automatic==1){if(keynum<3){ale=1;_nop_();P2=seg_ale[keynum];num[3]=keynum;_nop_();ale=0;adc_convert();delay_ms(1);for(j=0;j<50;j++){dis();delay_ms(10);if(key2==0){delay_ms(1);dis();delay_ms(1);dis();delay_ms(1);dis();delay_ms(1);dis();delay_ms(1);dis();if(key2==0)break;}}keynum++;}else{ale=1;_nop_();P2=seg_ale[keynum];num[3]=keynum;_nop_();ale=0;adc_convert();delay_ms(1);for(j=0;j<50;j++){dis();delay_ms(10);}keynum=0;}}/****************手动通道切换***********************/ ale=1;_nop_();P2=seg_ale[keynum];num[3]=keynum;_nop_();ale=0;adc_convert();delay_ms(1);dis();delay_ms(6);}}。
基于51单片机的数字电压表
课程设计题目数字电压表学生姓名张玉龙学号20081341056学院信息与控制学院专业测控技术与仪器指导教师葛化敏二O一一年六月三十日基于51单片机的数字电压表一、设计内容:先在proteus 上进行软件仿真设计,在仿真实现的基础上,要求完成部分硬件模块的制作和系统联调,实验内容为设计一个数字电压表,实现从模拟信号输入到数字信号输出的基本功能。
二、设计要求:采用51系列单片机和ADC 设计一个数字电压表电路,通过调节滑动变阻器改变电压,在LCD 液晶屏上显示其相应的电压值,要求电压精确到小数点后第四位,显示格式为,LCD 第一行前一段为“20081341056”(班级同学张玉龙的学号),后一段则为“V :”(电压单位);第二行的前一段为“Class 2”(班级2班),后一段则显示电压值,单位为“V ”。
三、设计原理:通过在Keil 软件对单片机AT89C52进行编程,硬件电路中单片机与ADC0804及LCD 显示屏连接。
P0与ADC0804相连接,P1与LCD 连接。
通过start()子程序启动ADC0804,通过init ()子程序初始化LCD 。
模拟信号通过ADC0804的VIN+引脚输入到ADC0804中转换为数字信号,P0获得此数字量后,经过处理得到每位的数据后,通过P1口写数据到LCD上图为基本的原理图 四、实验电路图及仿真结果:51系列 单片机电压输入五、程序代码:#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit lcdrs=P3^0;sbit lcden=P3^1;sbit wrad=P3^6;sbit rdad=P3^7;uint temp,a1,a2,a3,a4,a5,num;uchar code table[]="0123456789.";//显示数字uchar code table1[]="20081341056 V:"; uchar code table2[]="Class 2";void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=100;y>0;y--);}void start()//启动AD{wrad=1;wrad=0;wrad=1;}void write_command(uchar com)//写命令{lcdrs=0;P1=com;delay(2);lcden=1;delay(2);lcden=0;}void write_data(uchar date)//写数据{lcdrs=1;P1=date;delay(5);lcden=1;delay(5);lcden=0;}void init()//lcd初始化{lcden=0;write_command(0x38);//设置16x2显示write_command(0x0c);//设置光标write_command(0x06);//写字符指针加1,光标加1write_command(0x01);//清屏}void main(){init();//LCD初始化write_command(0x80);//LCD写地址for(num=0;num<15;num++){write_data(table1[num]);delay(5);}while(1){start();//启动ADdelay(50);rdad=0; //rd低脉冲读数据delay(50);temp=P0;a1=(temp*50000/255)/10000;//区分位数,最高位 255*50000/255/10000=5.0000V a2=(temp*50000/255)%10000/1000;a3=(temp*50000/255)%1000/100;a4=(temp*50000/255)%100/10;a5=(temp*50000/255)%10;write_command(0x80+0x40);for(num=0;num<7;num++){write_data(table2[num]);delay(5);}write_command(0x80+0x49);//LCD写地址write_data(table[a1]);delay(1);write_data(table[10]);delay(1);write_data(table[a2]);delay(1);write_data(table[a3]);delay(1);write_data(table[a4]);delay(1);write_data(table[a5]);delay(1);write_data('V');delay(1);}}六、心得体会:课程设计中不得不遇到一些问题,但只要自己有恒心有毅力,终究会克服一切困难;在设计中我们要学会运用keil软件及protues软件对我们设计的电路不断地进行仿真、调试和修正,遇到程序问题时我们应该学会一段一段地去排查,最终解决所有问题;另外,还应熟练掌握每个芯片及器件如51单片机及ADC0804和LM016L每个引脚的作用和接法及各种状态的判断。
单片机数字电压表设计LED显示含C源代码
1. 绪论............................... 错误!未定义书签。
1.1 课程设计规定...................... 错误!未定义书签。
1.2 数字电压表简介.................... 错误!未定义书签。
2. 硬件单元电路设计................... 错误!未定义书签。
2.1数字电压表构造框图................. 错误!未定义书签。
2.1.1 AT89C51单片机简介............ 错误!未定义书签。
2.1.2 ADC0832转换器简介............ 错误!未定义书签。
2.1.3 时钟电路..................... 错误!未定义书签。
2.1.4 复位电路..................... 错误!未定义书签。
2.1.5 LED显示电路.................. 错误!未定义书签。
3. 软件单元电路设计................... 错误!未定义书签。
3.1 主程序流程图...................... 错误!未定义书签。
3.2显示子程序流程图................... 错误!未定义书签。
3.3 A/D转换子程序流程图............... 错误!未定义书签。
3.4 数据解决子程序流程图.............. 错误!未定义书签。
4. 数字电压表仿真设计图与实物图....... 错误!未定义书签。
4.1 仿真图............................ 错误!未定义书签。
4.2 器件清单.......................... 错误!未定义书签。
4.3 硬件电路实物图.................... 错误!未定义书签。
5. 程序代码.............................. 错误!未定义书签。
单片机课程设计 数字电压表 程序和电路图
功能:电压报警5V直流测量0.02V 误差LCD显示名字程序COM EQU 50H ;指令寄存器DAT EQU 51H ;数据寄存器RS EQU P2.1 ;LCD寄存器选择信号RW EQU P2.2 ;LCD读/写选择信号E EQU P2.3 ;LCD使能信号ORG 0000HLJMP MAIN ;主程序入口地址ORG 000BHLJMP BT0 ;T0中断入口ORG 0030H ;主程序,初始化MAIN:MOV SP,#60HLCALL INTMOV 30H,#30H ;电压整数位MOV 31H,#0A5H ;小数点位MOV 32H,#30H ;小数个位MOV 33H,#30H ;小数十位MOV 34H,#30H ;小数百位MOV 35H,#56H ;字符"V"MOV R7,#30HLCALL STR0 ;显示字符串0LCALL DELAYLCALL STR1 ;显示字符串1LCALL DELAYLCALL N2 ;显示V oltage=0.000V;***********定时器初始化程序***********MOV TMOD,#00H ;定时器T0设为方式0MOV TH0,#00H ;装入定时常数定时100usMOV TL0,#00HSETB TR0 ;启动T0MOV 24H,#08H;装入T0中断次数MOV IE,#82H ;开中断LP:MOV R7,#30H ;显示缓冲区首地址LCALL DISPL YSJMP LP ;循环显示LED1:CLR P3.0RET;********************************************************************;定时器T0中断服务子程序,读取ADC0809第0通道的A/D转换结果并化为显示值* ;********************************************************************BT0:PUSH ACCPUSH PSWMOV PSW,#08HCLR TR0MOV TH0,#00H ;重新装入初值MOV TL0,#00HDEC 24HMOV A,24HJNZ RTN1MOV 24H,#08HLCALL ADCRTN1: SETB TR0POP PSWPOP ACCRETIADC:MOV DPTR,#0F6FFHMOV A,#0 ;选择通道0MOVX @DPTR,A ;启动AD转换MOV A,#40HDJNZ ACC,$MOVX A,@DPTRMOV 22H,AMOV 21H,#0CCHCJNE A,21H,BJ0BJ0:JNC LEDSJMP LL0LL0:SETB P3.0SJMP LLLED:LCALL LED1LL: MOV A,22HMOV B,#05H ;A/D转换结果化为显示值MUL AB ;(AD*5)/256MOV 30H,B ;AD*5的高字节为整数部分MOV B,#0AHMUL AB ;AD*5的低字节为/256的结果,为小数部分MOV 32H,B ;二进制小数换为10进制数MOV B,#0AHMUL ABMOV 33H,BMOV B,#0AHMUL ABMOV 34H,BMOV A,30HMOV DPTR,#TABMOVC A,@A+DPTRMOV 30H,AMOV A,32HMOVC A,@A+DPTRMOV 32H,AMOV A,33HMOVC A,@A+DPTRMOV 33H,AMOV A,34HMOVC A,@A+DPTRMOV 34H,ARETDISPL Y: ;LCD显示子程序MOV COM,#0CAHLCALL PR1MOV DAT,30HLCALL PR2MOV DAT,31HLCALL PR2MOV DAT,32HLCALL PR2MOV DAT,33HLCALL PR2MOV DAT,34HLCALL PR2MOV DAT,35HLCALL PR2RETSTR0:MOV COM,#01HLCALL PR1MOV COM,#06HLCALL PR1MOV COM,#090H ;设置DDRAM地址LCALL PR1 ;调写指令代码子程序MOV DPTR,#TAB4MOV R2,#16MOV R3,#00HWRIN0:MOV A,R3MOVC A,@A+DPTRMOV DAT,ALCALL PR2INC R3DJNZ R2,WRIN0MOV COM,#0D0HLCALL PR1MOV DPTR,#TAB5MOV R2,#16MOV R3,#00HWRIN1:MOV A,R3MOVC A,@A+DPTRMOV DAT,ALCALL PR2INC R3DJNZ R2,WRIN1MOV R3,#10HZUOYI:MOV COM,#18HLCALL PR0DJNZ R3,ZUOYILCALL DELAY00LCALL DELAY00LCALL DELAY00LCALL DELAY00RETRETSTR1:MOV COM,#01H ;LCD清0命令LCALL PR1 ;调写指令代码子程序MOV COM,#06H ;输入方式命令,光标右移LCALL PR1 ;调写指令代码子程序MOV COM,#40HLCALL PR1MOV R5,#20HMOV DPTR,#ZIMOV R4,#0LOOP1:MOV A,R4MOVC A,@A+DPTRMOV DAT,ALCALL PR2INC R4DJNZ R5,LOOP1MOV COM,#80HLCALL PR1MOV DPTR,#TAB2MOV A,#00HMOVC A,@A+DPTR MOV DAT,ALCALL PR2MOV A,#01HMOV DPTR,#TAB2 MOVC A,@A+DPTR MOV DAT,ALCALL PR2MOV A,#02HMOV DPTR,#TAB2 MOVC A,@A+DPTR MOV DAT,ALCALL PR2MOV A,#03HMOV DPTR,#TAB2 MOVC A,@A+DPTR MOV DAT,ALCALL PR2MOV R1,#00HMOV R0,#0dHMOV DPTR,#TAB3 LOOP2:MOV A,R1MOVC A,@A+DPTRMOV DAT,ALCALL PR2INC R1DJNZ R0,LOOP2RETN2: MOV COM,#0C0HLCALL PR1MOV DPTR,#TAB1MOV R2,#10MOV R3,#00HWRIN:MOV A,R3MOVC A,@A+DPTRMOV DAT,ALCALL PR2INC R3DJNZ R2,WRINRETTAB: DB "0123456789"TAB1: DB "VOLTAGE = "TAB2: DB 00HDB 01HDB 02HDB 03HDB 04HDB 05HZI: DB 01FH,008H,00EH,00AH,00AH,00AH,012H,000H DB 00EH,00EH,019H,00EH,01DH,00DH,00FH,000H DB 00FH,01EH,00EH,01DH,01DH,00EH,014H,000H;*****************************************;****LCD间接控制方式下的初始化子程序******;*****************************************INT:LCALL DELAYMOV COM,#38H ;设置工作方式LCALL PR1MOV COM,#01HLCALL PR1MOV COM,#06HLCALL PR1MOV COM,#0EHLCALL PR1RETDELAY: ;延时子程序MOV R6,#0FHMOV R7,#00HDELAY1:NOPDJNZ R7,DELAY1DJNZ R6,DELAY1RETDELAY00: ;延时子程序MOV R6,#0FFHMOV R7,#0FFHDELAY0:NOPDJNZ R7,DELAY1DJNZ R6,DELAY1RET;1 读BF和AC值PR0: PUSH ACCMOV P0,#0FFH ; P0置位, 准备读CLR RS ; RS=0SETB RW ; R/W=1SETB E ; E=1LCALL DELAYMOV COM,P0 ; 读BF和AC6-4值CLR E ; E=0POP ACCRET;********************************************* ;*******LCD间接控制方式下的驱动子程序********* ;********************************************* ;2 写指令代码子程序PR1:PUSH ACCCLR RSSETB RWPR11:MOV P0,#0FFHSETB ELCALL DELAYNOPMOV A,P0CLR EJB ACC.7,PR11CLR RWMOV P0,COMSETB ECLR EPOP ACCRET;3 写显示数据子程序PR2:PUSH ACCCLR RSSETB RWPR21:MOV P0,#0FFHSETB ELCALL DELAYMOV A,P0CLR EJB ACC.7,PR21SETB RSCLR RWMOV P0,DATSETB ECLR EPOP ACCRET;4 读显示数据子程序PR3: PUSH ACCCLR RS ; RS=0SETB RW ; R/W=1PR31: MOV P0,#0FFH ; P0置位, 准备读SETB E ; E=1LCALL DELAYMOV A,P0 ; 读BF和AC6-4值CLR E ; E=0JB ACC.7,PR31SETB RS ; E=1SETB RW ; R/W=1MOV P0,#0FFH ; 读数据SETB E ; E=1MOV DA T,P0CLR E ; E=0POP ACCRETEND。
用单片机制作一个数字电压表
用单片机制作一个数字电压表摘要数字电压表是诸多数字化仪表的核心与基础,电压表的数字化是将连续的模拟量如直流电压转换成不连续的离散的数字形式并加以显示,这有别于传统的以指针加刻度盘进行读数的方法,避免了读数的误差和视觉疲劳。
目前数字万用表的内部核心部件是A/D转换器,转换器的精度很大程度上影响着数字万用表的准确度,本设计—数字电压表 A/D转换器采用ADC0808对输入模拟信号进行转换,控制核心AT89S51在对转换的结果进行运算和处理,最后驱动输出装置显示数字电压信号。
数字电压表是诸多数字化仪表的核心与基础,电压表的数字化是将连续的模拟量如直流电压转换成不连续的离散的数字形式并加以显示,这有别于传统的以指针加刻度盘进行读数的方法,避免了读数的误差和视觉疲劳。
目前数字万用表的内部核心部件是A/D转换器,转换器的精度很大程度上影响着数字万用表的准确度,本设计—数字电压表 A/D转换器采用ADC0808对输入模拟信号进行转换,控制核心AT89S51在对转换的结果进行运算和处理,最后驱动输出装置显示数字电压信号。
并可以在LED上进行显示,可以显示电压值的小数点后两位。
关键词:单片机数字电压表 AT89S51 ADC0808系统总体设计要求:利用单片机AT89S51和ADC0809对直流电压0~5V进行采集,并在LED 上进行显示,可以显示电压值的小数点后两位。
目录1 概述 (3)1.1单片机简单的介绍 (3)1.2单片机总体功能简介 (3)1.3运用单片机设计的数字电压表的简单介绍 (4)2 系统总体方案及硬件设计 (7)2.1系统总体设计要求 (7)2.2 数字电压表硬件电路设计 (7)2.3 系统电路原理图 (8)3 软件设计 (9)3.1 初始化程序 (9)3.2 主程序 (9)3.3显示子程序 (9)3.4摸/数转换测量子程序 (10)4 Proteus软件仿真 (10)4.1Proteus ISIS简介 (10)4.2Proteus运行流程 (11)4.3Proteus功能仿真 (12)4.4Proteus仿真结果 (13)4.5Proteus仿真结果分析 (18)5设计体会 (19)参考文献 (20)附1:源程序代码 (21)附2:系统原理图 (24)1.实验任务利用单片机AT89S51与ADC0809设计一个数字电压表,能够测量0-5V之间的直流电压值,四位数码显示,但要求使用的元器件数目最少。
7位数字电压表单片机程序
7位数字电压表单片机程序下面是一个简单的 7 位数字电压表单片机程序,使用 Keil uVision 进行编写和调试。
该程序使用一个计数器来逐位读取输入的电压值,并将其转换为数字格式,以便在 7 位数字电压表中显示。
```c#include <reg52.h>#define uchar unsigned char#define uint unsigned int// 定义计数器初始化值uint count = 0;// 定义数字电压表显示循环uchar display_loop = 0;// 显示电压值void display_voltage(uchar voltage){// 如果计数器未到达当前电压值,则继续显示if (count != voltage){// 将当前电压值写入计数器count = voltage;// 循环显示前 6 位数字while (display_loop != 6){// 显示当前电压值的 6 位二进制数字for (uint i = 0; i < 6; i++){// 将当前电压值的 6 位二进制数字转换为对应的 ASCII 字符 uchar char_value = (uchar)((count >> (5 - i)) & 0x1F);// 显示 ASCII 字符SparseInt8(char_value);}// 显示换行符display_loop = 0;}// 循环显示后 1 位数字display_loop = 6;}}// 读取电压值uchar read_voltage(){uchar voltage;// 读取输入引脚电压值voltage = uchar)((*P1 >> 5) & 0x1F);// 将读取到的电压值转换为数字格式voltage = voltage / 16;return voltage;}// 主函数void main(){// 初始化片上存储器SparseInt8(0x20);SparseInt8(0x00);SparseInt8(0x00);SparseInt8(0x00);SparseInt8(0x00);SparseInt8(0x00);// 循环读取输入引脚电压值,并将其转换为数字格式,然后显示在数字电压表中while (1){uchar voltage = read_voltage();display_voltage(voltage);}}```这个程序使用一个计数器来逐位读取输入引脚电压值,并将其转换为数字格式,以便在 7 位数字电压表中显示。
51单片机数字电压表设计
51单片机数字电压表设计51单片机数字电压表设计题目要求:1. 设计要求以单片机为核心,设计一个数字电压表。
采用中断方式,对2路0~5V的模拟电压进行循环采集,采集的数据送LED显示,并存入内存。
超过界限时指示灯闪烁。
2. 实验原理本题目本质上是以单片机为控制器,ADC0809为ADC器件的AD 转换电路,设计要求的电压显示,是对ADC采集所得信号的进一步处理。
为得到可读的电压值,需根据ADC的原理,对采集所得的信号进行计算,并显示在LED上。
本项目中ADC0809的参考电压为+5V,根据定义,采集所得的二进制信号addata所指代的电压值为:而若将其显示到小数点后两位,不考虑小数点的存在(将其乘以100),其计算的数值为:。
将小数点显示在第二位数码管上,即为实际的电压。
本示例程序将1.25 V和2.5 V作为两路输入的报警值,反映在二进制数字上,分别为0x40和0x80。
当AD结果超过这一数值时,将会出现二极管闪烁和蜂鸣器发声。
运行截图:程序代码:#include#include //定义绝对地址访问#include#define uchar unsigned char#define uint unsigned intsbit RS=P1^7; //定义LCD1602端口线sbit RW=P1^6;sbit EN=P1^5;sbit ST=P3^7; //定义0808控制线sbit OE=P3^6;sbit EOC=P1^3;sbit CLK=P1^4;sbit buzzer = P1^1; //喇叭sbit alarm = P1^2; //leduchar data chnumber; //存放当前通道号uchar disbuffer[4]={0,'.',0,0}; //定义显示缓冲区uchar data ad_data[8]={0,0,0,0,0,0,0,0}; //0808的8个通道转换数据缓冲区uint temp;//检查忙函数void fbusy(){P0 = 0xff;RS = 0;RW = 1;EN = 1;EN = 0;while((P0 & 0x80)){EN = 0;EN = 1;}}//写命令函数void wc51r(uchar j){fbusy();EN = 0;RS = 0;RW = 0;EN = 1;P0 = j;EN = 0;}//写数据函数void wc51ddr(uchar j){fbusy(); //读状态;EN = 0;RS = 1;RW = 0;EN = 1;P0 = j;EN = 0;}void init(){wc51r(0x01); //清屏wc51r(0x38); //使用8位数据,显示两行,使用5*7的字型wc51r(0x0c); //显示器开,光标开,字符不闪烁wc51r(0x06); //字符不动,光标自动右移一格}/********0808转换子函数********/void test(){uchar m;for (m=0;m<8;m++){P3=m; //送通道地址ST=0;_nop_();_nop_();ST=1;_nop_();_nop_();ST=0;//锁存通道地址启动转换_nop_();_nop_();_nop_();_nop_();while (EOC==0); //等待转换结束OE=1;ad_data[m]=P2;OE=0; //读取当前通道转换数据}}//************延时函数************void delay(uint i) //延时函数{uint y,j;for (j=0;j<i;j++){< p="">for (y=0;y<0xff;y++){;}}}//定时器/计数器T0产生0808的时钟void T0X(void)interrupt 1 using 0{CLK=~CLK;}void main(void){uchar i;uint temp1;SP=0X50;TMOD=0x02;TH0=246;TL0=246;ET0=1;EA=1;TR0=1;delay(10);init(); //lcd显示器初始化wc51r(0x80); //写入显示缓冲区起始地址为第1行第1列wc51ddr('V'); //第1行第1Vwc51ddr('A'); //第1行第2 Awc51ddr('L'); //第1行第3列显示字母Lwc51ddr('U'); //第1行第4列显示字母Uwc51ddr('E'); //第1行第5列显示字母 Ewc51ddr('0'); //第1行第6列显示数字0wc51ddr(':'); //第1行第7列显示字母:wc51r(0xC0); //写入显示缓冲区起始地址为第2行第1列wc51ddr('V'); //第2行第1Vwc51ddr('A'); //第2行第2 Awc51ddr('L'); //第2行第3列显示字母Lwc51ddr('U'); //第2行第4列显示字母Uwc51ddr('E'); //第2行第5列显示字母 Ewc51ddr('1'); //第2行第6列显示数字 1wc51ddr(':'); //第2行第7列显示字母:alarm = 0; //关闭led和报警buzzer = 0;while(1)</i;j++){<>。
51单片机简单数字电压表
单片机硬件实习任务书通信工程教研室指导教师:_基于单片机的简易数字电压表的设计目录1 引言 (1)2 设计总体方案 (2)2.1设计要求 (2)2.2 设计思路 (2)2.3 设计方案 (2)3 硬件电路设计 (3)3.1 A/D转换模块 (3)3.2 单片机系统 (6)3.3 复位电路和时钟电路 (8)3.4 LED显示系统设计 (8)3.5 总体电路设计 (11)4 程序设计 (13)4.1 程序设计总方案 (13)4.2 系统子程序设计 (13)5 仿真 (15)5.1 软件调试 (15)5.2 显示结果及误差分析 (17)结论 (20)参考文献 (21)附录程序代码和实物图 (24)心得体会 ......................................................... 错误!未定义书签。
1引言在电量的测量中,电压、电流和频率是最基本的三个被测量,其中电压量的测量最为经常。
而且随着电子技术的发展,更是经常需要测量高精度的电压,所以数字电压表就成为一种必不可少的测量仪器。
数字电压表简称DVM,它是采用数字化测量技术,把连续的模拟量转换成不连续、离散的数字形式并加以显示的仪表。
由于数字式仪器具有读数准确方便、精度高、误差小、测量速度快等特而得到广泛应用[1]。
传统的指针式刻度电压表功能单一,进度低,容易引起视差和视觉疲劳,因而不能满足数字化时代的需要。
采用单片机的数字电压表,将连续的模拟量如直流电压转换成不连续的离散的数字形式并加以显示,从而精度高、抗干扰能力强,可扩展性强、集成方便,还可与PC实时通信。
数字电压表是诸多数字化仪表的核心与基础[2]。
以数字电压表为核心,可以扩展成各种通用数字仪表、专用数字仪表及各种非电量的数字化仪表。
目前,由各种单片机和A/D转换器构成的数字电压表作全面深入的了解是很有必要的。
最近的几十年来,随着半导体技术、集成电路(IC)和微处理器技术的发展,数字电路和数字化测量技术也有了巨大的进步,从而促使了数字电压表的快速发展,并不断出现新的类型[4]。
使用STC12C5204AD单片机的数字电压表
使用STC12C5204AD单片机的数字电压表这是一块使用STC12C5204AD数字电压表的制作程序,P0.0-P0.3 共阴数码管位驱动端,P2口为共阴数码管段a-g及dp的段驱动端口,P0、P2口设置为推挽输出方式,段输出加470欧限流电阻,AD为8位,转换电压分度5/256=0.0195312V,分流电阻为实测阻值,AD值*0.0195312v/对地分流电阻,算出分流电流,然后用分流电流*分流电阻与限流电阻之和即为要显示的输入电压值。
业余使用,精度已经够用了,比那个小的指针的要准确多了。
其中涉及到端口设置的地方大家对照芯片手册更正。
#include ; //STC12C5204AD头文件 (6 K) 下载次数:15 #include ;//_nop_();#define uchar unsigned char#define uint unsigned int//sfr ADC_CONTR=0XBC;//adc使能位.ADC电源控制位sfr ADC_RES=0XBD;// adc数据高八位,即ADC值sfr P1ASF=0X9D;//P1各端口ADC使能端uchar led_bcd[]={0x3F,/*0*/ //共阴数码管0x06,/*1*/0x5B,/*2*/0x4F,/*3*/0x66,/*4*/0x6D,/*5*/0x7D,/*6*/0x07,/*7*/0x7F,/*8*/0x6F,/*9*/0x00,/* */0x7c /*b*/},ad_data;uint data dis[5]={0x00,0x00,0x00,0x00,0x00},ZZ; //定义四个显示数据单元和一个数据存储单元//dis[4,3,2,1,5] 显示:12.345为存储单元/************************************************ *******************//* 延时子程序*//**//**//************************************************ *******************/void delay(uint z)//延时子函数{uchar de1,de2;for(de1=z;de1>;0;de1--)for(de2=100;de2>;0;de2--);}/*******************************************************///显示子函数 display(h1,h2,h3,h4)//h1,h2,h3,h4 为四位LED数码管显示变量///////************************************************ *******/void display(uchar h1,uchar h2,uchar s1,uchar s2) ////LED显示函数(参数:LED1,LED2,LED3,LED4) {// 第一个数码管显示数据if(h1==0x3f) h1=0x00;//0消隐语句P2=h1;//delay(2);P00=0;delay(2);//参数2-10数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.P2=0X00;P00=1;/************************************************ *******/// 第二个数码管显示数据P2=h2|0x80;//delay(2);P01=0;delay(2); //参数2-10数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.P2=0X00;P01=1;//delay(5);/************************************************ *******/// 第三个数码管显示数据P2=s1;//delay(2);P02=0;delay(2); //参数2-10数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.P2=0X00;P02=1;// delay(5);/************************************************ *******/// 第四个数码管显示数据P2=s2;//delay(2);P03=0;delay(2); //参数2-10数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.P2=0X00;P03=1;//delay(5);}void init()//系统初始化函数{P2M1=0Xff; //强推挽推动a-g dpP2M0=0X00; //强推挽推动a-g dpP0M1=0X0f; //强推挽推动位P0M0=0X00; //强推挽推动位P0=0XFF;//初始化P2=0;//初始化/***定时器0初始化设置*****/TMOD = 0x01;TH0 = 0xFC; //初值1msTL0 = 0x18; //初值1msEA = 1;//开总中断ET0 = 1; //定时器0中断打开TR0 = 1; //打开定时器开始计时/*************************/ZZ=0;}void initADC() //AD初始化{P1ASF=0x01;//只使用P1.0端口做为ADC输入端.ADC_RES=0;//ADC数据寄存器清零ADC_CONTR=ADC_POWER|ADC_SPEEDLL; //打开ADC开关并设置转换速率详见STC12C52.Hdelay(2); //打开ADC并延时.}uchar readADC()//读AD{ADC_CONTR=ADC_POWER|ADC_SPEEDLL|0|ADC_START;_nop_();_nop_();_nop_();_nop_();while(!(ADC_CONTR&ADC_FLAG));//等待转换完成标志ADC_CONTR&=~ADC_FLAG;//close ADCreturn ADC_RES;//返回ADC值.}void main(){init();initADC();//初始化ADCad_data=readADC();//开机转换while(1){float j;uchar ad_data;while(ZZ>;=500) //500毫秒读一次ADC{ad_data=readADC();//读入ADC数据ZZ=0;}j=ad_data*19.5312;//由AD数据*19.5312(放大1000倍)=分流后的电压j=j/9890; //j(电压)/接地电阻(实测)9890欧j=j*60190;//j(电流)*(输入限流电阻(实测)60190欧+接地电阻(实测)9890欧) 计算出实际输入电压如果使用高精度电阻,则直接输入电阻值dis[4]=j/1000;dis[3]=dis[4]/10;dis[2]=dis[4]%10;//h=(h-(dis[3]*10+dis[2]))*100;dis[4]=j/10-dis[4]*100;//dis[4]=j%100;//小数位第一位dis[1]=dis[4]/10;dis[0]=dis[4]%10;//小数位第二位//delay(10000);}}void Timer0Interrupt(void) interrupt 1{ZZ++;//AD读取间隔时间控制TH0 = 0xFC;TL0 = 0x18;display(led_bcd[dis[3]],led_bcd[dis[2]],led_bcd[d is[1]],led_bcd[dis[0]]);}。