电子系统实验报告实验三简易数字电压表设计姓名张巧玲指导教师贾立新课程电子系统设计与实践专业班级自动化1004班学院信息工程学院一、设计题目采用C8051F360单片机最小系统设计一简易数字电压表,实现对0~2.4V直流电压的测量,原理框图如图1所示。
模拟输入电压通过一只1 kΩ电位器产生,采用C8051F360 单片机内部的A/D 转换器将模拟电压转换成数字量后换算成电压值,用十进制的形式在LCD 上显示。
A/D 转换的输入模拟信号由实验板PR3 电位器产生的0~3.3V 的直流电压信号,用一根杜邦实验线将J8 的0~3.3V 输出插针与J7 口的P2.0 插针相连。
注意A/D 转换器模拟输入电压的范围取决于其所选择的参考电压,如果A/D 转换器选择内部参考电压源,其模拟电压的范围为0~2.4V,如果选择外部电源作为参考电压,则其模拟输入电压范围为0~3.3V。
测试时,A/D转换器的模拟输入信号可通过一个电位器产生。
图1 简易数字电压表实验示意框图二.设计方案(1)简易数字电压表设计程序流程图如图2所示。
图2 简易数字电压表设计程序中A/D转换和计时流程图(2)简易数字电压表实验板连接图如图3所示。
此外,还需用一根杜邦实验线将J8 的0~3.3V 输出插针与J7 口的P2.0 插针相连。
图3简易数字电压表设计实验板接线图三、详细设计1.简易数字电压表设计相应C8051F360和LCD初始化程序⑴内部振荡器初始化:OscInit()⑵ I/O端口初始化:PortIoInit()⑶外部数据存储器接口初始化:XramInit()⑷定时器初始化:TimerInit()⑸中断系统初始化:Int0Init()⑹ ADC0初始化:void ADC_Init()⑺ PCA初始化:Int0Init()2.电压转换方式将电压转换成十进制:AT=ADC0H*256+ADC0L;volt=AT*3.31/1024;voltage=volt*1000;for(i=0;i<4;i++){v[i]=voltage%10;voltage=voltage/10;}3. LCD显示接口的设计当时间到达设定值,即0.5s后,执行以下程序将所测的电压值在LCD屏幕上第三排显示出来。
WriteCom(0x8C);WriteData(v[3]+0x30);WriteData(0x2e);WriteData(v[2]+0x30);WriteData(v[1]+0x30);WriteData(v[0]+0x30);4.实验中AD转换方式选用逐次逼近型,A/D转换完成后得到10位数据分为高低字节存放在寄存器ADCOH和ADC0L中,此处选择右对齐,转换时针为2MHZ。
5.选择内部参考电压2.4伏为基准(在实际单片机调试中改为3.311伏),正端接P2.0,负端接地。
四、测试结果在0V~3.3V中取十组测试数据,每组间隔约为0.3V左右,实验数据如表由表1可知,10组数据中最大误差的一组是:其余的误差都不超过,并且大部分数据误差都只有左右,满足小于0.01V的设计误差要求,即本实验的设计可以满足实验要求。
五、心得体会通过这次对简易电压表的设计,我对单片机的最小系统设计有了新的理解,对于硬件和软件的配合也更熟练了。
在这个实验中LCD显示模块的CPLD部分由FPGA充当,芯片本身自带程序,因而这个部分不需要再通过QUARTUS 软件进行编程。
在参考电压选择过程中发现,单片机实际最大电压并不是2.4v而是3.3v,则在转换中将3.3V替换2.4V即可。
六.代码附录/*简易数字电压表*/#include <C8051F360.H>#define uchar unsigned char#define uint unsigned int#define WCOMADDR 0xC008 //写命令寄存器的地址#define WDATADDR 0xC009 //写数据寄存器的地址#define RCOMADDR 0xC00A //读命令寄存器的地址#define RDATADDR 0xC00B //读数据寄存器的地址#define KEYCS 0xC00Cuchar code hanzi[] = "简易数字电压表";uchar code keynum[]="键值";uchar code keyc[]="次数";uint time=0;float volt;uint v[4];uint AT,voltage;uchar keyn,keycode;void OscInit(); //内部振荡器初始化void PortIoInit(); //I/O端口初始化void XramInit(); //外部数据存储器接口初始化void PcaInit(); //PCA初始化(设置看门狗定时器的工作状态)void InitDevice(); //内部资源初始化void CheckLcd(); //检查LCD是否空闲子程序void WriteCom(uchar n); //Lcd写指令子程序void WriteData(uchar m); //Lcd写数据子程序void InsitiLcd(); //Lcd初始化子程序void DispHan( uchar code *a,uchar m,uchar k);//显示汉字子程序void TimerInit(); //定时器初始化void InterruptsInit(); //中断系统初始化void ADC_init(); //ADC0初始化详见书本P144 void Int0Init(); //外部中断初始化void main(){uchar i;InitDevice(); //F360初始化InsitiLcd(); //LCD模块初始化ADC_init();DispHan(hanzi,0x90,0x0e); //显示“键盘显示测试程序”AD0BUSY=1;while(1){if(TF0==1){TF0=0;TL0=0xf0;TH0=0xd8; //重置时间常数10mstime++;}if(time >=49){time = 0;AT=ADC0H*256+ADC0L;volt=AT*0.003234;voltage=volt*1000;for(i=0;i<4;i++){v[i]=voltage%10;voltage=voltage/10;}WriteCom(0x8d);WriteData(v[3]+0x30);WriteData(0x2e);WriteData(v[2]+0x30);WriteData(v[1]+0x30);WriteData(v[0]+0x30);TR0=1;AD0BUSY=1;}}}void ReadKey() interrupt 0{uchar xdata *addr;uchar c1,c2;addr=KEYCS;keycode=*addr;keycode&=0x0F;keyn++;DispHan(keynum,0x88,0x04);WriteCom(0x8b);if(keycode<10){WriteData(0x30);WriteData(keycode+0x30);}else{c1=keycode%10;c2=keycode/=10;WriteData(c2+0x30);WriteData(c1+0x30);}DispHan(keyc,0x98,0x04);WriteCom(0x9b);if(keyn==10)keyn=0;WriteData(keyn+0x30);}void Int0Init(){EA=1;IT01CF=0x05;EX0=1;IT0=1;}void OscInit(void) //内部振荡器初始化{SFRPAGE=0x0f; //选择特殊功能寄存器页地址OSCICL=OSCICL+4;OSCICN=0xc2; //允许内部振荡器,频率除2作为SYSCLK=12MHzCLKSEL=0x00; //选择内部振荡器SFRPAGE=0x00;}void ADC_init(){ADC0CF=0x28; // 选择内部参考电压2.4V为基准ADC0CN=0x80; //正端接P2.0AMX0P=0x08; //负端接地AMX0N=0x1F; //右对齐,转换时针为2MHZREF0CN=0x08; //写AD0BUSY启动A/D转换器}void TimerInit(){TMOD=0x01;TH0=0xd8;TL0=0xf0;TR0=1;}void InterruptsInit(void){EA=1;ET0=1;EX0=1;PX0=1;IE0=0;}void PortIoInit(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=0xff; //P2设置为数字量输入// P2MDOUT=0xff; //P2设置为推拉式输出// P2SKIP=0xff;P3MDIN=0xff; //P3设置为数字量输入P3MDOUT=0xff; //P3设置为推拉式输出P3SKIP=0xff;P4MDOUT=0xff; //P4.5设为OC输出,其余推拉式输出XBR0=0x01; //使能UARTXBR1=0xC0; //禁止弱上拉,交叉开关允许SFRPAGE=0x00;return;}void XramInit(void) //外部数据储存器初始化{SFRPAGE=0x0f;EMI0CF=0x07; //引脚复用方式SFRPAGE=0x00;return;}void PcaInit(void) //PCA初始化{PCA0CN=0x40; //允许PCA计数器/定时器PCA0MD=0x00; //禁止看门狗定时器return;}void InitDevice(void){OscInit();PortIoInit();XramInit();//SmbInit();//UartInit();ADC_init();TimerInit();InterruptsInit();Int0Init();PcaInit();return;}void CheckLcd(){uchar temp = 0x00;uchar xdata *addr;while (1){addr=RCOMADDR;temp=*addr;temp &= 0x80;if(temp == 0x00)break;}}void WriteCom(uchar n){uchar xdata *addr;CheckLcd();addr=WCOMADDR;*addr=n;}void WriteData(uchar m){uchar xdata *addr;CheckLcd();addr=WDATADDR;*addr = m;}void InsitiLcd(){WriteCom(0x30); //设为基本指令集WriteCom(0x01); //清屏WriteCom(0x0c); //开整体显示}void DispHan( uchar code *a,uchar m,uchar k) // 书本177页有详细解释 {uchar dat, i, j, length;length = k/2;WriteCom(m);for (i=0;i < length;i++){j = 2*i;dat = a[j];WriteData(dat);dat = a[j+1];WriteData(dat);}WriteData(0x3a);}void DispShu( unsigned int a,uchar m){WriteCom(m);WriteData(a+0x30);}。