找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10849|回复: 0
收起左侧

简易单片机计算器的课程设计实验报告(程序+实验记录)

[复制链接]
ID:477682 发表于 2019-2-18 13:58 | 显示全部楼层 |阅读模式
一、 实验题目
基于51单片机的简易计算器
二、 内容
1、实验内容
              该系统通过单片机控制,实现对4*4键盘扫描进行实时的按键检测,并把检测数据存储下来。整个计算器系统的工作过程为:首先存储单元初始化,显示初始值和键盘扫描,判断按键位置,得出按键值,单片机则对数据进行储存与相应处理转换,之后送入数码管动态显示。整个系统可分为三个主要功能模块:功能模块一,实时键盘扫描;功能模块二,数据转换为了数码管显示;功能模块三,数码管动态显示。
            
2、功能说明
  • 矩阵按键对应表
s1 s2 s3 s4         1  2  3  +
s5 s6 s7 s8         4  5  6  -
s9 s10 s11 s12      7  8  9  *
s13 s14 s15 s16     0  clr  =  /
  • 显示模块
本来计划用数码管显示,结果发的单片机数码管驱动芯片与预想的不一样,不是通过段选,位选的方式。然后就没看的特别懂,临时换成了lcd1602显示屏,驱动程序较为固定,且显示的也更加全面。
  • 中断的运用
通过中断定时器零设置中断,定时10s,开机10秒后,执行中断,自动清零,相当于自动按下按键14。
三、 原理
见下页。

四、 实验记录
因为在课堂上未记录实验现象,所以在课下在按照自己的单片机的引脚设置更改了程序后,再将程序下载到51单片机中,得到以下实验结果:
刚下入程序时,初始化后的显示如下:
            
然后进行一些简单的计算显示:
最多可以进行八位数的运算:
            
五、 修改后程序框图

六、总结
              本来在实验课上由于前期准备不够充分,课上经历了更改显示方式,由数码管显示改为了1602液晶屏显示,且在实验课上仅完成了计算器的功能,能够实现加减乘除的运算,但是不能实现连续运算功能。在课下又经过充分的学习了解,成功的加上了定时器中断,实现了定时清屏功能。由此可见,充足的课前准备能够极大地提高效率。
              本次实验满足了设计要求,包含有矩阵按键的使用,定时器中断,LCD1602外设,将要求用到的内容都成功的联系在了一起。虽然该例子中的定时器中断在实际生活中并不会这样使用,不过通过这种方式,也让我对定时器中断的使用有了更加深刻的认识,也能够通过定时器中断进行一些简单的设计。
              通过本次实验,加深了对51单片机原理的理解与认知,尤其是对矩阵按键扫描判断,定时器中断,LCD1602外设的应用等方面的原理的学习也提高了一个层次。通过本次实验,提高了自己的逻辑分析能力,发现问题解决问题的能力。提高了对C语言编程的理解与应用,能够灵活的运用例程达到自己的设计要求,完成实验。
七、附录
  1. #include "REG52.h"
  2. typedef unsigned char uint8;
  3. typedef unsigned int uint16;
  4. typedef unsigned long ulong;
  5. uint8 key;//存放按键值
  6. uint8 num,number,t;
  7. uint8 fuhao;//定义具体的那个符号,是加减还是乘除。
  8. uint8 flag;              //定义有没有按下符号键,这个是统称
  9. long a,b,c,d;              //定义运算数据的第一个和第二个及等于的数变量
  10. uint8 k; //定义小数点后面显示的位数
  11. uint8 biao;

  12. sbit rs = P1^0;            
  13. sbit rw = P1^1;            
  14. sbit e = P1^2;              //LCD使能端
  15. uint8 dat1[]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2b-0x30 };//保存显示的数据

  16. void Delay(unsigned int);              //声明延时函数
  17. void InterruptTimer0() ;

  18. void lcdwrc(uint8 c)                //写指令数据
  19. {
  20.               Delay(5);
  21.               rs=0;
  22.               rw=0;
  23.               e=0;
  24.               P0=c;
  25.               e=1;
  26.               Delay(5);
  27.               e=0;
  28. }
  29. void lcdwrd(uint8 dat)                            //写显示数据
  30. {
  31.               Delay(5);
  32.               rs=1;
  33.               rw=0;
  34.               e=0;
  35.               P0=dat;
  36.               e=1;
  37.               Delay(5);
  38.               e=0;
  39.               rs=0;
  40. }

  41. void lcdinit()                               //lcd初始化
  42. {
  43.               Delay(7);
  44.               lcdwrc(0x38);
  45.     Delay(3);
  46.               lcdwrc(0x38);
  47.               Delay(3);
  48.               lcdwrc(0x38);
  49.               Delay(3);
  50.               lcdwrc(0x38);
  51.               lcdwrc(0x08);
  52.               lcdwrc(0x01);
  53.               lcdwrc(0x06);
  54.               lcdwrc(0x0c);
  55.               key=0;
  56.               num=0;
  57.               flag=0;
  58.               fuhao=0;
  59.               a=0;
  60.               b=0;
  61.               c=0;
  62.               d=0;
  63.               biao=0;
  64. }

  65. //函数名称:Delay
  66. //函数功能:延时函数
  67. //入口参数:uiCount-延时参数,每加1增加0.5ms
  68. void Delay(unsigned int uiCount)
  69. {
  70.               unsigned char j = 244;
  71.               for(;uiCount > 0;uiCount--) while(--j);            
  72. }

  73. void keyscan()                //矩阵按键扫描函数
  74. {
  75.               P2=0xef;   //令第一行为0,然后判断是哪一列按下
  76.               if(P2!=0xef)
  77.               {
  78.                             Delay(5);
  79.                             if(P2!=0xef)
  80.                             {
  81.                                           key=P2&0x0f;
  82.                                           switch(key)
  83.                                           {
  84.                                                         case 0x0e: num=0;break;                //1
  85.                                                         case 0x0d: num=1;break;                //2
  86.                                                         case 0x0b: num=2;break;                //3
  87.                                                         case 0x07: num=3;break;                //加
  88.                                           }
  89.                             }
  90.                             while(P2!=0xef);
  91.                             if(num==0||num==1||num==2)              //确认第一行的数1,2,3
  92.                             {
  93.                                           if(flag==0)              //没有按下符号键
  94.                                           {
  95.                                                         a=a*10+dat1[num];            
  96.                                           }
  97.                                           else
  98.                                           {
  99.                                                         b=b*10+dat1[num];
  100.                                           }
  101.                            
  102.                             }
  103.                             if(num==3)
  104.                             {
  105.                                           flag=1;
  106.                                           fuhao=1;//加号+            
  107.                             }
  108.                             lcdwrd(0x30+dat1[num]);
  109.               }


  110.               P2=0xdf;                                                        //令第二行为0,判断是哪一列按下
  111.               if(P2!=0xdf)
  112.               {
  113.                             Delay(5);
  114.                             if(P2!=0xdf)
  115.                             {
  116.                                           key=P2&0x0f;
  117.                                           switch(key)
  118.                                           {
  119.                                                         case 0x0e: num=4;break;                //4
  120.                                                         case 0x0d: num=5;break;                //5
  121.                                                         case 0x0b: num=6;break;                //6
  122.                                                         case 0x07: num=7;break;                //减—
  123.                                           }            
  124.                             }
  125.                             while(P2!=0xdf);
  126.                             if(num==4||num==5||num==6)
  127.                             {
  128.                                           if(flag==0)              //没有按下符号键
  129.                                           {
  130.                                                         a=a*10+dat1[num];            
  131.                                           }
  132.                                           else
  133.                                           {
  134.                                                         b=b*10+dat1[num];
  135.                                           }                                         
  136.                             }
  137.                             else
  138.                             {
  139.                                           flag=1;
  140.                                           fuhao=2;//代表减号
  141.                             }
  142.                             lcdwrd(0x30+dat1[num]);
  143.               }


  144.               P2=0xbf;                            //令第三行为0,判断哪一列按下
  145.               if(P2!=0xbf)
  146.               {
  147.                             Delay(5);
  148.                             if(P2!=0xbf)
  149.                             {
  150.                                           key=P2&0x0f;
  151.                                           switch(key)
  152.                                           {
  153.                                                         case 0x0e: num=8;break;                //7
  154.                                                         case 0x0d: num=9;break;                //8
  155.                                                         case 0x0b: num=10;break;  //9
  156.                                                         case 0x07: num=11;break;  //乘*
  157.                                           }            
  158.                             }
  159.                             while(P2!=0xbf);
  160.                             if(num==8||num==9||num==10)
  161.                             {
  162.                                           if(flag==0)              //没有按下符号键
  163.                                           {
  164.                                                         a=a*10+dat1[num];            
  165.                                           }
  166.                                           else
  167.                                           {
  168.                                                         b=b*10+dat1[num];
  169.                                           }                                         
  170.                             }
  171.                             else
  172.                             {
  173.                                           flag=1;
  174.                                           fuhao=3;//代表乘号*
  175.                             }
  176.                             lcdwrd(0x30+dat1[num]);
  177.               }


  178.               P2=0x7f;                            //令第四行为0,判断哪一列按下
  179.               if(P2!=0x7f)
  180.               {
  181.                             Delay(5);
  182.                             if(P2!=0x7f)
  183.                             {
  184.                                           key=P2&0x0f;
  185.                                           switch(key)
  186.                                           {
  187.                                                         case 0x0e: num=12;break;  //0
  188.                                                         case 0x0d: num=13;break;  //清除rst
  189.                                                         case 0x0b: num=14;break;  //等号=
  190.                                                         case 0x07: num=15;break;  //除/
  191.                                           }            
  192.                             }
  193.                             while(P2!=0x7f);
  194.                             switch(num)
  195.                             {
  196.                                           case 12:
  197.                                                                       if(flag==0)              //没有按下符号键
  198.                                                                       {
  199.                                                                                     a=a*10+dat1[num];
  200.                                                                                     lcdwrd(0x30);            
  201.                                                                       }
  202.                                                                       else
  203.                                                                       {
  204.                                                                                     b=b*10+dat1[num];
  205.                                                                                     lcdwrd(0x30);
  206.                                                                       }
  207.                                                                       break;
  208.                                          
  209.                                           case 13:
  210.                                                                       lcdwrc(0x01);              //清屏指令                                         
  211.                                                                       a=0;
  212.                                                                       b=0;
  213.                                                                       flag=0;
  214.                                                                       fuhao=0;
  215.                                                                       break;

  216.                                           case 15:
  217.                                                                       flag=1;
  218.                                                                       fuhao=4;
  219.                                                                       lcdwrd(0x2f);//除号/
  220.                                                                       break;
  221.                                                                      
  222.                                           case 14:
  223.                                                                       if(fuhao==1)//加
  224.                                                                       {
  225.                                                                                     lcdwrc(0x4f+0x80);
  226.                                                                                     lcdwrc(0x04);//设置光标左移,屏幕不移动
  227.                                                                                     c=a+b;
  228.                                                                                     while(c!=0)              //一位一位显示
  229.                                                                                     {
  230.                                                                       lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
  231.                                                                                                   c=c/10;//取前面的结果数据            
  232.                                                                                     }
  233.                                                                                     lcdwrd(0x3d); //显示等于号=
  234.                                                                                     a=0;
  235.                                                                                     b=0;
  236.                                                                                     flag=0;
  237.                                                                                     fuhao=0;//全部清除为0
  238.                                                                       }
  239.                                                                       if(fuhao==2)   //减
  240.                                                                       {
  241.                                                                                     lcdwrc(0x4f+0x80);
  242.                                                                                     lcdwrc(0x04);//设置光标左移,屏幕不移动
  243.                                                                                     if(a>b)
  244.                                                                                                   c=a-b;
  245.                                                                                     else
  246.                                                                                                   c=b-a;
  247.                                                                                    
  248.                                                                                     while(c!=0)              //一位一位显示
  249.                                                                                     {
  250.                                                                       lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
  251.                                                                                                   c=c/10;//取前面的结果数据            
  252.                                                                                     }
  253.                                                                                     if(a<b)              lcdwrd(0x2d); //显示-号
  254.                                                                                     lcdwrd(0x3d); //显示等于号=
  255.                                                                                     a=0;
  256.                                                                                     b=0;
  257.                                                                                     flag=0;
  258.                                                                                     fuhao=0;//全部清除为0
  259.                                                                       }
  260.                                                                       if(fuhao==3)//乘法                           
  261.                                                                       {
  262.                                                                                     lcdwrc(0x4f+0x80);
  263.                                                                                     lcdwrc(0x04);//设置光标左移,屏幕不移动
  264.                                                                                     c=a*b;
  265.                                                                                     while(c!=0)              //一位一位显示
  266.                                                                                     {
  267.                                                                       lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
  268.                                                                                                   c=c/10;//取前面的结果数据            
  269.                                                                                     }
  270.                                                                                     lcdwrd(0x3d); //显示等于号=
  271.                                                                                     a=0;
  272.                                                                                     b=0;
  273.                                                                                     flag=0;
  274.                                                                                     fuhao=0;//全部清除为0            
  275.                                                                       }                           
  276.                                                       
  277.                                                                       if(fuhao==4)
  278.                                                                       {
  279.                                                                                     k=0;
  280.                                                                                     lcdwrc(0x4f+0x80);
  281.                                                                                     lcdwrc(0x04);//设置光标左移,屏幕不移动
  282.                                                                                     c=(long)(((float)a/b)*1000);//强制转换为long。
  283.                                                                                     while(c!=0)              //一位一位显示
  284.                                                                                     {
  285.                                                                                                   k++;
  286.                                                         lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
  287.                                                                                                   c=c/10;//取前面的结果数据
  288.                                                                                                   if(k==3)
  289.                                                                                                   {
  290.                                                                                                                 lcdwrd(0x2e);
  291.                                                                                                                 k=0;
  292.                                                                                                   }                           
  293.                                                                                     }
  294.                                                                       if(a/b<0)                //如果a比b小的话那么除的结果最高位是0
  295.                                                                                     {
  296.                                                                                                   lcdwrd(0x30);            
  297.                                                                                     }
  298.                                                                                     lcdwrd(0x3d); //显示等号
  299.                                                                                     a=0;
  300.                                                                                     b=0;
  301.                                                                                     flag=0;
  302.                                                                                     fuhao=0;//全部清除为0
  303.                                                                       }
  304.                                                                       break;

  305.                             }
  306.               }

  307. }

  308. void InterruptTimer0() interrupt 1                            //定时器中断0
  309. {
  310.     TH0=0xDC;              //装初值
  311.               TL0=0x00;
  312.               number++;
  313.               if(number==100)              //定时1s
  314.               {
  315.                             number=0;
  316.                             t++;
  317.                             if(t==10)              //定时10s
  318.                             {
  319.                                           t=0;
  320.                                           lcdwrc(0x01);              //清屏指令                                         
  321.                                                                       a=0;
  322.                                                                       b=0;
  323.                                                                       flag=0;
  324.                                                                       fuhao=0;            
  325.                             }
  326.               }
  327. }
  328.                            
  329.   void main()              //主函数
  330. {
  331.               TH0=0xDC;              //装初值
  332.               TL0=0x00;
  333.     TMOD=0x01;           //定时器0工作于16位,用于定时产生中断
  334.     EA=1;                                                        //允许总中断
  335.               ET0=1;                                                        //允许定时器0中断
  336.               TR0=1;                                                        //开定时器0            
  337.               lcdinit();  
  338.               while(1)
  339.               {
  340.                             keyscan();                           
  341.               }                     
  342. }
复制代码

完整的Word格式实验报告文档51黑下载地址:
单片机实验报告.docx (1.09 MB, 下载次数: 44)

评分

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

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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