基于8051单片机的简易数字电压表设计姓名:吴建亮班级:电信1202学号:201203090224摘要电压表应用十分广泛,但大部分是模拟电压表,而由于其特性,反应速度慢,读数麻烦并且误差较大,所以为适应不断快速发展的高速信号领域,已经广泛使用数字电压表。本实验设计是基于51单片机开发板ESDM-3A实现的一种数字电压表系统。该设计采用8051单片机作为控制核心,以ADC0为模数转换数据采样,实现被测电压的数据采样,外部采用LCD12864液晶显示电压表的电压值。1.设计任务和要求1.1设计任务设计制作一个简易直流电压表,该直流电压表能测量直流电压。各硬件模块如图1.1所示。输入电压AD转换器8051单片机LCD12864图1.1硬件框图1.2设计要求(1)ADC0的工作方式设置如下:采用单端输入,模拟输入电压从P2.0输入;选择DDV作为参考电压源;转换时钟频率设置为2MHz;采用写“AD0BUSY”启动A/D转换。(2)采用定时器中断每隔0.5s启动一次A/D转换;通过ADC0中断服务程序读取转换值。2.设计方案2.1硬件电路硬件模块如上图1.1所示。输入电压由开发板上J8接口的第2脚0~5.0V接跳线至单片机扩展接口J7的第4脚P2.0,调节电位器RP3实现不同电压的输入。AD转换器、单片机、液晶屏在开发板已经连接好。下面简单介绍所用的器件。C8051F360单片机主要模拟和数字资源包括:(1)高速8051微控制器内核。(2)10位逐次逼近型A/D转换器。(3)10位电流输出D/A转换器。(4)两个模拟电压比较器CP1和CP0。(5)片内锁相环PLL。(6)扩充中断处理系统。(7)存储器,256字节内部RAM;1024字节XRAML;32字节闪存存储器。(8)数字资源,多达39个I/O引脚,全部为三态双向口,允许与5V系统接口。(9)时钟源,2个内部振荡器;80kHz低频低功耗振荡器。(10)片内调试电路。液晶屏HG1286412B功能和接口。1:VSS接地端2:VDD电源正,接+5V3:VO对比度调整,接电位器4:D/I(CS*)片选,也叫使能,接+5V5:R/W(SID*)数据输入端6:E(SCLK*)时钟输入端7~14:DB0~DB7并行数据总线15:PSB串并模式选择,串行模式下接地,并行模式下接+5V16:NC空引脚,不需要连接17:RSTB复位端,低电平有效,一般接+5V18:VEE对比度调整,接电位器19:BLA背光正极,接+5V20:BLK背光负极,接地表2.1液晶屏引脚接法12864液晶屏引脚按表2.1所示与单片机连接,在开发板上已经连接好,只需要配置好相应的寄存器即可。HG1286412B内部有三种不同RAM,DDRAM,CGRAM和GDRAM,其自带汉字字库,提供8192个中文字形,这些字可以字符串的形式直接显示。2.2程序设计程序的编写使用C语言,利用KeilμVision4进行程序的编写和烧录。程序执行时所对应的流程如下图2.1所示。图2.1程序执行流程图开始初始化定时器0.5S?启动A/D转换YESNOA/D转换是否结束?NO采集的数据进行转换YES液晶屏是否忙碌?YES液晶屏显示NO循环执行下面简单介绍各模块的设计思路。(1)时钟和定时器:选用内部24MHz振荡器,频率除2作为SYSCLK;定时器选择定时器1工作方式1,TMOD=0X10,采用循环的方法,定时器定时50ms,循环10次得0.5s,装入初值TH1=(65536-50000)/256,TL1=(65536-50000)%256。(2)ADC0:通过置“AD0BUSY”启动AD转换,采用10位采集通道,电压的最大值为3.3V,通过转换器的到的数值为AD_data=ADC0H×256+ADC0L,得到的实际电压为volt=AD_data×3.3/1023,通过AD0INT位,判断A/D转换是否结束。(3)液晶屏LCD12864:液晶屏操作分指令操作和数据操作,每次写指令或数据前先确认内部动作是否完成,通过读取忙碌状态进行确认。读、写指令或数据通过读或写4个内部寄存器WCOMADDR,WDATADDR,RCOMADDR和RDATADDR来完成。详细代码请见附录。3.测试结果分析组数电压表显示(V)单片机显示(V)误差10.4490.4450.89%21.0801.0740.56%31.6531.6510.12%42.5702.5670.12%53.1003.0960.13%表3.1测试结果根据表3.1的分析看,本次设计的数字电压表的符合要求,误差控制在1%内。4.总结本次的设计和实验采用了KeilμVision4进行C语言的编写和烧录,熟悉了Keil的操作,对8051单片机的定时器、A/D转换器、LCD12864液晶屏等模块有了一定的了解和认识。在程序的编写的过程和实际电路操作时遇到了种种问题,通过查阅大量的资料解决了问题,为以后的学习和实际应用奠定了基础。附录:本次设计实验的C语言代码:#includeC8051F360.H#defineucharunsignedchar#defineuintunsignedint#defineLEDENCS0xC004//LCD模块背光控制片选信号#defineWCOMADDR0xC008//写命令寄存器的地址#defineWDATADDR0xC009//写数据寄存器的地址#defineRCOMADDR0xC00A//读命令寄存器的地址#defineRDATADDR0xC00B//读数据寄存器的地址uintnum=0;ucharLEDCON=0x00;/*LCD模块背光控制字,最低位为0时关LED背光,最低位为1时开启LED背光,*/sbitSTART=P3^0;sbitSW0=P3^1;sbitSW1=P3^3;ucharcodehanzi10[]=电压显示;uintAD_data;uintvolt;uinta[4];uinti;voidTimeInit();//定时器初始化voidOscInit(void);//内部振荡器初始化voidPortIoInit(void);//端口初始化voidXramInit(void);//外部数据储存器初始化voidSmbInit(void);//I2C总线初始化voidUartInit(void);//异步串口通信接口初始化voidDacInit(void);//D/A转化器初始化voidAdcInit(void);//A/D初始化voidInt0Init(void);//外部中断初始化voidPcaInit(void);//PCA初始化voidInterruptsInit(void);//中断系统初始化voidInitDevice(void);//设备初始化voidCheckLcd();//检查LCD是否空闲子程序voidWriteCom(ucharn);//Lcd写指令子程序voidWriteData(ucharm);//Lcd写数据子程序voidInsitiLcd();//Lcd初始化子程序voidDispHan(ucharcode*a,ucharm,uchark);//显示汉字子程序voidDispShu(uinta,ucharm);//数字显示程序/*********************************************主函数/**********************************************/voidmain(){ucharxdata*addr;InitDevice();InsitiLcd();addr=LEDENCS;LEDCON=~LEDCON;*addr=LEDCON;DispHan(hanzi10,0x80,0x08);WriteCom(0x95);WriteData(0x56);while(1){if(TF1==1){TF1=0;TH1=(65536-50000)/256;TL1=(65536-50000)%256;num++;}if(num==10)//50ms*10=0.5s{num=0;AD0INT=0;AD0BUSY=1;while(AD0INT==0);AD_data=ADC0H*256+ADC0L;volt=AD_data*3.3/1023*1000;for(i=0;i4;i++){a[i]=volt%10;volt=volt/10;}DispShu(a[3],0x90);WriteCom(0x91);WriteData(0x2e);//DispShu(0x2e,0x91);DispShu(a[2],0x92);DispShu(a[1],0x93);DispShu(a[0],0x94);AD0BUSY=1;TR1=1;}}}voidTimeInit()//定时器1工作方式1,50ms{TMOD=0X10;TH1=(65536-50000)/256;TL1=(65536-50000)%256;EA=1;ET1=1;TR1=1;}/*********************内部资源初始化子程序***************函数功能:各种内部资源初始化******************************************************/voidOscInit(void)//内部振荡器初始化{SFRPAGE=0x0f;//选择特殊功能寄存器页地址OSCICL=OSCICL+4;OSCICN=0xc2;//允许内部振荡器,频率除2作为SYSCLK=12MHzCLKSEL=0x00;//选择内部振荡器SFRPAGE=0x00;}voidPortIoInit(void)//I/O口初始化{SFRPAGE=0x0f;P0MDIN=0xe7;//P0.3、P0.4模拟量输入P0MDOUT=0x83;//P0.0、P0.1、P0.7推拉式输出P0SKIP=0xf9;//P0.1、P0.2不被交叉开关跳过P1MDIN=0xff;//P1设置为数字量输入P1MDOUT=0xff;//P1设置为推拉式输出P1SKIP=0xff;//P1被交叉开关跳过P2MDIN=0x00;//P2设置为模拟量输入P2MDOUT=0xff;//P2设置为推拉式输出P2SKIP=0xff;P3MDIN=0xff;//P3设置为数字量输入P3MDOUT=0xff;//P3设置为推拉式输出P3SKIP=0xff;P4MDOUT=0xff;//P4设为推拉式输出XBR0=0x01;//使能UARTXBR1=0xC0;//禁止弱上拉,交叉开关允许SFRPAGE=0x00;return;}voidXramInit(void)//外部数据储存器初始化{SFRPAGE=0x0f;EMI0CF=0x07;//引脚复用方式SFRPAGE=0x00;return;}voidSmbInit(void)//I2C总线初始化{SMB0CF=0xc1;//定时器T1溢出作为时钟return;}voidUartInit(void)//异步串口通信接口初始化{SCON0=0x00;//10位UARTreturn;}voidDacInit(void)//D/A转化器初始化{IDA0CN=0xf2;//IDA0使能,写IDA0H触发DAC输出更新,2mA满度输出return;}voidAdcInit(void)//A/D初始化{ADC0CN=0X80;//adc0一直跟踪,AD0BUSY写“1”启动ADC0CF=0x28;//转换率2Mhz,右对齐REF0CN=0X08;//选择Vdd做基准电压AMX0P=0X08;//单端输入P2.0AMX0N=0X1F;EIE1=0x08;//允许ADC中断return;}voidInt0Init(void)//外部中断初始化{IT01CF=0x05;//选择P0.5为INT0IT0=1;//INT0下降沿触发return;}voidPcaInit(void)//PCA初始化{