单片机实验报告 计算器讲解
单片机计算器报告
基于51单片机实验报告(计算器)一.计算器模块1.功能介绍利用8051 单片机硬件资源和常用外围电路如LCD1602,七段数码管,时钟(DS1302)温度传感器(18B20)等实现一个能做简单四则运算,并具有时钟显示,温度显示附加功能的计算器。
2.设计方案利用STC89C52为内核的单片机,PC机。
四则运算利用4*4矩阵键盘实现从0—9和运算符号的输入,并将操作过程和结果显示在LCD1602上。
时钟显示和温度显示,可以利用DS1302产生年份,月份,日期,星期,时,分,秒的数据,并将数据送往LCD1602显示,同样可以利用单片机开发板上面集成的DS18B20温度传感器来测试周围环境的温度,将获取的温度通过在LCD1602来显示。
系统设计框图3.具体实现代码计算器四则运算部分主要分为键盘扫描的键值读取,判断运算符号实现乘除优先级计算,LCD1602显示。
键盘扫描常用的有行扫描法,线反转法,此处我们用行扫描法,可以更明了读取键值。
unsigned char temp;key = null;//第一行按键P3 = 0xfe;temp = P3;temp = temp & 0xf0;if (temp != 0xf0){delay(10); //延时软件去抖动temp = P3;temp = temp & 0xf0;if (temp != 0xf0) //确认有键按下{temp = P3;switch (temp){case 0xee:key = 'D'; //读键值break;case 0xde:key = 0;break;case 0xbe:key = '=';break;case 0x7e:key = '/';break;}flag++;}}读完按键值之后我们需要读取运算的数字与运算符号,通过判断键值为数字则通过nun=nun*10+key,计算出数字,判断键值为运算符号则读出数字和键值。
单片机串口计算器实验报告
单⽚机串⼝计算器实验报告[⼆0⼀三年]1、作品简介本作品的名称是串⼝计算器,其功能是计算机将数据或者字符串发送给单⽚机,单⽚机根据要求可以把⽤户的相应指令进⾏整合运算,并把这个数据的结果显⽰到串⼝助⼿和数码管上,完成计算的功能。
其中还涉及到了浮点数的运算,我们将浮点数精确到了⼀位,在这个计算其中还可以对负数进⾏运算,并将负数显⽰到数码管和串⼝助⼿。
1、串⾏通信功能:实验板和PC电脑通过USB线相连,使MCU和PC软件“串⼝助⼿”能够进⾏串⾏通信。
(1)当实验板上电时默认波特率为9600bps,并发送欢迎词和提⽰词,例如“Welcome to Calculator V1.0”,"You can press key1 and key2to change baud rate."....(2)当实验板上按键1按下时波特率变更为4800bps,按键2按下时波特率变更为9600bps,并⽤两个LED灯指⽰相应的波特率。
2、计算器功能通过串⼝助⼿发送框发送需要计算的公式,例如20*4=,MCU收到后解析公式并计算结果,将结果返回给串⼝,例如“The result is 80”,同时将计算结果显⽰在数码管上,具体细节如下:(1)可以进⾏加(+)、减(-)、乘(*)、除(\)、取余(%)运算;(2)整形、浮点型运算;(3)当计算结果为整形数时,有效的运算结果范围是-999~9999,超过此结果,返回相应的提⽰符,例如“The result is out of range.”,数码管上提⽰“Err”;(4)当计算结果为浮点数时,有效的运算结果范围是-99.9~999.9,数码管上显⽰时保留1位⼩数点,超过此结果,返回相应的提⽰符,例如“The result is out of range.”,数码管上提⽰“Err”。
期间,本⼈编写了串⼝助⼿程序,⽅便本⼈在调试过程中发现错误,改正错误。
这是⼀个副产品。
单片机计算器课程设计报告程序讲解
单片机课程设计报告一、内容摘要用单片机做一个四则运算的计算器,首先查资料,了解各个电路的功能,事先须熟悉Keil和Proteus两个软件,及它们的联调,程序和仿真完成,就焊接电路板,焊接完,最后就系统联调,直到得出结果。
二、功能要求利用89c51作为主控器组成一个四则运算的计算器。
三、电路原理图电路图说明:(1)键盘的列扫描接单片机P2口的低4位,行扫描接单片机P1口的低4位;(2)数码管的段选通过单片机的P0口接74LS244来驱动,数码管的位选接单片机的P2口;(3)晶振电路为单片机提供时钟频率;(4)复位电路为单片机提供复位信号。
四、计算器功能说明(1)通过数码管来显示键盘的按键,显示被加数(减数……),加数(……),运算结果;(2)本计算器适合不大于八位整数的加、减、乘、除,要求结果也不大于八位整数,否则出错显示,显示(HELLO);(3)在还没按一个数之前就按下=,+,--,*或/,则显示错误;按下+,--,*或/后,立马按下=,显示错误;(4)若接连好了好几运算符键,实际参与运算的是最后一次按的运算键;(5)本计算器有连加,连减,连乘,连除功能,例如:2+5=7+5=12--5=7*5=35/5=7;(6)减法可以实现负数,除法可以显示小数。
五、软件仿真软件设计时,我是分一个一个模块设计的,设计顺序如下:(1)数码管显示函数void displayljy(void)//"显示"子函数{uchar array3[32]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40,0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x38,0x3e,0x6e,0xbe};uchar *p=array,count=0xfe,i,time,time1;F0=1;while(F0){i=*p;P2=count;P0=array3[i];for(time1=0x0c;time1>0x00;time1--)for(time=0xff;time>0x00;time--);p++;count=_crol_(count,1);if(count==0xfe)F0=0;}}(2)判断是否有键按下子函数void iskeyyou(void)//"判断是否有键按下"子函数{P2=0x00;P1|=0x0f;a=P1;a|=0xf0;}(3)键扫子函数void inkeylove(void)//"判断按下的是什么键"子函数{uchar b=0xfe,c=0x00,d;uchar array4[16]={0x07,0x08,0x04,0x05,0x01,0x02,0x0f,0x00,0x09,0x0a,0x06,0x0b,0x03,0x0c,0x0e,0x0d};F1=0;iskeyyou();if(a!=0xff){displayljy();displayljy(); iskeyyou();if(a!=0xff){F0=1;while(F0){P2=b;P1|=0x0f;if(P10==0){a=0x00;F1=1;}else if(P11==0){a=0x02;F1=1;}else if(P12==0){a=0x04;F1=1;}else if(P13==0){a=0x06;F1=1;}else{a=c;a%=4;if(a==0x01){a=0x07;c+=a;}elsec++;b=_crol_(b,1);if(b&0x10==0){F0=0;a=0xff;}}while(F1){a+=c;a=array4[a];d=a;while(a!=0xff){displayljy();iskeyyou();}a=d;F1=0;F0=0;}}}}}(4)两个变形的子函数void bian1(void)//"将uchar型变量转化为ulong型变量"子函数{uchar i;for(i=7;i>0;i--){if(array[i]==0x10)array[i]=0x00;if(array1[i]==0x10)array1[i]=0x00;}num1=(ulong)array1[7]*10000000;num1+=(ulong)array1[6]*1000000;num1+=(ulong)array1[5]*100000;num1+=(ulong)array1[4]*10000;num1+=(ulong)array1[3]*1000;num1+=(ulong)array1[2]*100;num1+=(ulong)array1[1]*10;num1+=(ulong)array1[0];num2=(ulong)array[7]*10000000;num2+=(ulong)array[6]*1000000;num2+=(ulong)array[5]*100000;num2+=(ulong)array[4]*10000;num2+=(ulong)array[3]*1000;num2+=(ulong)array[2]*100;num2+=(ulong)array[1]*10;num2+=(ulong)array[0];}void bian2(void)//声明"将ulong型变量转化为uchar型变量"子函数{uchar i=7,F0=1;if(num1>99999999)error();else{array[7]=(uchar)(num1/10000000);array[6]=(uchar)(num1%10000000/1000000);array[5]=(uchar)(num1%1000000/100000);array[4]=(uchar)(num1%100000/10000);array[3]=(uchar)(num1%10000/1000);array[2]=(uchar)(num1%1000/100);array[1]=(uchar)(num1%100/10);array[0]=(uchar)(num1%10);while(i>0&&F0){if(array[i]==0x00){array[i]=0x10;i--;}elseF0=0;}}}(5)主函数void main(){uchar r7=0x00,i;while(1){displayljy();inkeylove();if(a!=0xff)//如果有键输入,继续往下执行,否则从新开始{if(a==0x0f) //如果输入的是"清除"键,将显示器清屏,同时清存放运算符号的单元{r7=0x00;for(i=0;i<8;i++){array[i]=0x10;array1[i]=0x10;}}else if(a==0x0e)//如果输入的是"=",继续往下执行,否则从新开始{if(array1[0]==0x10)//如果未按下第二个数之前就按下“=”,则出错显示error();else if(r7==0x0d)//如果r7中存放的是"+",则执行加运算{bian1();jia();bian2();r7=0x00;for(i=0;i<8;i++)array1[i]=0x10;}else if(r7==0x0c)//如果r7中存放的是"-",则执行减运算{bian1();jian();r7=0x00;for(i=0;i<8;i++)array1[i]=0x10;}else if(r7==0x0b)//如果r7中存放的是"*",则执行乘运算{bian1();cheng();bian2();r7=0x00;for(i=0;i<8;i++)array1[i]=0x10;}else if(r7==0x0a)//如果r7中存放的是"÷",则执行除运算{bian1();chu();r7=0x00;for(i=0;i<8;i++)array1[i]=0x10;}elseerror();//如果r7没有存进运算符,则转出错处理}else{if(r7!=0x00)//如果已按过运算键,往下执行,否则转else{if(a>0x09&&a<0x0e)//如果还按下运算键,则后按的取代前面按的r7=a;else if(array1[0]==0x10)//判断是不是输入加数(减数...)的第一个数{for(i=0;i<8;i++)//是的话,将被加数(被减数...)存入array1中array1[i]=array[i];for(i=0;i<8;i++)array[i]=0x10;for(i=7;i>0;i--)//array中存入加数(减数...)array[i]=array[i-1];array[0]=a;}else //不是输入加数(减数...)的第一个数{if(array[7]!=0x10)//如果加数(减数...)已是八位整数,则转出错处理error();else{for(i=7;i>0;i--)//否则将加数左移array[i]=array[i-1];array[0]=a;}}}else//之前还没有运算键按下{if(a>0x09)//有运算键按下{if(array[0]==0x10)//但是在运算键按下之前没有输入被加数,则转出错error();elser7=a;//否则将运算键输入r7中保存}else if(array[7]!=0x10)//如果被加数已是八位整数,则转出错error();else //否则将被加数左移{for(i=7;i>0;i--)array[i]=array[i-1];array[0]=a;}}}}}}(6)加、减、乘、除、出错显示子函数void jia(void)//"加运算"子函数{num1+=num2;}void jian(void)//"减运算"子函数{uchar i;if(num1>num2){num1-=num2;bian2();}else if(num1==num2){for(i=1;i<8;i++)array[i]=0x10;array[0]=0x00;}else{num1=num2-num1;bian2();if(array[7]!=0x10)error();elsearray[7]=0x11;}}void cheng(void)////声明"乘运算"子函数{num1*=num2;}void chu(void)//"除运算"子函数{uchar i,j=0x00,k;double num3;num3=(double)(num1)/(double)(num2);num1=(ulong)(num3);num3-=num1;if(num3==0||num1>9999999)bian2();else{bian2();while(array[7]==0x10){j++;for(i=7;i>0;i--)array[i]=array[i-1];array[0]=0x10;}array[j]+=0x12;k=j-1;while(k>0){num3*=10;num2=(ulong)(num3);num3-=num2;array[k]=(uchar)(num2);k--;}num3*=10;num2=(ulong)(num3);array[0]=(uchar)(num2);while(array[0]==0x00){for(i=0;i<7;i++)array[i]=array[i+1];array[7]=0x10;}}}void error(void)//"出错显示"子函数(出错显示"HELLO") {array[7]=0x10;array[6]=0x10;array[5]=0x10;array[4]=0x1d;array[3]=0x0e;array[2]=0x1c;array[1]=0x1c;array[0]=0x12;}(7)全局变量定义,函数声明等#include <reg52.h>#include <intrins.h>//循环左右移要用该头文件(-cror-(),-crol-())#define uchar unsigned char#define ulong unsigned longuchar array[8]={0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10};uchar array1[8]={0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10};uchar a;ulong num1=0,num2=0;sbit P10=P1^0;sbit P11=P1^1;sbit P12=P1^2;sbit P13=P1^3;sbit F1=PSW^1;//定义一个标志位,F0在头文件里已定义void displayljy(void);//声明"显示"子函数void inkeylove(void);//声明"判断按下的是什么键"子函数void iskeyyou(void);//声明"判断是否有键按下"子函数void bian1(void);//声明"将uchar型变量转化为ulong型变量"子函数void bian2(void);//声明"将ulong型变量转化为uchar型变量"子函数void jia(void);//声明"加运算"子函数void jian(void);//声明"减运算"子函数void cheng(void);//声明"乘运算"子函数void chu(void);//声明"除运算"子函数void error(void);//声明"出错显示"子函数六、系统联调在焊接完板子后,我首先并没有把整个计算器的程序下进去,只是下了个显示的小程序,结果数码管的第四位没显示,首先我想段选肯定不会有错的,检查了程序对应的那个数和程序中位选的设置都没错,我想应该是接线中的位选错了,结果我用万用表检查电路发现也没错,这下我就纠结了,搞不清状况了,可是无意之中我按了板子,发下那个数码管显示了正确的数,但是只是一瞬间的事,我想肯定是我有个地方没焊稳,我就一个地方一个地方的按,最终定位在了单片机,单片机的底座我用的是单排母不是专门配的底座,因为用排母取下放上都比那个专门配的底座容易,我就重新认真的把底座补焊了下,结果就行了,接下来我就把计算器的程序下进去了,成功了,太开心了。
单片机实践简易计算器实验报告
零基础DIY单片机简易计算器实践
单片机是一种很有趣的微处理器,它广泛应用于电子产品中。
学习单片机可以帮助我们更深入理解计算机原理和底层运作。
本实验将介绍如何使用单片机来制作一个简易计算器。
所需材料:
1. 单片机开发板
2. 4位7段显示器
3. 数字按键开关
4. 杜邦线
5. 电位器
6. 板子外壳
步骤1:连接电路
将数码管和数字按键开关与单片机开发板连接。
使用杜邦线将每个组件的引脚连接到开发板的相应引脚。
电位器可用于调节数码管显示的亮度。
步骤2:编写程序
使用C语言编写程序。
程序需要识别按键输入的数字和运算符,
并根据不同的情况显示计算结果。
程序中需要使用条件语句、循环语
句和函数等基本语言结构。
步骤3:测试程序
将编写好的程序上传到单片机开发板中。
测试程序的过程中要注
意按键输入的顺序和正确性。
如果按键输入错误,程序需要能够正确
地识别并给出错误提示。
步骤4:完成外壳
将单片机开发板和数码管装进铝盒中,并将数字按键开关与外壳
相连。
在外壳上打开一个窗口,以便能看到数码管和按键。
为了美观,可以涂上一些喜欢的颜色或加上小贴纸等装饰。
通过这个实验,我们深入了解了单片机的基本原理和运作方式,
掌握了C语言编程语言基础知识,并制作了一个实用的计算器。
在实
践中,我们不仅锻炼了问题解决能力和动手能力,还增强了对电子产
品的兴趣和信心。
51单片机简易计算器设计报告
51单片机简易计算器设计报告
本文将介绍51单片机简易计算器的设计报告。
该计算器通过
16位的LCD显示屏实现了基本计算功能,包括加、减、乘、除、取反、开方等。
1. 硬件设计
该计算器的核心部件是STC89C52单片机。
STC89C52是一种
高性能、低功耗的8位单片机,拥有8KB的Flash程序存储器和128字节的内部RAM,可提供多种功能和通讯接口。
通过
I/O口与LCD模块通讯,实现输出功能。
该计算器使用16位的LCD显示屏,显示范围为-99.99~99.99,共有6个数字位。
显示屏使用了ST7920控制器,可通过串行、并行等多种方式控制。
2. 软件设计
该计算器的软件设计主要包括三部分:键盘扫描,计算功能和LCD显示。
键盘扫描:该计算器采用4x5矩阵键盘,通过程序对键盘进行扫描,实现对不同按键的检测。
计算功能:该计算器可以实现基本的四则运算、取反、开方等功能。
对于四则运算,通过栈来实现计算,将运算符压入栈中,然后将操作数从栈中取出进行计算。
LCD显示:该计算器使用16位的LCD显示屏,通过程序控制数据和命令的传输,将计算结果显示在LCD屏幕上。
3. 总结
通过对51单片机简易计算器的设计报告,可以看出该计算器实现了基本的计算功能,通过硬件设计和软件设计相结合,将计算器的功能实现得十分完整。
该计算器的设计初步掌握了51单片机的应用,有助于后续项目的开展。
单片机实践简易计算器实验报告
单片机实践简易计算器实验报告本次实验的目的是通过单片机实现一个简易计算器,实现加减乘除四则运算。
在实验过程中,我们使用了STC89C52单片机,通过编写程序实现计算器的功能。
实验步骤:1. 确定硬件电路连接我们需要确定硬件电路连接。
本次实验使用的是STC89C52单片机,需要将其与LCD1602液晶屏、4x4矩阵键盘、蜂鸣器等硬件连接。
具体连接方式如下:STC89C52单片机:P0口:连接LCD1602液晶屏的数据线D0-D7P1口:连接LCD1602液晶屏的控制线RS、RW、EP2口:连接4x4矩阵键盘的行线R1-R4P3口:连接4x4矩阵键盘的列线C1-C4P4口:连接蜂鸣器2. 编写程序接下来,我们需要编写程序实现计算器的功能。
程序主要分为以下几个部分:(1)LCD1602液晶屏初始化(2)4x4矩阵键盘扫描(3)计算器功能实现(4)LCD1602液晶屏显示结果3. 调试程序编写完程序后,我们需要进行调试。
在调试过程中,我们需要注意以下几点:(1)检查硬件连接是否正确(2)检查程序是否有语法错误(3)检查程序是否能够正常运行4. 实验结果经过调试,我们成功实现了一个简易计算器。
在使用过程中,用户可以通过4x4矩阵键盘输入数字和运算符,计算器会自动进行计算,并在LCD1602液晶屏上显示结果。
同时,计算器还具有清零、退格等功能,方便用户进行操作。
总结:通过本次实验,我们学习了单片机的基本原理和编程方法,掌握了如何使用单片机实现一个简易计算器。
同时,我们还学习了如何进行硬件电路连接和程序调试,提高了我们的实践能力和动手能力。
单片机课程设计报告简易计算器
{a=a*10+a2[i];
}
if(a2[i]!=14&&a2[i]>9)
//
{m=1; w=a2[i];
四则运算的判断
}
if(a2[i]<10&&m==1) //
第二个数
{b=b*10+a2[i];
}
if(a2[i]==13||o==1)
//
清零
{o=0;
lcd_w_cmd(0x01);
lcd_w_cmd(0x80);
4 软件调试........................................................8 个人小结...........................................................8 参考文 献........................................................... 9 附 录............................................................... 9
lcd_w_dat(a1[ge]);}
if(wan==0&&qian!=0)
//
千位显示
{lcd_w_dat(a1[qian]);
lcd_w_dat(a1[bai]);
lcd_w_dat(a1[shi]);
lcd_w_dat(a1[ge]);}
if(wan==0&&qian==0&&bai!=0) //
delay1();
E=1;
delay1();
P1=dat;
基于51单片机的计算器设计实验报告
实验报告
班级:
12电子2
姓名:
风间
学号:
2015年1月6日
一、
1.初步尝试运用单片机进行系统设计;
2.掌握矩阵键盘的中断扫描显示;
3.掌握液晶或数码管的动态显示;
4.掌握数据的存储和掉电保护。
二、
Keil c、proteus、及单片机开发板。
三、
基本要求:
1完成标准型计算器的基本功能
2.4*4矩阵键盘(0~9、+、-、*、/、=、%进行数据的输入及加、减、乘、除 基本运算,运用1602液晶或数码管进行显示
FDET^VD
PCLVA11
PH 5V**7
WTJM^
■ 口j
PQ卅Q+
prw肚旺
RBT
PDVAA<
PD7MD7
R.1W
PEMi口
rtsti
Ml
K
iP7伽ii
f13
P7<w'ftn
PHAU
l£
PW
P3fyp-aJi
・H IfOCIJi i
P1Z
pa^nrrn
P1J
333!llf~1
P3mTEJ
F 1 f
void delay(uchar z) // {
uchar y;
for(z;z>0;z--)
for(y=0;y<110;y++); }
延迟函数
void check()
{
do{
P0=0xFF;
rs=0;
rw=1;
lcde n=0;
//判断忙或空闲
//禁止读写
delay(1);
lcde n=1;
单片机设计实验报告简单计算器的设计
目录1.总体方案选择 (2)1.1 实验要求: (2)1.2方案设计 (2)2.硬件原理电路图的设计及分析 (3)2.1主控模块 (3)2.1.1 STC89C52单片机主要特性 (3)2.1.2 STC89C52单片机管脚图 (4)2.1.3 STC89C52单片机的中断系统 (5)2.1.4 STC89C52单片机的定时/计数器 (5)2.2矩阵键盘模块设计: (5)2.2.1矩阵键盘原理介绍 (5)2.2.2矩阵键盘电路设计 (6)2.3 LCD液晶显示器简介 (7)2.3.1液晶模块简介 (7)2.3.2液晶显示部分与89S52的接口 (8)3系统软件设计 (10)3.1系统软件流程图 (10)3.2系统整体原理图 (11)4.系统调试 (12)4.1硬件调试 (12)4.2软件调试 (12)4.3调试结果 (13)5.心得体会131.总体方案选择1) 1.1 实验要求:2)通过小键盘实现数据的输入, 并在LED数码管上显示3)实现+、-、*、/4)在LED数码管上显示结果并有清零, 退出功能1.2方案设计本系统以STC89C52单片机为控制核心, 对系统进行初始化, 主要完成对键盘的响应、液晶显示灯功能的控制, 起到总控和协调各模块之间工作的作用。
单片机通过检测键盘读取使用者按下对用功能的按键, 然后通过单片机内部运放把运算的结果显示在液晶屏幕上。
图1-1系统结构框图本系统结构如图1-1所示, 本设计可分为以下模块: 单片机主控模块、键盘模块、功率放大模块、闹铃模块、按键设置模块。
下面对各个模块的设计方案逐一进行论证分析。
2.硬件原理电路图的设计及分析2.1主控模块STC89C52有40个引脚, 4个8位并行I/O口, 1个全双工异步串行口, 同时内含5个中断源, 2个优先级, 2个16位定时/计数器。
STC89C52的存储器系统由4K的程序存储器(掩膜ROM), 和128B的数据存储器(RAM)组成。
实验报告之计算器(单片机C语言)
计算器实验报告电子08-1班XX学号:0850213134目录实验目的 (3)实验器材 (4)实验任务 (5)实验步骤 (6)1、在protues中画好原理图 (6)2、在keil中编写程序 (6)3、仿真 (7)4、程序清单 (7)实验小结 (15)学习运用4*4的矩阵键盘,学会使用单片机编程扫描法学习使用1602液晶显示,对其初始化学习综合使用液晶、键盘,学会综合编程上机仿真计算机一台Keil软件Protues软件运用at89s51和1602液晶与按键开关来制作简单的两位的加减乘除的简单计算器。
1、在protues中画好原理图2、在keil中编写程序编写过程编译通过3、仿真4、程序清单#include<reg51.h> //包含头文件#define uc unsigned char //宏定义sbit rs=P3^5; //位申明sbit rw=P3^6;sbit e=P3^7;void csh(); //函数申明void jj();uc keyscan();void wirte_com(uc com);void wirte_data(uc date);void delay(unsigned int z);uc code table[]="123+456-789*0=#/"; //定义表格uc code table1[]="0123456789";uc code table2[]="2 wei ji suan qi";uc temp,bb,num,a,b,c,d,shi,ge,bai,qi; //定义全局变量unsigned int i;void main() //主函数{csh(); //初始化while(1) //大循环{for(i=0;i<16;i++){wirte_data(table2[i]);}wirte_com(0xc0);num=99;keyscan();a=table[num]-48;wirte_data(table[num]);num=99;keyscan();wirte_data(table[num]);if(table[num]>=48&&table[num]<=57){d=table[num]-48;a=a*10+d;num=99;keyscan();b=table[num];wirte_data(b);}else{b=table[num];}num=99;keyscan();c=table[num]-48;wirte_data(table[num]);num=99;keyscan();if(table[num]>=48&&table[num]<=57) {wirte_data(table[num]);d=table[num]-48;c=c*10+d;}switch(b){case '+':i=a+c;break;case '-':jj();break;case '*':i=a*c;break;case '/':i=a/c;break;default:break;}qi=i/1000;bai=i%1000/100;shi=i%100/10;ge=i%10;keyscan();while(num!=13) keyscan();wirte_data(table[13]);if(qi!=0){wirte_data(table1[qi]);wirte_data(table1[bai]);wirte_data(table1[shi]);wirte_data(table1[ge]);while(num!=14) keyscan();wirte_com(0x01);}else if(bai!=0){wirte_data(table1[bai]);wirte_data(table1[shi]);wirte_data(table1[ge]);while(num!=14) keyscan();wirte_com(0x01);}else if(shi!=0){wirte_data(table1[shi]);wirte_data(table1[ge]);while(num!=14) keyscan();wirte_com(0x01);}else{wirte_data(table1[ge]);while(num!=14) keyscan();wirte_com(0x01);}}}void jj(){if(a>c)i=a-c;elsei=c-a;}void csh() //初始化子函数{P3=0xff;wirte_com(0x01);delay(10);wirte_com(0x38);delay(10);wirte_com(0x0f);delay(10);wirte_com(0x06);delay(10);wirte_com(0x80);delay(10);}void wirte_com(uc com) //液晶写指令{P2=com;rs=0;rw=0;e=0;delay(10);e=1;}void wirte_data(uc date) //液晶写数据{P2=date;rs=1;rw=0;e=0;delay(100);e=1;}void delay(unsigned int z) //延时子程序{unsigned int x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}uc keyscan() //键盘扫描子程序{while(1){P1=0xfe;temp=P1;temp=temp&0xf0;if(temp!=0xf0){delay(10);temp=P1;bb=P1;temp=temp&0xf0;if(temp!=0xf0){temp=P1;switch(temp){case 0xee:num=0;break;case 0xde:num=1;break;case 0xbe:num=2;break;case 0x7e:num=3;break;default:break;}while(P1==bb);delay(10);while(P1==bb);}}P1=0xfd;temp=P1;bb=P1;temp=temp&0xf0;if(temp!=0xf0){delay(10);temp=P1;temp=temp&0xf0;if(temp!=0xf0){temp=P1;switch(temp){case 0xed:num=4;break;case 0xdd:num=5;break;case 0xbd:num=6;break;case 0x7d:num=7;break;default:break;}while(P1==bb);delay(10);while(P1==bb);}}P1=0xfb;temp=P1;bb=P1;temp=temp&0xf0;if(temp!=0xf0){delay(10);temp=P1;temp=temp&0xf0;if(temp!=0xf0){temp=P1;switch(temp){case 0xeb:num=8;break;case 0xdb:num=9;break;case 0xbb:num=10;break;case 0x7b:num=11;break;default:break;}while(P1==bb);delay(10);while(P1==bb);}}P1=0xf7;temp=P1;bb=P1;temp=temp&0xf0;if(temp!=0xf0){delay(10);temp=P1;temp=temp&0xf0;if(temp!=0xf0){temp=P1;switch(temp){case 0xe7:num=12;break;case 0xd7:num=13;break;case 0xb7:num=14;break;case 0x77:num=15;break;default:break;}while(P1==bb);delay(10);while(P1==bb);}}if(num!=99) return(num);}}实验小结通过本次实验我巩固了前面对键盘、液晶的使用,并且学会了如何把它们综合起来运用,更加熟悉了程序编写过程!。
51单片机简易计算器设计报告(一)
51单片机简易计算器设计报告(一)背景介绍在数字化时代,计算器作为一种简单易用的工具,越来越得到人们的关注和热爱。
而基于51单片机的简易计算器,不仅可以成为一种学习电子技术的手段,还具有满足简单计算需求的实用性。
设计思路本计算器采用键盘输入和数码管输出的电路设计,为用户提供加、减、乘、除、小数点、退位以及等于等功能。
1.键盘输入采用矩阵键盘的方式,将所有按键按行列排列,并利用51单片机中断方式来读取键值。
2.计算处理通过编写相应的程序代码,计算出用户输入的两个数值及操作符的结果,并将结果存储在数据缓存器中,最后将其输出至数码管。
3.数码管显示根据计算结果的数据类型,将其经过相应的转换处理后,通过数码管将结果输出至用户。
设计技术1.软件编写软件编写方面,采用汇编语言进行编写,代码总长度为2.2KB 左右。
其中,以中断方式读取键值、实现数值存储与判断、计算处理、数码管的结果输出等作为关键点进行编写。
2.硬件搭建硬件搭建方面,需要按照电路图进行搭建,并将51单片机与相关周边电路进行连接。
根据设计思路,将键盘、数码管、电源、指示灯等设备按照需求进行连接。
可改进之处虽然 51单片机的简易计算器的搭建能够满足基本计算需求,但其在以下几方面还有可改进之处:•添加计算科学函数,如三角函数、对数函数等。
•改进操作方式,使其更加符合人体工程学原理。
•添加储存器,使用户能够将计算结果进行存储和调用。
总结通过本次对基于51单片机的简易计算器的设计与实现,我们深入了解了电子技术的基本概念和硬件搭建原理,并了解到了简单嵌入式系统的工作原理。
虽然该计算器在功能和效率方面还有待改进,但对于初学者来说,其对于电子技术的学习和实验还是很有价值和意义的。
•编写的汇编代码过于繁琐,可考虑使用高级语言编写以提高效率和易读性。
•在电路搭建时需注意布线的合理性,尽量避免出现干扰和信号损失的问题。
综上所述,基于51单片机的简易计算器的设计和实现虽存在一些不足,但还是很有价值的。
单片机实训计算器报告
一、引言随着科技的飞速发展,单片机技术作为嵌入式系统的重要组成部分,已经在各个领域得到了广泛的应用。
为了提高学生对单片机技术的理解和实践能力,我们开展了单片机实训课程。
本次实训报告以设计一个简易计算器为例,详细介绍单片机在计算器中的应用及其设计过程。
二、实训目的1. 熟悉单片机的基本原理和编程方法。
2. 掌握单片机外围设备的接口技术。
3. 培养学生的实际动手能力和创新意识。
三、实训内容1. 设计要求本次实训要求设计一个基于单片机的简易计算器,能够实现以下功能:(1)加、减、乘、除四则运算;(2)结果显示在LCD1602显示屏上;(3)具有简单的错误处理功能。
2. 系统组成本计算器系统主要由以下几部分组成:(1)AT89C51单片机:作为系统的核心控制器,负责控制整个计算器的运行;(2)LCD1602显示屏:用于显示输入的数字、运算符和计算结果;(3)矩阵键盘:用于输入数字和运算符;(4)按键:用于控制计算器的开关、清零和退出等功能。
3. 硬件设计(1)AT89C51单片机:选用AT89C51单片机作为核心控制器,具有丰富的I/O端口和片内资源,可以满足计算器的需求。
(2)LCD1602显示屏:通过单片机的PORTD端口与LCD1602显示屏相连,实现数据显示功能。
(3)矩阵键盘:采用4x4矩阵键盘,将行线连接到单片机的PB0-PB3端口,列线连接到PB4-PB7端口。
(4)按键:设置三个按键,分别用于控制计算器的开关、清零和退出功能。
4. 软件设计(1)初始化:首先对单片机的I/O端口、LCD1602显示屏和矩阵键盘进行初始化。
(2)键盘扫描:通过扫描矩阵键盘,获取用户输入的数字和运算符。
(3)运算逻辑处理:根据用户输入的数字和运算符,进行相应的运算。
(4)结果显示:将计算结果显示在LCD1602显示屏上。
(5)错误处理:当输入错误或发生溢出时,显示错误信息。
四、实训过程1. 硬件电路搭建:根据设计要求,将AT89C51单片机、LCD1602显示屏、矩阵键盘和按键连接到一起,搭建计算器的硬件电路。
单片机实验-计算器
键盘功能示意:
四、实验代码 ORG 0000H SJMP START ORG 0030H START: CLR 00H CLR 01H CLR P3.0 MOV R7, #00H ; 按键次数计数器 LOOP: ACALL KEY CJNE R7, #01H, NEXT1 MOV R0, #30H ;存放第一个数的个位 MOV 31H, @R0 NEXT1: JB 00H,NEXT2 CJNE R7, #02H, NEXT2 MOV R0, #30H ;存放第一个数的十位 MOV A, #09H SUBB A, @R0 MOV32H,#00H ;异常处理 INC R7 JC NEXT2 DEC R7 MOV R2,31H MOV 31H, @R0 MOV 32H,R2 SETB 00H ;重来时要记得清 0 NEXT2: CJNE R7, #03H, NEXT3 MOV R0, #30H ; 存放操作数 有 “加减乘除”四 种情况 MOV 33H, @R0 NEXT3: CJNE R7, #04H, NEXT4 MOV R0, #30H ;存放第二个数的个位 MOV 34H, @R0 NEXT4: JB 01H,NEXT5 CJNE R7, #05H, NEXT5 MOV R0, #30H ;存放第二个数的十位 MOV A, #09H SUBB A, @R0 MOV 35H,#00H ;异常处理 INC R7 JC NEXT5 DEC R7 MOV R2,34H MOV 34H, @R0 MOV 35H,R2 SETB 01H ;重来时要记得清 0 NEXT5: CJNE R7, #06H, NEXT6 MOV R0, #30H ;存放操作数 等于号 0EH MOV 36H, @R0 NEXT6: LCALL DISPLAY CJNE R7, #06H, LOOP MOV R0, #36H CJNE @R0, #0EH, FU;存放开始计算的操作数 等待 等号 的键值 SJMP CK FU: DEC R7 LJMP LOOP ;开始计算 CK: MOV R7, #00H CLR 00H
基于51单片机的计算器课程设计实验报告
项目一:简单计算器1。
实验题目:用51单片机实现简单的计算器功能2。
实验截图:1).实验运行前截图:2).实验运行后截图:3.实验代码:#include<reg52。
h〉#include〈intrins.h〉#include〈math.h>#include<defined。
H>#include〈LCD1602.h>unsigned char table1[16]; //1602第一行显示字符unsigned char table2[16]; //1602第二行显示字符unsig ned char code table_error[] = ”error”;/*键扫描函数*/unsigned char keyscan() //扫描键盘函数{unsigned char key_l,key_h,addres,num;P0=0x0f;key_l=P0;P0=0xf0;key_h=P0;addres=key_l | key_h;if(addres!=0xff){Delayms(1);if(addres!=0xff){P0=0x0f;key_l=P0;P0=0xf0;key_h=P0;addres=key_l | key_h;switch(addres){case 0xee:num='1’;break;case 0xde:num=’2';break;case 0xbe:num=’3’;break;case 0xed:num='4';break;case 0xdd:num='5’;break;case 0xbd:num=’6';break;case 0xeb:num=’7’;break;case 0xdb:num='8’;break;case 0xbb:num='9’;break;case 0xd7:num='0’;break;//按键0case 0xe7:num=’C';break;//按键*case 0xb7:num=’=';break;//按键#case 0x7e:num='/’;break;//按键Acase 0x7d:num=’*’;break;//按键Bcase 0x7b:num='—’;break;//按键Ccase 0x77:num='+';break;//按键D}while(addres!=0xff){P0=0x0f;key_l=P0;P0=0xf0;key_h=P0;addres=key_l | key_h;}return num;}}return 0;}void clear_lcd(void)//清屏{unsigned char j;for(j=0;j〈16;j++){table1[j]=’\0’;table2[j]='\0';}}void main(){unsigned char i=0,j;unsigned char key;unsigned char flag_operator = 0;//加减乘除标志位unsigned char flag_equ = 0;//等于标志位unsigned char flag_key = 0;//运算位标志bit flag_MaxValue = 0;bit flag_minus = 0;//负数long int value = 0; //最终运算结果unsigned long int value_H =0; //第一个数据unsigned long int value_L = 0;//第二个数据unsigned long int temp[]={1, 10, 100,1000,10000,100000,1000000,10000000,100000000};Initialize_LCD();while(1){key=keyscan();if(key != 0){if(key == ’C')//清除键C按下{clear_lcd();i=0;flag_operator = 0; flag_equ = 0; value = 0; value_H =0; value_L = 0; flag_key = 0; flag_minus=0;}else{for(j=0; j<i; j++){table1[15—i+j] = table1[15—i+j+1];}table1[15] = key;//table1[i] = key;i++;}if(key == '='){for(j=0; j〈16; j++)//确定运算符位置{if(table1[j] == ’=’){flag_equ = j;flag_key++;break;}if( table1[j]== ’+' || table1[j] == ’—' || table1[j] == ’*' ||table1[j] == '/'){flag_operator = j;flag_key++;}}for(j=16—i; j〈flag_operator; j++) //第一个数据处理{//value_H = value_H + (table1[j]-48) * ( pow(10 ,(flag_operator—j-1)));value_H = value_H + (table1[j]—48) * temp[flag_operator—j—1];}for(j=flag_operator+1; j〈15; j++) //第二个数据处理{//value_L = value_L + (table1[j]-48) * pow( 10 , (flag_equ—j—1));value_L = value_L + (table1[j]—48) * temp[flag_equ—j—1];}if(table1[flag_operator] == '+'){value = value_H + value_L;}else if(table1[flag_operator]== ’-'){value = value_H — value_L;}else if(table1[flag_operator] == '*'){value = value_H * value_L;}else if(table1[flag_operator]== ’/’){value = value_H / value_L;}if(value == 0)table2[15] = (value + 48);else if(value<0){value = abs(value);flag_minus = 1;}else if(value〉2000000000){flag_MaxValue = 1;//break;}j=15;while(value!=0){table2[j] = (value%10 + 48);value = value/10;j—-;}if(flag_minus) //负数{table2[j] = ’—’;}}if(flag_key 〉2 || table1[0] == '0' || flag_MaxValue==1 ){ShowString(5,1,table_error);while(keyscan() != 'C’);clear_lcd();i=0;flag_operator = 0; flag_equ = 0; value = 0; value_H =0; value_L = 0; flag_key = 0; flag_minus=0;}}ShowString(0,0,table1);ShowString(0,1,table2);}}。
基于C51单片机计算器实训报告
目录一、设计的意义二、设计的流程三、设计的原理四、设计的模块五、元器件清单六、成品的制作七、设计的总结一、设计的意义计算器是日常工作和学习生活中的常用工具,人们利用它代替了许多复杂计算,包括加减乘除和其他运算。
尤其是小型计算器,它携带方便,在生活中用起来方便快捷,成为了财政、学习、生意上都青睐的必需品。
它的需求广泛,在计算器的发展上存在很大的空间和市场意义。
单片机在我国的各行各业得到了广泛使用,单片机的出现是计算机制造技术高速发展的产物。
如今,它已经广泛应用到我们生活中的各个领域,如:电子、科技、通信、汽车、工业等。
一般只需几块钱,有着经济廉价的优势,用单片机可以很方便的实现计算器的设计。
本设计是以单片机为基础设计出简单的一次式计算器。
二、设计的流程本设计的计算器硬件电路采用三部分电路模块构成,第一部分是键盘模块,采用4*4矩阵键盘作为输入电路;第二部分是LCD1602液晶显示模块;第三部分是以89C52单片机作为控制核心。
软件程序主要由三部分组成:主程序、按键扫描程序和LCD1602显示程序。
下图为硬件模块框图:下图为设计流程图:三、设计的原理硬件电路原理图:四、设计的模块1、电源模块:电源的设计采用了自锁开关控制电源正极的接通与断开,当P1接上+5V直流电源时;若S1没有按下,此时S1的1与5端口接通,+5V电流不流通到电路,电路不工作;当S1按下后,3与5端口接通,此时+5V电流流通到电路是电路工作。
2、89C52单片机模块:此模块式是本设计的控制核心模块,常称为单片机最小系统;单片机最小系统由三部分组成:STC89C52芯片部分、复位部分(由按键开关、极性电容、10K电阻组成)、晶振部分(由12M石英晶振、两个30PF的瓷片电容组成)。
主要起程序的输入与控制、程序的复位、时间频率控制的作用。
3、4*4矩阵键盘模块:键盘可分为两类:编码键盘和非编码键盘。
编码键盘是较多按键(20个以上)和专用驱动芯片的组合,当按下某个按键时,它能够处理按键抖动、连击等问题,直接输出按键的编码,无需系统软件干预。
单片机设计之简易计算器报告
信息工程系专业班级:学号:姓名:指导教师:2011年 12 月 10 日摘要在设计中我们主要用到AT89S52芯片为系统控制核心,通过8位共阳数码管来显示该设计的主要功能。
外接4X4的键盘,通过键盘扫描来对输入数的控制,并外接驱动电路,系统采用LED数码管作为显示器,软件程序采用均采用C语言编写,便于移植与升级。
报告详细介绍了整个系统的硬件组成结构、工作原理和系统的软件程序设计。
计算器将完成的功能有整数的加,减,乘,除等功能。
关键词:AT89S52,计算器,数码管。
目录一、方案的论证和比较: (1)1.1 单片机型系统的选择与论证 (1)1.2 显示模块的选择与论证 (1)1.3 计算实现 (2)二、各系统框图及工作原理 (2)2.1 系统总体设计结构框图 (2)2.2 系统的硬件电路设计 (3)三、软件编程 (9)3.1LED显示程序流程图设计 (9)3.2 读键输入程序流程设计 (9)3.3主程序流程图设计 (10)四、测试结果和结论 (11)五、心得体会 (12)致谢 (13)参考文献 (13)附录A (14)附录B (14)一、方案的论证和比较:1.1 单片机型系统的选择与论证方案一:此方案采用AT89C51八位单片机实现。
它内存较小,只有4K字节Flash闪速存储器,128字节内部RAM,32个I/O口线,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,无在线下载编程功能,也无在线仿真功能。
只能通过编程器烧写成以.hex为后缀名的文件。
方案二:此方案采用AT89S52八位单片机实现。
它内存较大,有8K的字节Flash闪速存储器,比AT89C51要多4K。
它可在线编程,可在线仿真的功能,这让调试变得方便。
单片机软件编程的自由度大,可通过编程实现各种各样的算术算法和逻辑控制。
而且体积小,硬件实现简单,安装方便。
另外AT89S52在工业控制上也有着广泛的应用,编程技术及外围功能电路的配合使用都很成熟。
基于51单片机实验报告(计算器)
基于51单片机实验报告(计算器)一.计算器模块1.功能介绍利用8051 单片机硬件资源和常用外围电路如LCD1602,七段数码管,时钟(DS1302)温度传感器(18B20)等实现一个能做简单四则运算,并具有时钟显示,温度显示附加功能的计算器。
2.设计方案利用STC89C52为内核的单片机,PC机。
四则运算利用4*4矩阵键盘实现从0—9和运算符号的输入,并将操作过程和结果显示在LCD1602上。
时钟显示和温度显示,可以利用DS1302产生年份,月份,日期,星期,时,分,秒的数据,并将数据送往LCD1602显示,同样可以利用单片机开发板上面集成的DS18B20温度传感器来测试周围环境的温度,将获取的温度通过在LCD1602来显示。
系统设计框图3.具体实现代码计算器四则运算部分主要分为键盘扫描的键值读取,判断运算符号实现乘除优先级计算,LCD1602显示。
键盘扫描常用的有行扫描法,线反转法,此处我们用行扫描法,可以更明了读取键值。
unsigned char temp;key = null;//第一行按键P3 = 0xfe;temp = P3;temp = temp & 0xf0;if (temp != 0xf0){delay(10); //延时软件去抖动temp = P3;temp = temp & 0xf0;if (temp != 0xf0) //确认有键按下{temp = P3;switch (temp){case 0xee:key = 'D'; //读键值break;case 0xde:key = 0;break;case 0xbe:key = '=';break;case 0x7e:key = '/';break;}flag++;}}读完按键值之后我们需要读取运算的数字与运算符号,通过判断键值为数字则通过nun=nun*10+key,计算出数字,判断键值为运算符号则读出数字和键值。
单片机计算器报告
单片机课程调查题目:计算器系统设计学号:姓名:杨艳班级:应用1301一、需求分析本次调查的任务就是要以51系列单片机为核心实现一个简易计算器,它的结构非常简单,外部主要由键盘和一个LCD1602A液晶显示屏,一块STC89C52RC单片机构成,通过软件编程要求能完成四则运算并能实现循环显示。
本次实验的目的包括了解并熟练掌握proteus仿真软件的使用;掌握C语言,学会用它们进行单片机编程;学会使用Keil C编译工具进行编程和编译,并掌握proteus和Keil C 联调以实现在proteus上的软硬件仿真。
二、正规划分1、数码显示电路,LCD1602A的引脚详细介绍见下图:采用LCD1602A来显示,要求能显示两行。
它的D—7D引脚分别接到单片机的P0.0~P0.7引脚;RS、R/W、E管脚分别接到单片机的P2.4、P2.0、P2.3 。
具体连接见后面的电路图。
2、4*4键盘扫描电路用STC89C52RC的P3口中的P3.0,P3.1,P3.2和P3.3四根线作为按键的行输入线,用P3.4,P3.5,P3.6和P3.7作为按键的列输出线。
通过按次依次给P3口的高四位的每根线输出一个低电平列信号,每当一根列线输出后,将信号锁住,然后读取行线,看有没有哪一根出现低电平。
如果有,则说明有按键按下了,依据P3口是哪一根行线出现低电平和列线出现低电平,可以判别是第几行和第几列的按键按下了,如果读取行线没有出现低电平,则表示对应的列没有按键按下,那么换另一列输出低电平,在读取行信号,判别新的一列有没有键按下。
依此办法轮流使每一列依次输出低电平,判别每一列是否有键按下,直到把所有的按键判别完。
3、单片机微控制电路微控制电路就是以STC89C52RC为核心的控制核心,主要注意晶振电路的接法和RST法。
4、整体电路图见下图分析可知共分为七个模块:键盘扫描部分,定义各个位置上的键值部分,延迟部分,存贮部分,液晶显示部分,运算部分,动态显示部分。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
单片机原理及其应用实验报告基于51单片机的简易计算器的设计班级:12电子1班姓名:金腾达学号:12004011232015年1月6日摘要一个学期的51单片机的课程已经随着期末的到来落下了帷幕。
“学以致用”不仅仅是一句口号更应该是践行。
本设计秉承精简实用的原则,采用AT89C51单片机为控制核心,4X4矩阵键盘作为输入,LCD1602液晶作为输出组成实现了基于51单片机的简易计算器。
计算器操作方式尽量模拟现实计算器的操作方式,带有基本的运算功能和连续运算能力。
并提供了良好的显示方式,与传统的计算器相比,它能够实时显示当前运算过程和上一次的结果,更加方便用户记忆使用。
本系统制作简单,经测试能达到题目要求。
关键词:简易计算器、单片机、AT89C51、LCD1602、矩阵键盘目录一、系统模块设计......................................................................................... 错误!未定义书签。
1.1 单片机最小系统 (1)1.2 LCD1602液晶显示模块 (1)1.3 矩阵按键模块 (2)1.4 串口连接模块 (1)二、C51程序设计 (2)2.1 程序功能描述及设计思路 (2)2.1.1按键服务函数 (2)2.1.2 LCD驱动函数 (2)2.1.3 结果显示函数 (2)2.1.4状态机控制函数 (2)2.1.5串口服务函数 (2)2.2 程序流程图 (3)2.2.1系统总框图 (3)2.2.2计算器状态机流程转换图 (3)三、测试方案与测试结果 (4)3.1测试方案 (4)3.3 测试结果及分析 (7)4.3.1测试结果(仿真截图) (7)4.3.2测试分析与结论 (7)四、总结心得 (7)五、思考题 (8)附录1:整体电路原理图 (9)附录2:部分程序源代码 (10)基于51单片机的简易计算器的设计一、系统模块设计本系统主要由51单片机最小系统、串口模块、显示模块、矩阵键盘输入模块组成,下面分别论证这几个模块的选择。
1.1单片机最小系统51单片机的最小系统包括电源、时钟电路、复位电路,搭建最小系统是实现单片操作的最基本的硬件电路要求。
由于程序上需要使用串口工作在11920的波特率,为了更好地匹配该波特率,晶振采用11.0592MHz的晶振而不是常用的12MHz晶振。
1.2 LCD1602液晶显示模块为了便于计算器的计算过程以及结果的显示,方案采用了LCD1602的液晶来显示。
使用液晶比数码管的优势很多,占用较少的IO口、更低的功耗、更简单的控制过程、更强大的显示能力:1.3 矩阵按键模块计算器的输入通过4X4的矩阵按键来实现,由于软件上做了相应的映射处理,因此该4X4按键可以实现在极少代码更改下随意安排每个按键的实际意义。
矩阵按键通过行列扫描的方式快速求出当前的按下按键并等待起弹起以防止重复触发:1.4 串口连接模块由于使用Proteus仿真,这里的串口电路进行了简化,没有使用实际中将会用于进行电平转换的232芯片,而直接使用串口观察控件进行串口接收以及显示:二、C51程序设计由于本系统对系统的响应速度要求并不高,不需要进行高速的大量数据运算操作,因此不采用汇编方式编写程序。
使用C语言编写程序能够清晰地分析系统的整体思路。
本程序的主要思想是状态机,利用状态机的不同状态对程序的流程进行分段控制,在本系统中,较大限度的提高了系统的运行效率,同时具有了便于分析、改进和查错的天然优势2.1程序功能描述与设计思路2.1.1、按键服务函数:将4X4矩阵按键封装至按键服务函数中,利用映射表(数组)对4X4的对应按键进行键值映射,这样不仅仅完成了按键判断的函数封装更便于实际操作时对按键的定义的灵活改动,另外,按键的返回值采用ASCII码形式,这样更加利于程序上的可读性;2.1.2、LCD驱动函数:按照LM016模块的操作时序编写的LM016(LCD1602液晶)的驱动函数,使用C和H文件组合的形式既完成了底层的液晶驱动又开放了操作液晶的接口函数,使整体程序更加清晰明了;2.1.3、结果显示函数:由于计算结果涉及到小数点、负数以及长度的不确定性,这里直接通过调用stdio.h中的sprintf字符串格式化函数进行格式化,得到15个字符长度的ASCII形式数据显示,并在程序中进行范围限定以避免数据过大而产生显示不完整造成结果“不正确”的现象。
同时该函数还通过调用串口输出函数对单片机串口进行输出,可在计算机上位机端得到每次的计算结果信息;2.1.4、状态机控制函数:该函数直接在main函数的内部实现,并融合状态机的程序思想,利用状态机判断计算器输入时的各种可能状态并在不同程序状态中跳转实现灵活的程序流程控制,实践表明这种方式是非常适合计算器的程序设计的,能较大限度地提高系统的运行效率;2.1.5、串口服务函数:串口服务主要负责实现单片机向计算机上位机端的数据结果输出以及灵活的字符串显示。
2.2 程序流程图2.2.1、系统总框图2.2.2、计算器状态机流程转换图三、仿真方案与仿真结果3.1仿真方案1、硬件仿真使用Proteus7.8进行硬件仿真。
2、软件仿真使用Keil4For51 Debug工具进行软件编写和仿真3、硬件软件联调利用Proteus7.8和Keil4进行联合软硬件调试,方便查错和仿真展现3.2 测试结果及分析3.2.1测试结果(仿真截图)1、加、减、乘、除基本运算展示:2、连续运算展示:3、溢出和除0判断展示:4、串口通信展示:5、开机效果显示:3.3.2测试分析与结论根据上述测试数据,综上所述,本设计总体来说可以达到大部分设计要求。
四、总结与心得经过本次的实验设计学习,又一次深刻感受到了51单片机虽然已经过去几十年,现在也不断地收到16位、32位低价单片机的冲击,但仍然是一款性能优越的单片机,在处理生活中常用的简单任务时,51单片机依然能够焕发出青春般的光彩。
同时,51单片机也是学习和理解其他高级单片机的最好的入门平台,本次的实验也将增强了我对学习好其他高级单片机的决心和信心。
五、思考题1.描述完整所设计的计算器能完成的各项功能及实现方法。
(如几位数以内的运算;连加;复合运算等等)本实例实现了加减乘除基本运算、连续运算、最大长度14位的数据输入、超过14位数据后程序为避免不良显示自动显示溢出2.计算器设计过程中碰到的问题及解决的方法?使用时原本打算使用double型变量,但在实际测试中并没有发现精度很高,通过联合调试发现KEILC51编译器将double型自动转换为float型;3.如何实现掉电保护?使用E2PROM或者外部的SD卡等存储设备,通过一定的时序操作控制这些外部设备实现存储数据的接口,在每一步计算操作后都将过程和结果存储到存储设备中,在下次上电后直接读取实现掉电保护;4.日常生活中计算器光敏单元的功能及实现原理?光敏单元可看作为一个电流源,通过电阻进行简单的I/V转换,然后用ADC转换为数字量,通过单片机处理后调节液晶偏压或占空比来调节显示对比度以实现不同光强下的正常显示;5.如何与上位机进行计算结果的通信?本实例中已经简单实现了基于串口的单片机与计算机上位机之间的通信,不过是单向的,为了实现真正的通信,可定义相关协议,通过串口收发管理这些数据和操作来实现。
附录1:整体电路原理图附录2:部分源程序/*头文件引用部分*/#include "mySys.h"#include "LM016.h"#include "stdio.h"#include "MyUsart.h"/*端口定义部分*/#define PORT_KEY P1/*全局变量*/float CalNum1=0; //待计算数1float CalNum2=0; //待计算数2float ResNum =0; //计算结果unsigned char AppendNum=0; //判断是否为连续模式unsigned char NumsBegin=0; //判断是否真的开始有数字输入这里是为了避免重复输入前面的0 unsigned char FirstZero=0; //第一个是否为0 unsigned char NumPen=0; //书写坐标,会随着数字的输入而向后移动unsigned char AllNumsLen; //当前待计算数和运算符总长度,定义该变量是为了避免式子过长code unsigned char CalSymbolTable[]={0,'+','-','*','/'}; //运算符表unsigned char CalSymbol=0; //运算符unsigned char SysStatus=0; //程序运行状态//0程序初始化状态1正在输入第一个数2正在输入第二个数3得到运算结果/*函数声明部分*/unsigned char KeyScan(void);void ShowLogo(void);void ShowCalResult(float Value);/*函数实现部分*/void main(void){u nsigned char TempKey;L M016_Init();M yUsart_Init();M yUsart_Print("This is 51 Calculator Program!");M yUsart_Print("Usart Mode : TX BAD=19200bps");S howLogo(); //显示LOGOM yUsart_Print("System Init Done! Have Fun!");w hile(1){switch(SysStatus){case 0: //【程序初始化状态】LM016_Clear(); //清屏CalNum1=0;CalNum2=0;ResNum =0;NumPen =0;AppendNum=0;NumsBegin=0;FirstZero=0;AllNumsLen =0;CalSymbol=0;SysStatus=1; //进入正在输入第一个数状态break;case 1: //【正在输入第一个数字】TempKey = KeyScan();if(!TempKey) break; //没有按键按下则快速跳出if(TempKey>= '0' && TempKey <='9') //*****数字键{if(!NumsBegin) //现在还没有开始正式输入数字{if(TempKey == '0'){if(!FirstZero) //第一次输入0FirstZero = 1; //给了一次输入0的机会,后面就不给了else break;}else{NumsBegin = 1; //开头是非零,已经开始正式输入数字了NumPen=0; //书写坐标归位,此时将会覆盖原有的0}}if(AllNumsLen >= 10) break; //长度过长则快速跳出不在接受数字输入CalNum1 *= 10;CalNum1 += (TempKey - '0'); //求得当前数值LM016_PutChar(0,NumPen, TempKey);NumPen++; //书写坐标向右边移动AllNumsLen++;}else //*****符号键{switch(TempKey){case '+':case '-':case '*':case '/':if((!NumsBegin)&&(!FirstZero)) //若没有任何数字按键按下则补充这个0{LM016_PutChar(0,0, '0');NumPen++;}CalSymbol=TempKey;LM016_PutChar(0,NumPen, TempKey);NumPen++;AllNumsLen++;NumsBegin=0;FirstZero=0;AppendNum=0;CalNum2 = 0; //把第二个数值清空SysStatus=2;break;case '=':ResNum = CalNum1;ShowCalResult(ResNum);FirstZero=0;AppendNum=0;NumsBegin=0;NumPen=0;AllNumsLen=0;SysStatus=3; //进入过度阶段break;case 'C':SysStatus=0;break;}break;}case 2: //【正在输入第二个数字】TempKey = KeyScan();if(!TempKey) //没有按键按下则快速跳出break;if(TempKey>= '0' && TempKey <='9') //*****数字键{if(!NumsBegin) //现在还没有开始正式输入数字{if(TempKey == '0'){if(!FirstZero) //第一次输入0FirstZero = 1; //给了一次输入0的机会,后面就不给了else break;}else{NumsBegin = 1; //开头是非零,已经开始正式输入数字了if(FirstZero) NumPen--; //书写坐标归位,此时将会覆盖原有的0 }}if(AllNumsLen >= 16) break; //长度过长则快速跳出不在接受数字输入CalNum2 *= 10;CalNum2 += (TempKey - '0'); //求得当前数值LM016_PutChar(0,NumPen, TempKey);NumPen++; //书写坐标向右边移动AllNumsLen++;}else //*****符号键{switch(TempKey){case '=':switch(CalSymbol){case '+':ResNum = CalNum1 + CalNum2;reak;case '-':ResNum = CalNum1 - CalNum2;break;case '*':ResNum = CalNum1 * CalNum2;break;case '/':ResNum = CalNum1 / CalNum2;break;}if((!NumsBegin)&&(!FirstZero)) //若没有任何数字按键按下则补充这个0{LM016_PutChar(0,NumPen, '0');CalNum2 = 0;NumPen++;}ShowCalResult(ResNum);FirstZero=0;AppendNum=0;NumsBegin=0;NumPen=0;AllNumsLen=0;SysStatus=3; //进入过度阶段break;case 'C':SysStatus=0;break;}}break;case 3: //【当前是过度阶段】TempKey = KeyScan();if(!TempKey) break; //没有按键按下则快速跳出if(TempKey>= '0' && TempKey <='9') //*****数字键{LM016_Clear(); //清屏if(!NumsBegin) //现在还没有开始正式输入数字{if(TempKey == '0'){if(!FirstZero) //第一次输入0FirstZero = 1; //给了一次输入0的机会,后面就不给了elsebreak;}else{NumsBegin = 1; //开头是非零,已经开始正式输入数字了NumPen=0; //书写坐标归位,此时将会覆盖原有的0 }}CalNum1 = (TempKey - '0'); //求得当前数值这里直接赋值就OK了CalNum2 = 0; //把第二个数值清空LM016_PutChar(0,NumPen, TempKey);NumPen=1; //书写坐标向右边移动AllNumsLen=1;SysStatus=1; //进入输入第一个数值状态}else //*****符号键{switch(TempKey){case '+':case '-':case '*':case '/':LM016_Print(0,0,"Ans ");AppendNum=1;CalNum1 = ResNum;CalNum2 = 0;NumPen=2;if((!NumsBegin)&&(!FirstZero)) //若没有任何数字按键按下则补充这个0{LM016_PutChar(0,3, '0');NumPen++;}CalSymbol=TempKey;LM016_PutChar(0,NumPen, TempKey);NumPen++;AllNumsLen=4;NumsBegin=0;FirstZero=0;AppendNum=0;SysStatus=2;break;case '=':switch(CalSymbol){case '+':ResNum = ResNum + CalNum2;break;case '-':ResNum = ResNum - CalNum2;break;case '*':ResNum = ResNum * CalNum2;break;case '/':ResNum = ResNum / CalNum2;break;}ShowCalResult(ResNum);FirstZero=0;AppendNum=0;NumsBegin=0;NumPen=0;AllNumsLen=0;SysStatus=3; //进入过度阶段break;case 'C':SysStatus=0;break;}break;}break;}}}。