找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机制作的多位连续四则运算的计算器 Proteus仿真程序

[复制链接]
跳转到指定楼层
楼主
     基于单片机制作的多位连续四则运算的计算器

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)

单片机源程序如下:
  1. #include<reg52.h>//52单片机头文件
  2. #include<math.h>//要用到数学计算公式,所以调用
  3. #include <intrins.h>//移位
  4. #define key P2    //定义矩阵键盘的I/O口
  5. #define GPIO_LCD P0//定义LCD1602  数据/命令的输入端
  6. unsigned char number[20];//用来储存我们所按键按下去的字符和数字
  7. unsigned char add=0;//是否按过+号
  8. unsigned char subtract=0;//是否按过-号
  9. unsigned char ride=0;//是否按过*号
  10. unsigned char divide=0;//是否按过/号
  11. unsigned char eliminate=0;//是否按过清除键
  12. unsigned char minus=0;//是否计算的数据需要添加负号
  13. unsigned char decimals=0;//是否计算的数据需要小数点
  14. unsigned char equal=0;//是否按下等号键
  15. sbit LCD_RS =P3^4;//定义LCD的模式选择,1为写数据,0为写命令
  16. sbit LCD_RW =P3^5;//定义LCD功能  1是读,0是写
  17. sbit LCD_E =P3^6;//定义LCD使能端
  18. unsigned long a=0,b=0;//用于储存我们所要运算的数据
  19. unsigned char i;//定义一个全局变量
  20. unsigned char LCD_Wait(void)//判忙函数
  21. {
  22.               LCD_RS=0;
  23.               LCD_RW=1;
  24.               _nop_();
  25.               LCD_E=1;
  26.               _nop_();
  27.             
  28.               LCD_E=0;
  29.               return               GPIO_LCD;                           
  30. }

  31. void delay(void)   //延时函数
  32. {
  33.     unsigned char x,z;
  34.     for(z=19;z>0;z--)
  35.         for(x=130;x>0;x--);
  36. }



  37. void LCD_Write_Com(unsigned char com)//LCD1602写命令函数
  38. {
  39. LCD_RS =0;
  40. LCD_RW =0;
  41. GPIO_LCD=com;
  42. delay() ;
  43. LCD_E=1;
  44. delay() ;
  45. LCD_E=0;
  46. delay() ;
  47. }
  48. void LCD_Write_Date( unsigned char input)//LCD1602写数据函数
  49. {
  50.               LCD_RS=1;
  51.               LCD_RW=0;              ;
  52.               LCD_E=0;
  53. _nop_();
  54.               GPIO_LCD =input;            
  55.               _nop_();
  56.               LCD_E=1;            
  57. _nop_();
  58.               LCD_E=0;                                          
  59. _nop_();
  60.               LCD_Wait();
  61. }
  62. void LCD_Initial()//LCD1602初始化函数
  63. {
  64. delay();
  65. LCD_Write_Com (0x38);
  66. delay() ;        
  67. LCD_Write_Com (0x38);
  68. delay() ;
  69. LCD_Write_Com (0x08);
  70. delay() ;
  71. LCD_Write_Com (0x0c);
  72. delay() ;  
  73. LCD_Write_Com (0x06);
  74. delay() ;
  75. LCD_Write_Com (0x01);
  76. delay() ;
  77. }
  78. 以上函数是LCD1602的模块化函数库,如果看不懂,需要先学习一下LCD1602.如果懒得学的话,可以直接用这个函数库,前提是上面定义的变量要整体一一对应,各个端口的引脚也要和你的实际端口一一对应
  79. unsigned long calculate()//计算数据模块
  80. {
  81.    unsigned long value=0;
  82.                
  83.                            
  84.                                           if(add)//如果我们按键按下了加号,那么在计算时进入这个加运算
  85.                                           {
  86.                                                         value=a+b;
  87.                                           }
  88.                                           if(subtract) //如果我们按键按下了减号,那么在计算时进入这个减运算
  89.                                           {
  90.                                                 if(a>=b)
  91.                                                                                                   value=a-b;
  92.                                                                                     else
  93.                                                                                     {
  94.                                                                                         value=b-a;
  95.                                                                                                   minus=1;//说明后面的数大于前面的额数,将其标志为一,在输出结果是,可以利用它判断是否输出负号
  96.                                                                                     }
  97.                                                                       }
  98.                                           if(ride)//乘法运算
  99.                                           {
  100.                                           value=a*b;
  101.                                           }
  102.                                           if(divide)//除法运算
  103.                                           {
  104.                                           value=(unsigned long)(((float)a/b)*1000);//因为此计算器是,保留小数点后三位,所以,两数相除,1/2=0.5,那么通过这个,可以让其先等于200,方便我们后续的结果处理
  105.                                                         decimals=1;//标示结果已经<0,最后结果要出现小数点,
  106.                                           }
  107.                                          
  108.                                           return value;//返回计算的结果
  109.                                           }
  110.                            
  111.                            
  112.             
  113. void result()
  114.               {
  115.               unsigned char f=0;//标志结果需要保留什么数
  116.                             unsigned long value;
  117.                            
  118.                             if(equal==1)
  119.                             {
  120.                                           value=calculate();//将上面计算算出来的值赋值给这个函数中的value
  121.                                           LCD_Write_Com (0x40);//写LCD1602的命令,使得结果数据显示在第二排
  122.                                           delay();
  123.                   LCD_Write_Com (0xcf); //从第二排最后一个位置依次向左写数据
  124.                                           delay();
  125.                                           LCD_Write_Com (0x04);//光标从第二排最后一个数据向左移动
  126.                                           delay();
  127.       do
  128.       {
  129.                                          
  130.                                                         LCD_Write_Date(0x30+value%10);//0x30是LCD字符库中数字0的代号,例如我们想写入 2这个结果,根据前面计算函数,计算函数已经将2变成2000,所以这里是让其变回来从后往前依次写数据到LCD1602上,
  131.                                                         delay();
  132.                                                         f++;//value的位数如果计算结果是0.2,则通过计算函数变成200,那么这时的f就会被加到3,
  133.                                                         if(decimals&&f==3)//接上如果f被加到三
  134.                                                         LCD_Write_Date(0x2e);//就在LCD1602上显示小数点
  135.                                              delay();
  136.                                                         value/=10;//如果经过计算函数后是2000,则经过一次这个 value减少一位(减少的哪一位的数据已经写入LCD1602中了)
  137.                                                         delay();
  138.                                           }
  139.                                           while(value);//当value 被用尽后跳出循环
  140.                                           if(decimals&&f<=3)//decimals是标志是否进行的是除法运算
  141.                                           {
  142.                                                         if(f==3)
  143.                                                         {
  144.                                                         LCD_Write_Date(0x30);//如果是三,因为前面程序已经在对应位置加了小数点了,这时我们住需要再在前面加一个0就可以了,如果没有这条语句,0.5 的显示就是.5
  145.                                                         }
  146.                                                         else
  147.                                                                       {
  148.                                                                       while(3-f)//当f<3时进入这程序
  149.                                               {LCD_Write_Date(0x30);
  150.                                                                                     f++;
  151.                                                                       }
  152.                                                                       LCD_Write_Date(0x2e);//写小数点
  153.                                                                       delay();
  154.                                                           LCD_Write_Date(0x30);//写数据0            
  155.                                                         }                                                                     
  156.                                           }                                                      
  157.                                 if(minus)//如果有负号标志
  158.                                                         LCD_Write_Date(0x2d);//在LCD1602上显示负号
  159.                                                         add=0;
  160.                                 subtract=0;
  161.                                 ride=0;
  162.                                 divide=0;
  163.                                 equal=0;
  164.                                                         decimals=0;
  165.                                                         minus=0;
  166.                                                         eliminate=0;
  167.                             }            
  168.                            
  169.               }
  170. void main()
  171. {

  172.               int j,k=0,g;
  173.               i=0;

  174.               LCD_Initial();//初始化LCD1602

  175.               j=0;
  176.               while(1)
  177.               {
  178.               P2=0xfe;//扫描第一行是否有按键按下
  179.               while((P2&0xf0)!= 0xf0)               
  180.               {
  181.                             delay();              //延时消抖                     
  182.     while((P2&0xf0)!=0xf0)              //确认按下
  183.                             {
  184.                                           switch(key)              //锁定按的是哪一个键                                         
  185.                                           {
  186.                                                         case 0xee: number[i]= 7; i++;k=1;break;//k=1表明按下的是数字键
  187.                                                         case 0xde: number[i]=8;i++;k=1; break;
  188.                                                         case 0xbe: number[i] =9; i++;k=1;break;
  189.                                                         case 0x7e: number[i]= '/';divide++;i++;break;//计算对应的表示功能键的变量按键次数
  190.                                                         default:   number[i] = '#';
  191.                                           }
  192.      while((P2& 0xf0) != 0xf0) ;//扫描第二行
  193.                             }
  194.               }
  195.               P2= 0xfd;            
  196.               while((P2&0xf0) != 0xf0)
  197.               {
  198.                             delay();

  199.                             while((P2& 0xf0) != 0xf0)
  200.                             {
  201.                                           switch(key)
  202.                                           {
  203.                                                         case 0xed: number[i]= 4;i++;k=1; break;
  204.                                                         case 0xdd: number[i] = 5; i++;k=1;break;
  205.                                                         case 0xbd: number[i] = 6;i++;k=1; break;
  206.                                                         case 0x7d: number[i] = '*';ride++;i++;break;
  207.                                                                      
  208.                                                         default:   number[i] = '#';
  209.                                           }

  210.                                           while((P2&0xf0)!= 0xf0)
  211.                                                         ;
  212.                             }
  213.               }
  214. P2= 0xfb;//扫描第三行
  215.               while((P2& 0xf0) != 0xf0)
  216.               {
  217.                             delay();
  218.                            
  219.                             while((P2& 0xf0) != 0xf0)
  220.                             {
  221.                                           switch(key)
  222.                                           {
  223.                                                         case 0xeb: number[i] =1; i++;k=1;break;
  224.                                                         case 0xdb: number[i]= 2; i++;k=1;break;
  225.                                                         case 0xbb: number[i] = 3; i++;k=1;break;
  226.                                                         case 0x7b: number[i]= '-';subtract++;i++;break;
  227.                                                                      
  228.                                                         default: number[i] = '#';
  229.                                           }

  230.                                           while((P2&0xf0)!= 0xf0);
  231.                             }
  232.               }
  233.               P2= 0xf7;//扫描第四行
  234.               while((P2&0xf0)!=0xf0)
  235.               {
  236.                             delay();
  237.     while((P2&0xf0)!=0xf0)
  238.                             {
  239.                                           switch(P2)
  240.                                           {
  241.                                                         case 0xe7: number[i]= 'eliminate=1;i++; break;
  242.                                                         case 0xd7: number[i]=0;i++;k=1; break;
  243.                                                         case 0xb7: number[i]= '=';i++;equal++;break;
  244.                                                         case 0x77: number[i]= '+';add++;i++;break;
  245.                                                         default:   number[i] = '#';
  246.                                           }

  247.                                           while((P2&0xf0)!= 0xf0);
  248.                             }
  249.               }
  250.               if(k==1)//如果有数字键按下,进入此程序
  251.               {
  252.               if(add+subtract+ride+divide==1)//如果有第一个加减乘除键被按下则进入负号符号键后面的数据存储,如1+2  这里的b存 的是2
  253.               {
  254.                            
  255.               b=b*10+number[i-1];
  256.                             g=calculate();
  257.               }
  258.                            
  259.                                             if(add+subtract+ride+divide==2)//如果2+2+1,这里面的a=2+2, b=1,因为g村存储了前面只有一个加号时的value
  260.               {
  261.                             a=g;
  262.                             b=0;
  263.                 b=b*10+number[i-1];
  264.               }
  265.                                             if(add+subtract+ride+divide==3)//如2+2+2+3,这里的a=2+2+2,b=3,同理往下
  266.               {
  267.                             a=g;
  268.                             b=0;
  269.                 b=b*10+number[i-1];
  270.               }
  271.                                             if(add+subtract+ride+divide==4)
  272.               {
  273.                             a=g;
  274.                             b=0;
  275.                 b=b*10+number[i-1];
  276.               }
  277. if(add+subtract+ride+divide==0)
  278.               {
  279.               a=a*10+number[i-1];
  280.               }
  281.               g=calculate();

  282.               k=0;
  283.   }
  284.               LCD_Write_Com (0x80); //将要输入的数据放在首行
  285.               delay();
  286.               for(j=0;j<i;j++)
  287.               {
  288.                             if(number[j]=='+'||number[j]=='||number[j]=='-'||number[j]=='*'||number[j]=='/'||number[j]=='=')
  289.                  LCD_Write_Date( number[j]);//写符号位
  290.                             else
  291.                                           LCD_Write_Date( number[j]+0x30);//写数据位
  292.                             delay();
  293.               }
  294.               if(eliminate==1)//一旦按下清除键,LCD1602内数据会自动清零,可以反复输入
  295.               {

  296.                             LCD_Initial();
  297.                             eliminate=0;
  298.                             i=0;
  299.                             a=0;
  300.                             b=0;
  301.               }
  302.               result();              //调用结果函数

  303.               }

  304. }
复制代码

全部资料51hei下载地址:
简易计算器.rar (375.26 KB, 下载次数: 125)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:677934 发表于 2019-12-31 13:06 | 只看该作者
能不能实现连乘啊
回复

使用道具 举报

板凳
ID:930485 发表于 2021-6-4 08:58 | 只看该作者
里面能进行小数的运算吗
回复

使用道具 举报

地板
ID:751615 发表于 2021-7-10 08:40 | 只看该作者
计算的都是错的,你还直接超过来了?卧槽
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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