|
最近在学习单片机,把自己的资料分享给有需要的童鞋。
源码:(部分预览 完整代码请下载附件):
计算器设计.7z
(384.54 KB, 下载次数: 410)
- #include<reg52.h>
- #include<math.h>
- #include "lcd1602_8.h"
- uint temp,num;//键盘扫描数值
- uchar keynum1=0,keynum2=0,sign=0,i=0,j=0; //按键计数,符号标示
- uchar num1[8]={0},num2[8]={0}; //按键存储数组
- float ans1=0,ans2=0,ans=0,point=0; //运算数据
- bit conflag=0; //继续运算标志位
- bit newcalc=0; //新运算标志
- bit ac=0; //清零标志,1为清零
- bit beepflag=0; //蜂鸣器标志位
- bit sqrtflag1=0; //开方1标志位
- bit sqrtflag2=0; //开方2标志位
- bit powflag=0;
- sbit keybeep=P3^3;//蜂鸣器开关按键
- sbit beep=P2^3; //蜂鸣器控制口
- sbit keysqrt=P3^4;//开方按键
- sbit keypow=P3^5;//任意次方按键
- uchar keyscan();
- void maininit(void);
- /****主程序***/
- void main(void)
- {
- maininit();//初始化
- while(1) //整个系统大循环,让计算器一直处于工作状态
- {
- while(1) //第一运算数扫描
- {
- if(ac==1)
- break; //若清零,则退出输入
- if((keyscan()!='N')&&((num>=0&&num<=9)||num=='.')) //记录按下的数字
- {
- if(newcalc==1) //新一次运算开始
- {
- lcdwrite_com(0x01);//清屏
- newcalc=0;
- lcd_setxy(0,0);
- }
- if(keynum1<=7) //限制输入位数
- {
- if(num=='.')
- {
- lcdwrite_data('.'); //显示小数点
- }
- else
- lcdwrite_num1(num);
- num1[keynum1]=num;
- keynum1++;
- }
- }
- else if(num=='+'||num=='-'||num=='*'||num=='/'||num=='='||num=='^'||keysqrt==0)
- {
- if(keynum1==0&&num1[0]==0) //若直接输入运算符而没有输入数字则执行连续运算
- {
- here: ans1=ans;
- sign=num;
- lcdwrite_com(0x01);
- delayms(5);
- lcd_setxy(0,0);
- lcdwrite_float(ans1);
- if(sqrtflag2!=1&&num!='N')
- lcdwrite_data(num);
- break;
- }
- for(i=0;keynum1>0;i++) //计算按下的数字的大小
- {
- if(num1[i]!='.')
- ans1=ans1*10+num1[i];
- else if(num1[i]=='.')
- break;
- keynum1--;
- }
- for(keynum1--,i++,j=0;keynum1>0;j++,i++,keynum1--)
- point=point*10+num1[i];
- for(;j>0;j--)
- point*=0.1;
- ans1=ans1+point;
- sqrtflag1=0; //清除开方标志
- sqrtflag2=0;//清除开方标志
- if(keysqrt==0) //计算开方
- {
- delayms(5);
- if(keysqrt==0)
- {
- if(beepflag==1) //若开声音则每一次按键均鸣叫
- {
- beep=0;
- delayms(100);
- beep=1;
- }
- ans=sqrt(ans1);
- sqrtflag1=1;
- lcdwrite_data(0xe8);
- while(keysqrt==0);
- delayms(10);
- while(keysqrt==0);
- break;
- }
- }
- sign=num; //记住运算符号
- lcdwrite_data(num);
- break; //输入运算符号则退出第一运算数的输入
- }
- }
- while(1)
- {
- if(ac==1)
- break; //若清零,则退出输入
- if(sqrtflag1==1) //若第一次按键为开方,则直接显示结果
- {
- break;
- }
- if((keyscan()!='N')&&((num>=0&&num<=9)||num=='.')) //记录按下的数字
- {
- if(keynum2<=7)
- {
- if(num=='.')
- {
- lcdwrite_data('.'); //显示小数点
- }
- else
- lcdwrite_num1(num);
- num2[keynum2]=num;
- keynum2++;
- }
- }
- else if(num=='='||keysqrt==0)
- {
- sqrtflag2=0;//清除开方标志
- if(keysqrt==0) //进入开方
- {
- delayms(5);
- if(keysqrt==0)
- {
- sqrtflag2=1; //开方标志
- lcdwrite_data(0xe8); //写开方符号
- if(beepflag==1) //若开声音则每一次按键均鸣叫
- {
- beep=0;
- delayms(100);
- beep=1;
- }
- while(keysqrt==0);
- delayms(10);
- while(keysqrt==0);
- }
- }
- point=0;
- for(i=0;keynum2>0;i++) //计算按下的数字的大小
- {
- if(num2[i]!='.')
- ans2=ans2*10+num2[i];
- else if(num2[i]=='.')
- break;
- keynum2--;
- }
- for(keynum2--,i++,j=0;keynum2>0;j++,i++,keynum2--)
- point=point*10+num2[i];
- for(;j>0;j--)
- point*=0.1;
- if(sqrtflag2!=1)
- lcdwrite_data(num);
- ans2=ans2+point;
- break; //输入等于号则退出第二运算数的输入
- }
- else if(num=='+'||num=='-'||num=='*'||num=='/'||num=='^')
- {
- point=0;
- for(i=0;keynum2>0;i++) //计算按下的数字的大小
- {
- if(num2[i]!='.')
- ans2=ans2*10+num2[i];
- else if(num2[i]=='.')
- break;
- keynum2--;
- }
- for(keynum2--,i++,j=0;keynum2>0;j++,i++,keynum2--)
- point=point*10+num2[i];
- for(;j>0;j--)
- point*=0.1;
- lcdwrite_data(num);
- ans2=ans2+point;
- conflag=1;
- break; //进行连续计算
- }
- }
- if(ac==1)
- {
- ac=0;
- continue; //清零后进行下一次运算
- }
- if(sign=='+') //计算结果
- ans=ans1+ans2;
- if(sign=='-')
- ans=ans1-ans2;
- if(sign=='*')
- ans=ans1*ans2;
- if(sign=='/')
- ans=ans1/ans2;
- if(sign=='^') //计算多次方
- ans=pow(ans1,ans2);
- if(sqrtflag2==1) //计算开方
- ans=sqrt(ans1);
- lcd_setxy(1,0);
- if((ans2==0&&sign=='/')||(ans1<0&&sqrtflag2==1))
- lcdwrite_string("math error");//ans2=0或被开方数小于0时提示错误
- else lcdwrite_float(ans); //显示结果
- sqrtflag1=0,newcalc=1; //为新的一次运算准备
- ans1=0;
- ans2=0;
- for(i=0;i<8;i++) //清除按键缓存
- num1[i]=0;
- for(i=0;i<8;i++)
- num2[i]=0;
- if(conflag==1)
- {
- conflag=0;
- goto here; //跳转到连续运算
- }
- }
- }
- /*****初始化程序*****/
- void maininit(void)
- {
- delayms(100); //等待液晶初始化
- lcd_init();
- lcd_setxy(0,0);
- lcdwrite_data('0');
- lcd_setxy(0,0);
- IT0=1;//下降沿触发
- EX0=1;//开外部中断0
- IT1=1;//下降沿触发
- EX1=1;//开外部中断1
- EA=1; //开中断
- }
- /***清零中断程序******/
- void EX0_int() interrupt 0
- {
- if(beepflag==1) //若开声音则每一次按键均鸣叫
- {
- beep=0;
- delayms(500);
- beep=1;
- }
- lcdwrite_com(0x01); //显示清屏
- lcd_setxy(0,0);
- lcdwrite_data('0');
- lcd_setxy(0,0);
- num='N'; //数字初始化
- keynum1=0,keynum2=0,sign=0;
- ans1=0,ans2=0,ans=0,point=0;
- conflag=0,newcalc=0;
- ac=1;
- }
- /***声音中断程序******/
- void EX1_int() interrupt 2
- {
- beepflag=~beepflag;
- if(beepflag==1) //若开声音则每一次按键均鸣叫
- {
- beep=0;
- delayms(500);
- beep=1;
- }
- }
- /*****键盘扫描程序*****/
- uchar keyscan()
- {
- num='N'; //若没有按下任何按键,则返回'N'
- P1=0xfe; //扫描第一行
- temp=P1;
- temp=temp&0xf0;
- while(temp!=0xf0) //扫描列
- {
- delayms(10);
- temp=P1;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P1;
- switch(temp)
- {
- case 0xee:num=7;
- break;
- case 0xde:num=8;
- break;
- case 0xbe:num=9;
- break;
- case 0x7e:num='/';
- break;
- }
- while(temp!=0xf0) //等待松手
- {
- temp=P1;
- temp=temp&0xf0;
- }
- }
- }
- P1=0xfd; //扫描第二行
- temp=P1;
- temp=temp&0xf0;
- while(temp!=0xf0) //扫描列
- {
- delayms(10);
- temp=P1;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P1;
- switch(temp)
- {
- case 0xed:num=4;
- break;
- case 0xdd:num=5;
- break;
- case 0xbd:num=6;
- break;
- case 0x7d:num='*';
- break;
- }
- while(temp!=0xf0)
- {
- temp=P1;
- temp=temp&0xf0; //等待松手
- }
- }
- }
- P1=0xfb; //扫描第三行
- temp=P1;
- temp=temp&0xf0;
- while(temp!=0xf0) //扫描列
- {
- delayms(10);
- temp=P1;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P1;
- switch(temp)
- {
- case 0xeb:num=1;
- break;
- case 0xdb:num=2;
- break;
- case 0xbb:num=3;
- break;
- case 0x7b:num='-';
- break;
- }
- while(temp!=0xf0) //等待松手
- {
- temp=P1;
- temp=temp&0xf0;
- }
- }
- }
- P1=0xf7; //扫描第四行
- temp=P1;
- temp=temp&0xf0;
- while(temp!=0xf0) //扫描列
- {
- delayms(10);
- temp=P1;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P1;
- switch(temp)
- {
- case 0xe7:num=0;
- break;
- case 0xd7:num='.';
- break;
- case 0xb7:num='=';
- break;
- case 0x77:num='+';
- break;
- }
- while(temp!=0xf0)
- {
- temp=P1;
- temp=temp&0xf0; //等待松手
- }
- }
- }
- if(keypow==0)
- {
- delayms(5);
- if(keypow==0)
- {
- powflag=1;
- num='^';
- }
- while(keypow==0); //扫描多次方按键
- delayms(5);
- while(keypow==0);
- }
- if(beepflag==1&&num!='N') //若开声音则每一次按键均鸣叫
- {
- beep=0;
- delayms(100);
- beep=1;
- }
- return num;
- }
复制代码
|
评分
-
查看全部评分
|