找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5190|回复: 4
收起左侧

单片机+1602制作一个能四则运算,连续运算的小型算术型计算器

  [复制链接]
ID:500784 发表于 2019-10-10 18:39 | 显示全部楼层 |阅读模式
摘要:计算器是我们生活中常用的工具,在我们生活中不可或缺。本次设计是设计一个算术型计算器,该计算器能够完成简单的四则运算,还可以实现连续运算。本次是以51单片机为运算核心,以LCD1602为显示的进行硬件上的设计,在软件上以Keil4进行软件编程,以Proteus进行仿真调试,设计出一个能够完成简单的四则运算,实现连续运算的小型算术型计算器。

正文:
一、设计概述
1. 课题意义
    计算器有键盘部分、单片机、显示部分三部分组成,键盘部分主要完成输入功能;单片机主要完成数据处理功能,包括确定按键,完成运算,以及输出数据;显示器部分主要完成单片机输出的显示。基本掌握计算器的设计原理和LCD1602的显示原理,进而熟悉C51的编程和调试方法。
2. 系统功能
   能够完成简单的四则运算,还可以实现连续运算的小型算术型计算器。
   硬件设计上通过Proteus进行电路原理图和仿真运行图的设计,软件设计上以Keil4为基础进行软件编程,将编程生成的.hex文件放入在Proteus已画好的原理图中调试,观察设计结果,并对代码进行修改。

二、硬件设计
                             [size=9.0000pt] 1 [size=9.0000pt]总原理图 图片15.png
     
1.按键设计
矩阵键盘的原理是见I/O口分为行线和列线,按键设置在跨接行线和列线的交点上,列线通过上拉电阻接正电源,进而形成基本的4x4行列式键盘。本次设计以矩阵键盘为基本的输入按键分别为123+456-789x0CLR=/ 形成计算器对应的基本的数字键和功能键     



图片14.png
显示设计

LCD1602是一种专门用来显示字母、数字、符号等的点阵型液晶模块,它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,因此它比较适合用在计算器的显示。
图片13.png
三、软件设计
1. 按键扫描
   本次设计中在软件上使用了反转法进行按键的扫描,其过程为先让行输出全为0列输出全为1读取与按键相接的P1口的状态,读取按键的列值,然后让行输出全为1列输出全为0读取与按键相接的P1口的状态,读取按键的行值,根据行值和列值可知其键值。
0.jpg
                           [size=9.0000pt]    4按键扫描流程图[size=9.0000pt]          

2.显示设计
LCD1602是一个16字双行的显示模块,在使用LCD1602之前我们应该先对其进行初始化,其初始化的内容有光标设置、显示设置和清屏指令等。初始化完成后从其参考手册可知LCD1602中已经存储有基本字模数据,所以想要在LCD1602中显示字符,只需要对LCD1602写入该字符相对应的ASCII码即可显示出相应的字符。LCD1602的写入可分为写数据和写命令,当要写入数据时其对应的状态为RS=1RW=0E为下降沿,然后通过单片机I/O口写入相应的数据。当要写入命令时其对应的状态为RS=0RW=0E为下降沿,然后通过单片机I/O口写入相应的命令。 0.jpg
                             [size=9.0000pt]5  LCD1602写指令图
3.键值处理
     首先我们初始化液晶显示器,然后显示出第一个被按下的数,并且使光标右移,如果有第二个数按下,则据继续显示,以此类推,然后把所有显示出来的数换算成一个数,如果按下+”号,则显示出“+”,并且同理显示出“+”号后面按下的数字,然后调用加子程序,运算出结果,如果按下的是“-,则调用减子程序,如果按下“*”,则调用乘子程序,如果按下“/”,则调用除子程序。然后再调用显示结果子程序,显示出结果。
0.jpg
                          6键值运算流程图


四、系统测试
1.加法测试
   图片9.png


2.减法测试
图片8.png

3.乘法测试
图片7.png


4.除法测试
图片5.png

5.连续运算测试
图片4.png 图片3.png


五、结论
经过调试可知此次设计已经基本达到要求,该计算器能够完成简单的四则运算,还可以实现连续运算。但只能进行整数的运算,无法进行浮点型数据运算,运算的连续运行需要一个个数的连续运算,无法做到一次性连续运算。
七、附录
1.系统电路图
         

2.实物运行图
0.png

单片机源程序如下:
  1. /* 实现两个数的运算,每个数的位数至少可以八位  */
  2. #include<reg52.h>        
  3. #include<math.h>               
  4. typedef unsigned char uint8;
  5. typedef unsigned int uint16;
  6. #define GPIO_KEY P1
  7. sbit rw=P2^5;
  8. sbit rs=P2^6;
  9. sbit e=P2^7;
  10. sbit k1=P3^0;
  11. uint8  num='N';                      //键值
  12. uint16 k0,k2,k3;          // 数组位
  13. uint8 fuhao;                //定义具体的那个符号,是加减还是乘除。
  14. uint8 flag,r;               //定义符号键标志位,小数点标志位和继续运算标志位 这个是统称
  15. float a,b,c,zheng,xiao;         //定义运算数据的第一个和第二个及等于的数变量
  16. uint8  shuzi1[5]={0},shuzi2[5]={0},shuzi3[4]={0};
  17. uint8 code dat1[]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x78-0x30, 0,0x2e-0x30,0x3d-0x30,0xfd-0x30 };//保存显示的数据 123+ 456- 789* 0.CLR /
  18. void delay(uint16 i)
  19. {  uint16 x,y;
  20. for(x=0;x<i;x++)
  21. for(y=0;y<114;y++);        
  22. }
  23. void lcdcommand(uint8 m)   //写命令
  24. {
  25.         delay(1);
  26.         rs=0;
  27.         rw=0;
  28.         e=0;
  29.         P0=m;
  30.         e=1;
  31.         delay(1);
  32.         e=0;
  33. }
  34. void lcddata(uint8 dat)          //写数据
  35. {
  36.         delay(1);
  37.         rs=1;
  38.         rw=0;
  39.         e=0;
  40.         P0=dat;
  41.         e=1;
  42.         delay(1);
  43.         e=0;
  44.         rs=0;
  45. }
  46. void lcdcsh()        //初始化         
  47. {
  48.         delay(5);
  49.         lcdcommand(0x38); //功能设定 8位总线 两行 5X7点阵
  50.         delay(5);
  51.         lcdcommand(0x38);
  52.         lcdcommand(0x38);
  53.         lcdcommand(0x0c); // 开显示 无光标
  54.         lcdcommand(0x06); //光标左移
  55.         lcdcommand(0x01); // 清屏
  56.         lcdcommand(0x80);//数据从左上开始
  57.         num='N';
  58.         flag=0;
  59.         fuhao=0;
  60.         a=0;
  61.         b=0;
  62.         c=0;
  63.    zheng=xiao=0;;
  64.         k0=0;k2=0;k3=0;

  65. }
  66. void shuchu(float e)                                        //在屏幕上显示数值e
  67. {
  68. char shuzu[10];
  69.   long z;  
  70.   int x=0;
  71.   float f;
  72.          
  73.     (long)z=e;                          //整数处理
  74.         if(z==0)
  75.         lcddata('0');

  76.         while(z!=0)
  77.         {        shuzu[x]=z%10;
  78.             z=z/10;
  79.                 x++;
  80.         }
  81.   for(x=x-1;x>=0;x--)
  82.         lcddata(shuzu[x]+0x30);

  83.         (long)z=e;                                                    //小数处理
  84. (float)f=e-z;

  85. if(f>0.000)
  86. {        x=0;
  87.    lcddata('.');
  88.    z=f*1000;
  89.           while(z!=0)
  90.         {        shuzu[x]=z%10;
  91.             z=z/10;
  92.                 x++;
  93.         }
  94.   for(x=x-1;x>=0;x--)
  95.         lcddata(shuzu[x]+0x30);

  96. }
  97. }

  98. void fuzhi()        // 显示与向数组赋值
  99. {        
  100.                         
  101.                         if(flag==0)         //是否按下符号键
  102.                            {
  103.                              delay(50);
  104.                  if(dat1[num]=='.')
  105.                                  r=1;
  106.                        if((r==0)&&(k0<5))
  107.                            {
  108.                             shuzi1[k0]=dat1[num];
  109.                                 k0++;
  110.                                 lcddata(0x30+dat1[num]);
  111.                                 }
  112.                            else if((r==1)&&(k3<4))
  113.                           {
  114.                           
  115.                             shuzi3[k3]=dat1[num];
  116.                                 k3++;
  117.                                 lcddata(0x30+dat1[num]);
  118.                                 }
  119.                           }
  120.          r=0;
  121.                  if(flag==1)         //是否按下符号键
  122.                            {
  123.                              delay(50);
  124.                  if(dat1[num]=='.')
  125.                                  r=1;
  126.                        if((r==0)&&(k2<5))
  127.                            {
  128.                             shuzi2[k2]=dat1[num];
  129.                                 k2++;
  130.                                 lcddata(0x30+dat1[num]);
  131.                                 }
  132.                            else if((r==1)&&(k3<4))
  133.                           {
  134.                           
  135.                             shuzi3[k3]=dat1[num];
  136.                                 k3++;
  137.                                 lcddata(0x30+dat1[num]);
  138.                                 }
  139.                         }

  140. }                  
  141. void  sz(uint8 s[8],int x)                                                  //数组转为数值
  142. {
  143.   int i,j;
  144.   zheng=0;
  145.   xiao=0;
  146.   i=0;                                         //整数
  147.   while(x>0)                                   
  148.    {
  149.          zheng=zheng*10+s[i];
  150.             i++;
  151.          x--;
  152.    }
  153. i=1;                                                   //小数
  154. j=k3;  
  155. while(j>0)
  156. {
  157. xiao=xiao*10+s[i];
  158. i++;
  159. j--;
  160. }
  161.   
  162. for(;k3>0;k3--)
  163. xiao=xiao/10;
  164. zheng=zheng+xiao;
  165. k0=k2=k3=0;         
  166. }         
  167. void KeyDown(void)
  168. {
  169.         char L=0;
  170.         GPIO_KEY=0x0f;
  171.         if(GPIO_KEY!=0x0f)//读取按键是否按下
  172.         {
  173.                 delay(10);//延时10ms进行消抖
  174.                 if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
  175.                 {        
  176.                         //测试列
  177.                         GPIO_KEY=0X0F;
  178.                         switch(GPIO_KEY)
  179.                         {
  180.                                 case(0X07):        num=0;break;
  181.                                 case(0X0b):        num=1;break;
  182.                                 case(0X0d): num=2;break;
  183.                                 case(0X0e):        num=3;break;
  184.                         }
  185.                         //测试行
  186.                         GPIO_KEY=0XF0;
  187.                         switch(GPIO_KEY)
  188.                         {
  189.                                 case(0X70):        num=num;break;
  190.                                 case(0Xb0):        num=num+4;break;
  191.                                 case(0Xd0): num=num+8;break;
  192.                                 case(0Xe0):        num=num+12;break;
  193.                         }
  194.                         while((L<50)&&(GPIO_KEY!=0xf0))         //检测按键松手检测
  195.                         {
  196.                                 delay(10);
  197.                                 L++;
  198.                         }
  199.                 }
  200.         }
  201. }
  202. void banduan()
  203. {         
  204.    switch(fuhao)
  205.    {
  206.    case 0:                     
  207.                      sz(shuzi1,k0);
  208.                                        a=zheng;
  209.                                 lcdcommand(0x01);
  210.                                                   lcdcommand(0x40+0x80);
  211.                             shuchu(a);
  212.                                                 b=0;
  213.                                                 flag=0;
  214.                                                 fuhao=0;     //全部清除为0
  215.                                                 zheng=0;
  216.                                                 xiao=0;         
  217.                                                 break;



  218.     case 1:                  
  219.                              
  220.                             lcdcommand(0x40+0x80);
  221.                                                 c=a+b;
  222.                                                 lcddata(0x3d); //显示等于号=
  223.                                                 shuchu(c);
  224.                                                 a=0;
  225.                                                 b=0;
  226.                                                 flag=0;
  227.                                                 fuhao=0;     //全部清除为0
  228.                                                 zheng=0;
  229.                                                 xiao=0;   
  230.                                                 break;

  231.      case 2:               
  232.                                   lcdcommand(0x40+0x80);
  233.                                        
  234.                                                 if(a>b)
  235.                                         {        c=a-b;
  236.                                         lcddata(0x3d);         //显示等于号=
  237.                                         }
  238.                                                 else if(a<b)
  239.                                                 {
  240.                                                 c=b-a;
  241.                                                 lcddata(0x3d);                                    //显示等于号=
  242.                                                 lcddata(0x2d);                             //显示负号-
  243.                                                  }
  244.                                                  if(a==b)
  245.                                                  c=0;
  246.                                                 shuchu(c);
  247.                                                 a=0;
  248.                                                 b=0;
  249.                                                 flag=0;
  250.                                                 fuhao=0;  //全部清除为0
  251.                                                 zheng=0;
  252.                                                 xiao=0;        
  253.                                                 break;

  254.      case 3:               
  255.                                                 lcdcommand(0x40+0x80);
  256.                                                 c=a*b;
  257.                                                 lcddata(0x3d); //显示等于号=
  258.                                                 shuchu(c);
  259.                                                 a=0;
  260.                                                 b=0;
  261.                                                 flag=0;
  262.                                                 fuhao=0; //全部清除为0
  263.                                                 zheng=0;
  264.                                                 xiao=0;        
  265.                                                 break;

  266.      case 4:                        
  267.                                                 lcdcommand(0x40+0x80);
  268.                                                 c=a/b;                                                         
  269.                                                 lcddata(0x3d); //显示等号
  270.                                                 shuchu(c);
  271.                                                 a=0;
  272.                                                 b=0;
  273.                                                 flag=0;
  274.                                                 fuhao=0; //全部清除为0
  275.                                                 zheng=0;
  276.                                                 xiao=0;
  277.                                        
  278.                                                 break;
  279.         }

  280. }

  281. void main()
  282. {         
  283.   
  284.   
  285.   
  286.     lcdcsh();

  287. while(1)
  288. { num='N';
  289.    KeyDown();
  290.    if(num==13)
  291.    {
  292.        lcdcommand(0x01);//清零
  293.                                                   
  294.                    flag=0;
  295.                    fuhao=0;
  296.                     a=0;
  297.                      b=0;
  298.                        c=0;
  299.                zheng=xiao=0;
  300.                            k0=k2=k3=0;
  301.    }
  302. while(1)
  303. {         
  304.   num='N';
  305.      KeyDown();
  306.   if(num==0||num==1||num==2||num==4||num==5||num==6||num==8||num==9||num==10||num==12||num==16)        //1-9-0-.
  307.          fuzhi();
  308.      if(num==13)
  309.    {
  310.        lcdcommand(0x01);//清零
  311.                                                   
  312.                    flag=0;
  313.                    fuhao=0;
  314.                     a=0;
  315.                      b=0;
  316.                        c=0;
  317.                zheng=xiao=0;
  318.                            k0=k2=k3=0;
  319.                                break;
  320.         }


  321.    if(num==3||num==7||num==11||num==15)
  322.    {
  323.    
  324.         flag=1;
  325.         switch(num)
  326.         {   case 3: fuhao=1;    break;
  327.         case 7:          fuhao=2;  break;
  328.                 case 11: fuhao=3;   break;
  329.                 case 15: fuhao=4;   break;

  330.         }
  331.                 sz(shuzi1,k0);
  332.                 c=zheng;

  333. loop:                a=c;        
  334.                         lcdcommand(0x01);
  335.                         lcdcommand(0x80);
  336.                         shuchu(a);
  337.                         lcddata(0x30+dat1[num]);
  338.                         break;
  339.      }
  340.    }
  341.    
  342.   while(1)
  343.   {                    
  344.    num='N';
  345.      KeyDown();
  346.   if(num==0||num==1||num==2||num==4||num==5||num==6||num==8||num==9||num==10||num==12)        //1-9-0
  347.          fuzhi();
  348.           if(num==13)
  349.    {
  350.        lcdcommand(0x01);//清零
  351.                                                   
  352.                    flag=0;
  353.                    fuhao=0;
  354.                     a=0;
  355.                      b=0;
  356.                        c=0;
  357.                zheng=xiao=0;
  358.                            k0=k2=k3=0;
  359.               break;
  360.    
  361. ……………………

  362. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有程序51hei提供下载:
1.c.zip (2.41 KB, 下载次数: 125)
图片6.png

评分

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

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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