单片机课程设计报告(多功能计算器)班级:姓名:学号:指导老师:一、内容摘要利用89c51作为主控器设计一个四则运算的计算器。
首先通过在图书馆和网上查找有关设计计算器的资料,大概了解设计计算器需要哪几个模块,熟悉Keil 和Proteus 两个软件的用法,以及它们的联调,完成计算器的程序设计和仿真,然后就是进实验室进行计算器电路板的焊接,最后就是将程序下载到单片机芯片中,系统联调,直到得出结果。
二、设计内容及要求用单片机设计计算器,要求可以进行加、减、乘、除运算。
三、系统方案设计,画出系统框图四、画出完整的电路图,并说明电路的工作原理51系列单片机4*4键盘8位LED 显示6264 RAM 扩展复位电路晶振电路等系统原理框图电路图说明:(1)键盘的列扫描接单片机P2口的低4位,行扫描接单片机P1口的低4位;(2)数码管的段选通过单片机的P0口接74LS244来驱动,数码管的位选接单片机的P2口;(3)发光二极管电路用来说明电路是否上电;(4)晶振电路为单片机提供时钟频率;(5)复位电路为单片机提供复位信号。
计算器的功能实现:(1)此计算器适应于不大于八位整数的四则混合运算,若单个数大于八位或者结果大于八位(溢出)则显示“Chu cuo”。
(2)如果在还没有按数字之前按了一个符号键或者等号则显示“Chu cuo”。
(3)若接连按了几个运算符键,实际上进行的运算是最后一次按的运算键。
(4)可以显示负数、小数。
(5)此计算器不可实现连乘、连加、连减、连除。
四、软件仿真,根据系统硬件图编写系统程序并调试#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);//声明"出错显示"子函数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(r7==0x0d)//如果r7中存放的是"+",则执行加运算{bian1();jia();bian2();}else if(r7==0x0c)//如果r7中存放的是"-",则执行减运算{bian1();jian();}else if(r7==0x0b)//如果r7中存放的是"*",则执行乘运算{bian1();cheng();bian2();}else if(r7==0x0a)//如果r7中存放的是"÷",则执行除运算{bian1();chu();}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;}}}}}}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;}}}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--;}array[0]=(uchar)(num3*10);while(array[0]==0x00){for(i=0;i<7;i++)array[i]=array[i+1];array[7]=0x10;}}}void error(void)//"出错显示"子函数(出错显示"Chu cuo.") {array[7]=0x0c;array[6]=0x1d;array[5]=0x1f;array[4]=0x10;array[3]=0x10;array[2]=0x1c;array[1]=0x1f;array[0]=0x1e;}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,0x58,0x74,0xdc,0x1c};uchar *p=array,count=0x80,i,time;F0=1;while(F0){i=*(p+7);P2=count;P0=array3[i];for(time=0xff;time>0x00;time--);p--;count=_cror_(count,1);if(count==0x80)F0=0;}}void iskeyyou(void)//"判断是否有键按下"子函数{P2=0x00;P1|=0x0f;a=P1;a|=0xf0;}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;}}}}}五、系统联调在我将计算器的电路板焊接好以后,我将程序下载到单片机芯片上面,再接上电源测试发现键盘上面只有几个按键有显示,开始我就怀疑是自己的焊接键盘的线时,出现了虚焊或者是焊错了的错误,我就写了一个程序让数码管上面显示“4321”这四个数字,下载进去后,发现没有错误,这就证明我的数码管那一块没有出现错误,由此推论,最有可能出现错误的就是键盘,由于自己当时并不清楚键盘的行列线,所以没有自己测量了,我去问老师,老师就说“实验室的键盘可能也有点问题”,于是他就给我们拿了几个他自己借来的键盘,然后手把手的教我们怎么测试行列线,我也很快就测出了其对应的行列线,但是一接上电源测试,还是有一行不能显示,最后在老师的提点下,是发现P1.0口始终接了高电平,从而导致无法显示,在老师的帮助下,最终我做出了结果。