基于51单片机的简易计算器制作专业:电气信息班级:11级电类一班姓名:王康胡松勇时间:2012年7月12日一:设计任务本系统选用AT89C52单片机为主控机。通过扩展必要的外围接口电路,实现对计算器的设计,具体设计如下:(1)由于设计的计算器要进行四则运算,为了得到较好的显示效果,经综合分析后,最后采用LED显示数据和结果。(2)采用键盘输入方式,键盘包括数字键(0~9)、符号键(+、-、×、÷)、清除键(on\c)和等号键(=),故只需要16个按键即可,设计中采用集成的计算键盘。(3)在执行过程中,开机显示零,等待键入数值,当键入数字,通过LED显示出来,当键入+、-、*、/运算符,计算器在内部执行数值转换和存储,并等待再次键入数值,当再键入数值后将显示键入的数值,按等号就会在LED上输出运算结果。(4)错误提示:当计算器执行过程中有错误时,会在LCD上显示相应的提示,如:当输入的数值或计算得到的结果大于计算器的表示范围时,计算器会在LED上提示八个0;当除数为0时,计算器会在LED上会提示八个负号。设计要求:分别对键盘输入检测模块;LED显示模块;算术运算模块;错误处理及提示模块进行设计,并用Visio画系统方框图,keil与protues仿真分析其设计结果。二.硬件设计单片机最小系统CPU:AT89C52显示模块:两个4位7段共阴极数码管输入模块:4*4矩阵键盘1.电路图电路图说明本电路图采用AT89C52作为中处理器,以4*4矩阵键盘扫描输入,用两个74HC573(锁存器)控制分别控制数码管的位于段,并以动态显示的方式显示键盘输入结果及运算结果。为编程方便,以一个一位共阴极数码管显示负号。三,程序设计#includereg52.h#defineLintlongint#defineuintunsignedint#defineucharunsignedcharsbitdula=P2^6;//锁存器段选sbitwela=P2^7;sbitdisplay_g=P2^0;//负号段选sbitdisplay_w=P2^1;//负号位选ucharcodetable[]={0x3f,0x06,0x5b,0x4f,//0,1,2,30x66,0x6d,0x7d,0x07,//4,5,6,70x7f,0x6f,//0x77,0x7c,//8,9//0x39,0x5e,0x79,0x71};//数码管段码表ucharcodetable1[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//数码管位码表/****************定义全局变量*******************/Lintstore[2]={0};//存取按键值和结果的数组ucharflag_op=0;//+,-,*,/操作符标志符ucharflag_order=0;//输入数的顺序标志符ucharflag_equal=0;//等于号标志符ucharkey=16;//按键值/*****************延时函数*********************/voiddelay(uintx){uinti,j;for(i=x;i0;i--)for(j=110;j0;j--);}/****************显示函数*********************/voiddisplay(Linttemp){uintbuf1,buf2,i=0;buf1=temp/10000000;if(buf1=10||temp-9999999)//数据溢出,显示错误00000000{display_w=1;//关负号位选dula=1;P0=0x3f;dula=0;P0=0xff;wela=1;P0=0x00;wela=0;delay(1);}elseif(temp0&&temp=-99999999)//显示负数{display_w=0;//开负号位选temp=-temp;do{buf2=temp%10;dula=1;P0=table[buf2];dula=0;P0=0xff;wela=1;P0=table1[i];wela=0;i++;P0=0x00;temp=temp/10;delay(1);}while(temp!=0);}else{display_w=1;//关负号位选do{dula=1;buf2=temp%10;P0=table[buf2];dula=0;P0=0xff;wela=1;P0=table1[i];wela=0;i++;P0=0x00;temp=temp/10;delay(1);}while(temp!=0);}}/******************键盘扫描函数******************/ucharKeyScan(){uchartemp;P3=0xfe;//扫描第一行temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(5);P3=0xfe;temp=P3;temp=temp&0xf0;if(temp!=0xf0){switch(temp){case0xe0:key=0;break;case0xd0:key=1;break;case0xb0:key=2;break;case0x70:key=3;break;}while(temp!=0xf0)//等待按键被释放{temp=P3;temp=temp&0xf0;}}}P3=0xfd;//扫描第二行temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(5);P3=0xfd;temp=P3;temp=temp&0xf0;if(temp!=0xf0){switch(temp){case0xe0:key=4;break;case0xd0:key=5;break;case0xb0:key=6;break;case0x70:key=7;break;}while(temp!=0xf0)//等待按键释放{temp=P3;temp=temp&0xf0;}}}P3=0xfb;//扫描第二行temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(5);P3=0xfb;temp=P3;temp=temp&0xf0;if(temp!=0xf0){switch(temp){case0xe0:key=8;break;case0xd0:key=9;break;case0xb0:key=10;flag_order=1;flag_op=1;break;//+case0x70:key=11;flag_order=1;flag_op=2;break;//-}while(temp!=0xf0)//等待按键释放{temp=P3;temp=temp&0xf0;}}}P3=0xf7;//扫描第四行temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(5);P3=0xf7;temp=P3;temp=temp&0xf0;if(temp!=0xf0){switch(temp){case0xe0:key=12;flag_order=1;flag_op=3;break;//*case0xd0:key=13;flag_order=1;flag_op=4;break;///case0xb0:key=14;break;case0x70:key=15;flag_equal=1;break;//=}while(temp!=0xf0)//等待按键释放{temp=P3;temp=temp&0xf0;}}}returnkey;}/***************运算函数*********************/voidYunSuan(){if(flag_equal==1){switch(flag_op){case1://加法运算store[0]=store[0]+store[1];flag_op=0;flag_order=0;store[1]=0;//输入的第二个数清零break;case2://减法运算store[0]=store[0]-store[1];flag_op=0;flag_order=0;store[1]=0;//输入的第二个数清零break;case3://乘法运算store[0]=store[0]*store[1];flag_op=0;flag_order=0;store[1]=0;//输入的第二个数清零break;case4://除法运算store[0]=store[0]/store[1];//计算结果,存入第一个数flag_op=0;//操作符清零flag_order=0;//输入顺序标识符清零,显示结果store[1]=0;//输入的第二个数清零break;}flag_equal=0;}}/*****************主函数*****************/voidmain(){while(1){display_g=1;//开负号段选key=KeyScan();//键盘扫描if(key=0&&key=9)//如果key在0到9之间,证明键盘按下的是数值{if(store[flag_order]10000000){store[flag_order]=store[flag_order]*10+key;}key=16;}if(key==14)//如果key为14时,证明键盘按下的是CE键{display_w=1;store[0]=0;//数据清零store[1]=0;flag_op=0;flag_order=0;flag_equal=0;key=16;}YunSuan();display(store[flag_order]);}}