找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10761|回复: 9
收起左侧

51单片机之4位数加法计算器的设计文档

  [复制链接]
ID:370491 发表于 2018-7-12 20:41 | 显示全部楼层 |阅读模式
名称 4位数加法计算器的设计

一、设计任务及要求:
设计任务:
    1、通过4*4矩阵键盘输入数字及运算符;
    2、可以进行4位十进制数以内的加法预算。如果计算结果超出四位数,则全部显示“E”;
    3、可以进行加减乘除所有运算;
    4、添加其他功能。

要 求:
首先进行预设计,根据设计的任务要求,先确定设计的硬件电路方案,然后进行硬件电路的初步设计,在计算机上画出硬件电路图,在老师的指导下进行修正硬件电路图,并对所涉及的参数进行计算。
在确定硬件的基础上,要进行软件的总体设计,包括软件主流程的设计以及各子程序的设计,同时,要写出详细的操作说明,如时间的调整方法,显示窗口的时间切换等,以配合软件的设计。
然后进入硬件的调试及编程工作,设计组内的同学可根据任务分工,有调试硬件各功能模块的,如键盘子程序、显示子程序等,有进行整体程序的编制的,各模块的编制过程中要注意资源的衔接。
最后进入联机调试,联机调试的原则也要采用分步走的原则,各个功能模块要逐步套入,通过一个再增加一项功能,从而达到设计的总体要求,不要上来编制个最大的程序,最后无法查找错误。
最后写出设计文档。

目    录
一、 绪 言1
二、系统设计1
2.1设计任务1
2.2方案比较与论证1
2.2.1系统整体流程图2
2.2.2单片机的选择方案论证2
2.2.3键盘选择方案论证2
2.2.4显示模块的选择方案论证2
2.2.5蜂鸣器的选择方案论证2
三、硬件电路设计2
3.1计算器的控制电路图2
3.2矩阵键盘的设计3
3.3 LCD1602显示电路的设计3
3.4蜂鸣器驱动电路的设计4
3.5主要元器件选择4
四、程序流程图5
五、c语言程序设计5
六、计算器的仿真19
6.1 Keil调试19
6.2 Proteus调试19
7、结束语20
参考文献21

、绪 言

    近年来随着科技的飞速发展,单片机的应用正在不断地走向深入,同时带动传统控制检测日新月异更新。在实时检测和自动控制的单片机应用系统中,单片机往往是作为一个核心部件来使用,仅单片机方面知识是不够的,还应根据具体硬件结构,以及针对具体应用对象特点的软件结合,加以完善。 电子时钟是现代社会中的主要计时工具之一,广泛应用于手机,电脑,汽车等社会生活需要的各个方面,及对时间有要求的场合。本设计采用AT89C52单片机作为主要核心部件,附以上电复位电路,时钟电路及按键调时电路组成。数字钟已成为人们日常生活中: 必不可少的必需品, 广泛用于个人家庭以及车站、 码头、剧场、办公室等公共场所,给人们的生活、学习、工作、娱乐带来极大的方便。 由于数字集成电路技术的发展和采用了先进的石英技术,使数字钟具有走时准确、性 能稳定、携带方便等优点,它还用于计时、自动报时及自动控制等各个领域。

、系统设计2.1 设计任务
    1、通过4*4矩阵键盘输入数字及运算符;
    2、可以进行4位十进制数以内的加法预算。如果计算结果超出四位数,则全部显示“E”;
    3、可以进行加减乘除所有运算;
    4、添加其他功能。
2.2 方案比较与论证

2.2.1 系统整体流程图

图1 系统整体流程图

2.2.2 计算器的控制方案论证

用4*4的矩阵键盘组成0-9数字键及加、减、乘、除、等于、清零按键,LCD屏幕实时显示输入的数字和运算符号,每按下一个按键都有蜂鸣器发出的响声。从矩阵键盘输入一个数字,选择运算符,再输入一个数字,然后按下“等于”键,最后的计算结果会呈现在LCD屏幕上。

2.2.3 单片机的选择方案论证

方案一:采用可编程逻辑期间CPLD              作为控制器。CPLD可以实现各种复杂的逻辑功能、规模大、密度高、体积小、稳定性高、I/O资源丰富、易于进行功能扩展。采用并行的输入输出方式,提高了系统的处理速度,适合作为大规模控制系统的控制核心。但本系统不需要复杂的逻辑功能,对数据的处理速度的要求也不是非常高,且从使用及经济的角度考虑我们放弃了此方案

方案二:采用Atmel公司的AT89C52单片机作为控制器。AT89C52是一个低功耗,高性能的51内核的CMOS 8位单片机,片内含8k空间的可反复擦些1000次的Flash只读存储器,具有256 bytes的随机存取数据存储器(RAM),32个双向I/O口,2个16位可编程定时计数器。

综合考虑,选择方案二,采用Atmel公司的AT89C52单片机作为控制器。

2.2.4 键盘选择方案论证

方案一:采用独立式键盘。由于各键相互独立,每个按键各接一根输入线,通过检测输入线的电平状态可以很容易的判断哪个按键被按下。此种键盘适用于按键较少或操作速度较高的场合。但本题发挥部分要求16个功能键,按键数目较多,这就需要较多的输入口线,而且电路结构复杂。故此方案不可取。

方案二:采用矩阵键盘。它由行和列组成,按键位于行列的交叉点上,行线信号和列线信号分别通过两个接口和CPU相连,通过行列扫描法判定按键的位置,此方案适用于按键较多的场合。

通过对4位数加法计算器项目的分析,采用4*4行列式键盘。

2.2.5 显示模块的选择方案论证

方案一:采用带字库LCD模块显示。能显示复杂的信息,具有质量轻,体积小,功耗低,指令功能强,接口简单,可靠性强等优点,显示内容丰富,图形美观,易于人机交流。但是价格昂贵。

方案二:采用LED数码管显示。数码管能显示数字和符号,但是占用I/O口资源较多,对于简单的电路可以选用此方案。

计算器,需要较为强大的人机交互界面,故选用方案一,显示所需信息。

2.2.6 蜂鸣器的选择方案论证

方案一:采用有源蜂鸣器。有源蜂鸣器内部带震荡源,只要一通电就会发出响声。

方案二:采用无源蜂鸣器。无源蜂鸣器内部不带震荡源,所以用直流信号无法令其鸣叫,必须用2K~5K的方波去驱动它。

综合考虑,为了程序控制的方便,选用了方案一。


硬件电路设计
3.1 计算器控制电路图

图2 计算器控制线路图

3.2 矩阵式键盘的设计

键盘电路如图3所示。设计数字键0~9 的键号依次为0~9,运算符号分别为“+”、“-”、“*”、“/”,以及“=”和清零“C”,通过逐行扫描函数来确定按下的键位。

图3 键盘电路

3.3 LCD1602显示电路的设计

LCD1602液晶屏采用LM016L型号元件,其电路如图3所示。

图4 LCD1602显示电路

3.4 蜂鸣器驱动电路的设计

蜂鸣器的驱动采用PNP三极管来驱动,低电平有效。其电路如图5 所示。

图5 蜂鸣器电路图

3.5 主要元器件选择

主要元器件选用型号和数量如表1所示:


序号

材料名称

规格型号

数量

元件代号

1

单片机

AT89C52

1

U1

2

晶振

12MHz

1

X1

3

三级管

MJE350

1

Q1

4

键盘

4*4

16



5

LCD1602

LM016L

1

LCD1602

6

蜂鸣器



1

BEEP

7

电阻

1k

1

R1


四、程序流程图
6.计算器仿真

在完成了计算器硬件设计和软件设计以后,便进入系统的调试阶段。系统的调试步骤和方法基本上是相同的,但具体细节和所采用的开发系统以及用户系统选用的单片机型号有关,如可选用Keil软件进行软件调试,用Proteus软件完成硬件调试。

6.1 Keil调试

6.2 Proteus调试

     

7 结束语

通过这次设计,使我们得到了一次用专业知识和专业技能去分析问题、解决问题全面系统的锻炼。使我们在单片机的基本原理、单片机应用系统开发过程,以及用C语言设计程序的思路技巧等方面都能向前迈了一大步,为我们日后成为合格的应用型人才打下良好的基础。


单片机源程序如下:


  1. #include <reg51.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. sbit lcden=P2^1;         //定义E口
  6. sbit lcdrs=P2^0;         //定义RS口
  7. sbit beep=P2^2;          //定义蜂鸣器
  8. uchar code table[]={'0','1','2','3','4','5','6',                 //创建键位数组,数字,运算符号,等于号,清零(小数点)
  9.                                                         '7','8','9','+','-','*','/','=','.'};                                                                     
  10. uchar key,flag1,js,k1,k2;
  11. uchar a[20],b[20];
  12. float jieguo=0;
  13. void delay(uchar z) //延迟函数
  14. {
  15.               uchar x,y;
  16.               for(x=z;x>0;x--)
  17.                             for(y=110;y>0;y--);
  18. }
  19. void write_cmd(uchar cmd) //写命令函数
  20. {
  21.               lcdrs=0;
  22.               P1=cmd;
  23.               delay(5);
  24.               lcden=1;
  25.               delay(4);
  26.               lcden=0;
  27. }
  28. void write_data(uchar date) //写数据函数
  29. {
  30.               lcdrs=1;
  31.               P1=date;
  32.               delay(5);
  33.               lcden=1;
  34.               delay(5);
  35.               lcden=0;
  36. }
  37. void init()              //LCD初始化函数
  38. {
  39.               lcden=0;
  40.               write_cmd(0x38); //设置16x2显示,8位数据接口
  41.               write_cmd(0x0c); //设置开显示,不显示光标(关显示是0x08)
  42.               write_cmd(0x06); //写一个字符后地址指针加1
  43.               write_cmd(0x01); //清屏
  44. }            
  45. void keyscan()
  46. {
  47.               uchar temp,uu=0xf7;
  48.               uint i;
  49.               for(i=0;i<4;i++)
  50.               {
  51.                             uu=_crol_(uu,1); //左移
  52.                             P3=uu;
  53.                             temp=P3;
  54.                             temp=temp&0x0f;
  55.                             if(temp!=0x0f)
  56.                             {
  57.                                           delay(10);
  58.                                           temp=P3;
  59.                                           temp=temp&0x0f;
  60.                                           if(temp!=0x0f)
  61.                                           {
  62.                                                         temp=P3;
  63.                                                         switch(temp)
  64.                                                         {
  65.                                                                       case 0xee:key=1;beep=0;delay(200);beep=1;break;                                            //延迟200响声
  66.                                                                       case 0xde:key=2;beep=0;delay(200);beep=1;break;
  67.                                                                       case 0xbe:key=3;beep=0;delay(200);beep=1;break;
  68.                                                                       case 0x7e:key=10;beep=0;delay(200);beep=1;break;
  69.                                                                       case 0xed:key=4;beep=0;delay(200);beep=1;break;
  70.                                                                       case 0xdd:key=5;beep=0;delay(200);beep=1;break;
  71.                                                                       case 0xbd:key=6;beep=0;delay(200);beep=1;break;
  72.                                                                       case 0x7d:key=11;beep=0;delay(200);beep=1;break;
  73.                                                                       case 0xeb:key=7;beep=0;delay(200);beep=1;break;
  74.                                                                       case 0xdb:key=8;beep=0;delay(200);beep=1;break;
  75.                                                                       case 0xbb:key=9;beep=0;delay(200);beep=1;break;
  76.                                                                       case 0x7b:key=12;beep=0;delay(200);beep=1;break;
  77.                                                                       case 0xe7:key=0;beep=0;delay(200);beep=1;break;
  78.                                                                       case 0xd7:key=15;beep=0;delay(200);beep=1;
  79.                             beep=0;delay(200);beep=1;beep=0;delay(200);beep=1;break;                            //清零长响声
  80.                                                                       case 0xb7:key=13;beep=0;delay(200);beep=1;break;
  81.                                                                       case 0x77:key=14;beep=0;delay(180);beep=1;delay(100);
  82.                              beep=0;delay(180);beep=1;break;                            //等于按键两声短响,中间较短间隔
  83.                                                         }
  84.                                                         while(temp!=0x0f)
  85.                                                         {
  86.                                                                       temp=P3;
  87.                                                                       temp=temp&0x0f;
  88.                                                         }
  89.                                                         flag1=1;
  90.                                           }
  91.                             }
  92.               }
  93. }
  94. void jscl() //计算显示函数
  95. {
  96.               uchar i,j,n;
  97.               float s,temp2;
  98.               long int s1,s2,a1,b1,c1,temp1;
  99.               a1=1;
  100.               b1=1;
  101.               s1=0;
  102.               s2=0;
  103.               s=0;
  104.               if(k2!=0)
  105.               {
  106.                             for(j=0;j<k1+1;j++)              //存放第一操作数
  107.                             {
  108.                                           for(i=0;i<k1-j;i++)
  109.                                                         a1=a1*10;
  110.                                           s1=s1+a[j]*a1;
  111.                                           a1=1;
  112.                             }
  113.                             for(j=k1+1;j<k2+1;j++) //存放第二操作数
  114.                             {
  115.                                           for(i=0;i<k2-j;i++)
  116.                                                         b1=b1*10;
  117.                                           s2=s2+a[j]*b1;
  118.                                           b1=1;
  119.                             }
  120.                             if(js==10)                //判断运算符号
  121.                             {
  122.                                           s=s1+s2;
  123.                             }
  124.                             if(js==11)
  125.                             {
  126.                                           s=s1-s2;
  127.                             }
  128.                             if(js==12)
  129.                             {
  130.                                           s=s1*s2;
  131.                             }
  132.                             if(js==13)
  133.                             {
  134.                                           s=(s1*0.1)/(s2*0.1);
  135.                             }
  136.                             jieguo=s;
  137.               }
  138.               else
  139.                             s=jieguo;
  140.               if(jieguo>9999||s>=9999)
  141.               {
  142.                             write_data('E');
  143.               }
  144.               else                                                                                                                   //运算结果小数的处理
  145.               {
  146.                             c1=(long int)(s*1000)%10;
  147.                             if(c1>=5)
  148.                                           s=s+0.01;
  149.                             temp1=(long int)(s);
  150.                             temp2=s-temp1;
  151.                             n=0;
  152.                             while(temp1)
  153.                             {
  154.                                           b[n]=temp1%10;
  155.                                           temp1=temp1/10;
  156.                                           n++;
  157.                             }
  158.                             b[n]=temp2*10;
  159.                             b[n+1]=(uchar)(temp2*100)%10;
  160.                             for(i=n;i>0;i--)
  161.                             {
  162.                                           write_data(table[b[i-1]]);
  163.                             }
  164.                             if(jieguo<1)
  165.                             {
  166.                                           write_data(table[0]);
  167.                                           write_data(table[15]);
  168.                                           write_data(table[b[n]]);
  169.                                 write_data(table[b[n+1]]);
  170.                             }
  171.                             else
  172.                             {
  173.                                           write_data(table[15]);
  174.                                           write_data(table[b[n]]);
  175.                                           write_data(table[b[n+1]]);
  176.                             }
  177.               }
  178. }
  179. void main()
  180. {
  181.               uchar i,j;
  182.               init();
  183.               write_cmd(0x80); //将液晶指针定位在第一行第一个单元
  184.               key=15;
  185.               i=0;
  186.               flag1=0;
  187.               while(1)
  188.               {
  189.                             keyscan();
  190.                             if(flag1==1)
  191.                             {
  192.                                           if(key==15)                              //判断为清零操作
  193.                                           {
  194.                                                         write_cmd(0x01);
  195.                                                         i=0;
  196.                                                         for(j=0;j<20;j++)
  197.                                                         {
  198.                                                                       a[j]=0;
  199.                                                                       b[j]=0;
  200.                                                         }
  201.                                                         k1=0;
  202.                                                         k2=0;
  203.                                           }
  204. ……………………

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

复制代码

本人初学,仅供参考,存在错误和不足之处,请大家回帖多多指教,不胜感激.切勿照搬,Word文档下载:

4位数加法计算器.doc (668.86 KB, 下载次数: 205)

回复

使用道具 举报

ID:647787 发表于 2019-11-23 16:27 来自手机 | 显示全部楼层
写命令函数cmd哪错了
回复

使用道具 举报

ID:637173 发表于 2019-12-5 09:24 来自手机 | 显示全部楼层
蜂鸣器为什么不响呀
回复

使用道具 举报

ID:674321 发表于 2019-12-26 12:59 | 显示全部楼层
大家可以多做参考
回复

使用道具 举报

ID:863744 发表于 2020-12-22 10:25 | 显示全部楼层
运行成功,蜂鸣器没响
回复

使用道具 举报

ID:991083 发表于 2021-12-12 13:03 来自手机 | 显示全部楼层
为什么我的代码运行没错,连线也找不出错误,但是就是仿真不出来
回复

使用道具 举报

ID:991511 发表于 2021-12-13 15:17 | 显示全部楼层
蜂鸣器是要单片机实物才能响吧
回复

使用道具 举报

ID:991511 发表于 2021-12-13 15:19 | 显示全部楼层
zwj圆 发表于 2021-12-12 13:03
为什么我的代码运行没错,连线也找不出错误,但是就是仿真不出来

生成了hex文件没
回复

使用道具 举报

ID:1051036 发表于 2022-11-8 16:19 | 显示全部楼层
应该是没生成hex文件
回复

使用道具 举报

ID:1081021 发表于 2023-5-31 15:32 来自手机 | 显示全部楼层
zwj圆 发表于 2021-12-12 13:03
为什么我的代码运行没错,连线也找不出错误,但是就是仿真不出来

我也仿真不出来,点按键没反应
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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