找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 13537|回复: 23
打印 上一主题 下一主题
收起左侧

基于89c52的简易计算器设计(仿真与源程序)

  [复制链接]
跳转到指定楼层
楼主
最近在学习单片机,把自己的资料分享给有需要的童鞋。




源码:(部分预览 完整代码请下载附件): 计算器设计.7z (384.54 KB, 下载次数: 410)
  1. #include<reg52.h>
  2. #include<math.h>
  3. #include "lcd1602_8.h"
  4. uint temp,num;//键盘扫描数值
  5. uchar keynum1=0,keynum2=0,sign=0,i=0,j=0; //按键计数,符号标示
  6. uchar num1[8]={0},num2[8]={0};         //按键存储数组
  7. float ans1=0,ans2=0,ans=0,point=0; //运算数据
  8. bit conflag=0;         //继续运算标志位
  9. bit newcalc=0;        //新运算标志
  10. bit ac=0;                //清零标志,1为清零
  11. bit beepflag=0;         //蜂鸣器标志位
  12. bit sqrtflag1=0;        //开方1标志位
  13. bit sqrtflag2=0;        //开方2标志位
  14. bit        powflag=0;
  15. sbit keybeep=P3^3;//蜂鸣器开关按键
  16. sbit beep=P2^3;         //蜂鸣器控制口
  17. sbit keysqrt=P3^4;//开方按键
  18. sbit keypow=P3^5;//任意次方按键
  19. uchar keyscan();
  20. void maininit(void);
  21. /****主程序***/
  22. void main(void)
  23. {
  24.         maininit();//初始化
  25.         while(1)        //整个系统大循环,让计算器一直处于工作状态
  26.         {
  27.                 while(1)        //第一运算数扫描
  28.                 {
  29.                         if(ac==1)
  30.                                 break;         //若清零,则退出输入
  31.                         if((keyscan()!='N')&&((num>=0&&num<=9)||num=='.')) //记录按下的数字
  32.                         {
  33.                                 if(newcalc==1)          //新一次运算开始
  34.                                 {
  35.                                         lcdwrite_com(0x01);//清屏
  36.                                         newcalc=0;
  37.                                         lcd_setxy(0,0);
  38.                                 }
  39.                                 if(keynum1<=7)           //限制输入位数
  40.                                 {                        
  41.                                         if(num=='.')
  42.                                         {        
  43.                                                 lcdwrite_data('.');        //显示小数点
  44.                                         }
  45.                                         else
  46.                                                 lcdwrite_num1(num);
  47.                                         num1[keynum1]=num;
  48.                                         keynum1++;
  49.                                 }
  50.                         }
  51.                         else if(num=='+'||num=='-'||num=='*'||num=='/'||num=='='||num=='^'||keysqrt==0)  
  52.                         {
  53.                                 if(keynum1==0&&num1[0]==0)          //若直接输入运算符而没有输入数字则执行连续运算
  54.                                 {        
  55.                         here:        ans1=ans;
  56.                                         sign=num;
  57.                                         lcdwrite_com(0x01);
  58.                                         delayms(5);
  59.                                         lcd_setxy(0,0);
  60.                                         lcdwrite_float(ans1);
  61.                                         if(sqrtflag2!=1&&num!='N')
  62.                                                 lcdwrite_data(num);
  63.                                         break;
  64.                                 }
  65.                                 for(i=0;keynum1>0;i++)           //计算按下的数字的大小
  66.                                 {
  67.                                         if(num1[i]!='.')
  68.                                                 ans1=ans1*10+num1[i];
  69.                                         else if(num1[i]=='.')
  70.                                                 break;
  71.                                         keynum1--;
  72.                                 }
  73.                                 for(keynum1--,i++,j=0;keynum1>0;j++,i++,keynum1--)
  74.                                         point=point*10+num1[i];
  75.                                 for(;j>0;j--)
  76.                                         point*=0.1;
  77.                                 ans1=ans1+point;
  78.                                 sqrtflag1=0; //清除开方标志
  79.                                 sqrtflag2=0;//清除开方标志
  80.                                 if(keysqrt==0)                  //计算开方
  81.                                 {
  82.                                         delayms(5);
  83.                                                 if(keysqrt==0)
  84.                                                 {
  85.                                                         if(beepflag==1) //若开声音则每一次按键均鸣叫
  86.                                                         {
  87.                                                                 beep=0;
  88.                                                                 delayms(100);
  89.                                                                 beep=1;
  90.                                                         }
  91.                                                         ans=sqrt(ans1);
  92.                                                         sqrtflag1=1;
  93.                                                         lcdwrite_data(0xe8);
  94.                                                         while(keysqrt==0);
  95.                                                         delayms(10);
  96.                                                         while(keysqrt==0);
  97.                                                         break;
  98.                                                 }
  99.                                 }
  100.                                 sign=num;                 //记住运算符号
  101.                                 lcdwrite_data(num);
  102.                                 break;                   //输入运算符号则退出第一运算数的输入
  103.                         }               
  104.                 }
  105.                 while(1)
  106.                 {
  107.                         if(ac==1)
  108.                                 break;          //若清零,则退出输入
  109.                         if(sqrtflag1==1)  //若第一次按键为开方,则直接显示结果
  110.                         {
  111.                                 break;
  112.                         }
  113.                         if((keyscan()!='N')&&((num>=0&&num<=9)||num=='.'))         //记录按下的数字
  114.                         {
  115.                                 if(keynum2<=7)
  116.                                 {
  117.                                         if(num=='.')
  118.                                         {
  119.                                                 lcdwrite_data('.');        //显示小数点
  120.                                         }
  121.                                         else
  122.                                                 lcdwrite_num1(num);
  123.                                         num2[keynum2]=num;
  124.                                         keynum2++;
  125.                                 }
  126.                         }
  127.                         else if(num=='='||keysqrt==0)
  128.                         {
  129.                                 sqrtflag2=0;//清除开方标志
  130.                                 if(keysqrt==0)         //进入开方
  131.                                 {
  132.                                         delayms(5);
  133.                                         if(keysqrt==0)
  134.                                         {
  135.                                                 sqrtflag2=1;   //开方标志
  136.                                                 lcdwrite_data(0xe8);  //写开方符号
  137.                                                 if(beepflag==1)        //若开声音则每一次按键均鸣叫
  138.                                                 {
  139.                                                         beep=0;
  140.                                                         delayms(100);
  141.                                                         beep=1;
  142.                                                 }
  143.                                                 while(keysqrt==0);
  144.                                                 delayms(10);
  145.                                                 while(keysqrt==0);
  146.                                         }
  147.                                 }
  148.                                 point=0;
  149.                                 for(i=0;keynum2>0;i++)   //计算按下的数字的大小
  150.                                 {
  151.                                         if(num2[i]!='.')
  152.                                                 ans2=ans2*10+num2[i];
  153.                                         else if(num2[i]=='.')
  154.                                                 break;
  155.                                         keynum2--;
  156.                                 }
  157.                                 for(keynum2--,i++,j=0;keynum2>0;j++,i++,keynum2--)
  158.                                         point=point*10+num2[i];
  159.                                 for(;j>0;j--)
  160.                                         point*=0.1;
  161.                                 if(sqrtflag2!=1)
  162.                                         lcdwrite_data(num);
  163.                                 ans2=ans2+point;
  164.                                 break;                //输入等于号则退出第二运算数的输入
  165.                         }
  166.                         else if(num=='+'||num=='-'||num=='*'||num=='/'||num=='^')
  167.                         {
  168.                                 point=0;
  169.                                 for(i=0;keynum2>0;i++)          //计算按下的数字的大小
  170.                                 {
  171.                                         if(num2[i]!='.')
  172.                                                 ans2=ans2*10+num2[i];
  173.                                         else if(num2[i]=='.')
  174.                                                 break;
  175.                                         keynum2--;
  176.                                 }
  177.                                 for(keynum2--,i++,j=0;keynum2>0;j++,i++,keynum2--)
  178.                                         point=point*10+num2[i];
  179.                                 for(;j>0;j--)
  180.                                         point*=0.1;
  181.                                 lcdwrite_data(num);
  182.                                 ans2=ans2+point;
  183.                                 conflag=1;
  184.                                 break;                         //进行连续计算
  185.                         }
  186.                 }
  187.                 if(ac==1)
  188.                 {        
  189.                         ac=0;
  190.                         continue; //清零后进行下一次运算
  191.                 }        
  192.                 if(sign=='+')       //计算结果
  193.                         ans=ans1+ans2;
  194.                 if(sign=='-')
  195.                         ans=ans1-ans2;
  196.                 if(sign=='*')
  197.                         ans=ans1*ans2;
  198.                 if(sign=='/')
  199.                         ans=ans1/ans2;
  200.                 if(sign=='^')         //计算多次方
  201.                         ans=pow(ans1,ans2);         
  202.                 if(sqrtflag2==1)        //计算开方
  203.                         ans=sqrt(ans1);
  204.                 lcd_setxy(1,0);
  205.                 if((ans2==0&&sign=='/')||(ans1<0&&sqrtflag2==1))
  206.                         lcdwrite_string("math error");//ans2=0或被开方数小于0时提示错误           
  207.                 else lcdwrite_float(ans);                //显示结果
  208.                 sqrtflag1=0,newcalc=1;                  //为新的一次运算准备
  209.                 ans1=0;
  210.                 ans2=0;
  211.                 for(i=0;i<8;i++)        //清除按键缓存
  212.                         num1[i]=0;
  213.                 for(i=0;i<8;i++)
  214.                         num2[i]=0;
  215.                 if(conflag==1)
  216.                 {
  217.                         conflag=0;
  218.                         goto here;           //跳转到连续运算
  219.                 }
  220.         }
  221. }
  222. /*****初始化程序*****/
  223. void maininit(void)        
  224. {
  225.         delayms(100); //等待液晶初始化
  226.         lcd_init();
  227.         lcd_setxy(0,0);
  228.         lcdwrite_data('0');
  229.         lcd_setxy(0,0);
  230.         IT0=1;//下降沿触发
  231.         EX0=1;//开外部中断0
  232.         IT1=1;//下降沿触发
  233.         EX1=1;//开外部中断1
  234.         EA=1; //开中断
  235. }
  236. /***清零中断程序******/
  237. void EX0_int() interrupt 0
  238. {
  239.         if(beepflag==1)        //若开声音则每一次按键均鸣叫
  240.         {
  241.                 beep=0;
  242.                 delayms(500);
  243.                 beep=1;
  244.         }
  245.         lcdwrite_com(0x01); //显示清屏
  246.         lcd_setxy(0,0);
  247.         lcdwrite_data('0');
  248.         lcd_setxy(0,0);
  249.         num='N';                          //数字初始化
  250.         keynum1=0,keynum2=0,sign=0;
  251.     ans1=0,ans2=0,ans=0,point=0;
  252.         conflag=0,newcalc=0;
  253.         ac=1;
  254. }
  255. /***声音中断程序******/
  256. void EX1_int() interrupt 2
  257. {
  258.         beepflag=~beepflag;
  259.         if(beepflag==1)  //若开声音则每一次按键均鸣叫
  260.                 {
  261.                 beep=0;
  262.                 delayms(500);
  263.                 beep=1;
  264.         }
  265. }
  266. /*****键盘扫描程序*****/
  267. uchar keyscan()
  268. {        
  269.     num='N';        //若没有按下任何按键,则返回'N'
  270.     P1=0xfe;        //扫描第一行
  271.     temp=P1;
  272.     temp=temp&0xf0;
  273.     while(temp!=0xf0) //扫描列
  274.     {
  275.         delayms(10);
  276.         temp=P1;
  277.         temp=temp&0xf0;
  278.         while(temp!=0xf0)
  279.         {
  280.             temp=P1;                        
  281.             switch(temp)
  282.             {
  283.                 case 0xee:num=7;
  284.                     break;                                       
  285.                 case 0xde:num=8;
  286.                     break;                                                
  287.                 case 0xbe:num=9;
  288.                     break;
  289.                 case 0x7e:num='/';
  290.                     break;
  291.             }                                                        
  292.             while(temp!=0xf0)         //等待松手
  293.             {
  294.                 temp=P1;
  295.                 temp=temp&0xf0;
  296.             }
  297.         }
  298.     }
  299.     P1=0xfd;                //扫描第二行         
  300.         temp=P1;
  301.         temp=temp&0xf0;
  302.         while(temp!=0xf0) //扫描列
  303.         {
  304.                 delayms(10);
  305.                 temp=P1;
  306.                 temp=temp&0xf0;
  307.                 while(temp!=0xf0)
  308.                 {
  309.                         temp=P1;                        
  310.                         switch(temp)
  311.                         {
  312.                                 case 0xed:num=4;
  313.                                         break;                                       
  314.                                 case 0xdd:num=5;
  315.                                         break;                                                
  316.                                 case 0xbd:num=6;
  317.                                         break;
  318.                                 case 0x7d:num='*';
  319.                                         break;
  320.                         }
  321.                      while(temp!=0xf0)
  322.                         {
  323.                                 temp=P1;
  324.                                 temp=temp&0xf0;                 //等待松手
  325.                         }
  326.                 }
  327.         }
  328.          P1=0xfb;         //扫描第三行
  329.         temp=P1;
  330.         temp=temp&0xf0;
  331.         while(temp!=0xf0) //扫描列
  332.         {
  333.                 delayms(10);
  334.                 temp=P1;
  335.                 temp=temp&0xf0;
  336.                 while(temp!=0xf0)
  337.                 {
  338.                         temp=P1;                        
  339.                         switch(temp)
  340.                         {
  341.                                 case 0xeb:num=1;
  342.                                         break;                                       
  343.                                 case 0xdb:num=2;
  344.                                         break;                                                
  345.                                 case 0xbb:num=3;
  346.                                         break;
  347.                                 case 0x7b:num='-';
  348.                                         break;
  349.                         }
  350.                      while(temp!=0xf0)        //等待松手
  351.                         {
  352.                                 temp=P1;
  353.                                 temp=temp&0xf0;
  354.                         }
  355.                 }
  356.         }
  357.          P1=0xf7;          //扫描第四行
  358.         temp=P1;
  359.         temp=temp&0xf0;
  360.         while(temp!=0xf0) //扫描列
  361.         {
  362.                 delayms(10);
  363.                 temp=P1;
  364.                 temp=temp&0xf0;
  365.                 while(temp!=0xf0)
  366.                 {
  367.                         temp=P1;                        
  368.                         switch(temp)
  369.                         {
  370.                                 case 0xe7:num=0;
  371.                                         break;                                       
  372.                                 case 0xd7:num='.';
  373.                                         break;                                                
  374.                                 case 0xb7:num='=';
  375.                                         break;
  376.                                 case 0x77:num='+';
  377.                                         break;
  378.                         }
  379.                      while(temp!=0xf0)
  380.                         {
  381.                                 temp=P1;
  382.                                 temp=temp&0xf0;                 //等待松手
  383.                         }
  384.                  }
  385.         }
  386.         if(keypow==0)
  387.         {
  388.                 delayms(5);
  389.                 if(keypow==0)
  390.                 {
  391.                         powflag=1;
  392.                         num='^';
  393.                 }
  394.                 while(keypow==0); //扫描多次方按键
  395.                 delayms(5);
  396.                 while(keypow==0);
  397.         }
  398.         if(beepflag==1&&num!='N')  //若开声音则每一次按键均鸣叫
  399.         {
  400.                 beep=0;
  401.                 delayms(100);
  402.                 beep=1;
  403.         }
  404.     return num;
  405. }
复制代码


评分

参与人数 4黑币 +61 收起 理由
安山有狐狸 + 1 赞一个!
妖行 + 5 很给力!
ZHANGJINGYU + 5 回帖助人的奖励!
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏12 分享淘帖 顶4 踩
回复

使用道具 举报

沙发
ID:161497 发表于 2017-6-2 22:41 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:103952 发表于 2017-6-14 15:03 | 只看该作者

下载地址就在上面哦
回复

使用道具 举报

地板
ID:214665 发表于 2017-6-26 10:47 | 只看该作者
很厉害啊
回复

使用道具 举报

5#
ID:245246 发表于 2017-11-2 11:23 | 只看该作者
下载了可以用吗
回复

使用道具 举报

6#
ID:247636 发表于 2017-11-10 09:21 来自手机 | 只看该作者
我想弄这个,试试看
回复

使用道具 举报

7#
ID:294062 发表于 2018-3-19 15:43 | 只看该作者
看着很不错,学习一下
回复

使用道具 举报

8#
ID:339591 发表于 2018-5-28 10:44 | 只看该作者
看起来很厉害,参考一下
回复

使用道具 举报

9#
ID:341778 发表于 2018-6-11 15:21 | 只看该作者
很棒很不错
回复

使用道具 举报

10#
ID:350401 发表于 2018-6-13 10:21 | 只看该作者
nice,最近在做课程设计,学到了
回复

使用道具 举报

11#
ID:350967 发表于 2018-6-13 11:35 | 只看该作者
厉害了
回复

使用道具 举报

12#
ID:354047 发表于 2018-6-21 18:13 来自手机 | 只看该作者
里面有没有工程
回复

使用道具 举报

13#
ID:162514 发表于 2018-9-19 08:55 | 只看该作者
下来玩玩!
回复

使用道具 举报

14#
ID:530642 发表于 2019-5-9 16:09 | 只看该作者
在哪里下载?
回复

使用道具 举报

15#
ID:258520 发表于 2019-5-16 17:21 | 只看该作者
能输入小数点吗   
回复

使用道具 举报

16#
ID:553254 发表于 2019-6-2 21:09 | 只看该作者
感谢分享
回复

使用道具 举报

17#
ID:655531 发表于 2019-12-3 22:19 | 只看该作者
感谢分享
回复

使用道具 举报

18#
ID:498685 发表于 2019-12-8 10:35 | 只看该作者
感谢分享,值得学习,谢谢楼主
回复

使用道具 举报

19#
ID:639069 发表于 2019-12-19 14:50 来自手机 | 只看该作者
那个lc1602_8.h没有包含怎么办
回复

使用道具 举报

20#
ID:669432 发表于 2019-12-21 18:01 | 只看该作者
已经下载了,谢谢大佬
回复

使用道具 举报

21#
ID:681485 发表于 2020-1-5 19:40 | 只看该作者
这个的按键具体是哪些?要怎么用
回复

使用道具 举报

22#
ID:771836 发表于 2020-6-7 13:19 | 只看该作者
感谢大佬
回复

使用道具 举报

23#
ID:838120 发表于 2020-11-8 19:16 | 只看该作者
你这个能进行8*8位的运算吗
回复

使用道具 举报

24#
ID:834848 发表于 2020-12-27 13:19 来自手机 | 只看该作者
感谢感谢分享   值得学习
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表