找回密码
 立即注册

QQ登录

只需一步,快速开始

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

整数计算器 单片机开发技能训练

[复制链接]
ID:935432 发表于 2021-7-5 00:08 | 显示全部楼层 |阅读模式
通过本次训练的实施,增进对单片机的感性认识,加深对单片机理论方面的理解,掌握单片机的内部功能模块的应用,如定时器/计数器、中断、片内外存贮器、I/O口、串行口通讯等,了解和掌握单片机应用系统的软硬件设计过程、方法及实现,为以后设计和实现单片机应用系统打下良好基础。通过设计练习,以此达到巩固、充实和综合运用所学知识解决实际问题的目的。

(1)绘制系统原理图;
(2)编制软件框图;
(3)完成详细完整的程序清单和注释;
(4)写出设计小结,对在完成以上文件过程中所进行的有关步骤、设计思想、指标论证、方案确定、元器件选择、原理分析等作出说明,并对所完成的设计作出评价,对自己整个设计工作中经验教训,总结收获和今后的研修方向。
1.3设计课题选题及任务要求
本次单片机开发设计课题选题为:整数计算器
课题要求:1、实现整数的加减乘除运算;
用LCD1602显示;
运算支持混合运算,考虑加减乘除的计算优先级;
使用Proteus软件仿真实现
如图1所示,选用单片机STC90C52RC作为本课题设计的核心元件,利用单片机灵活的编程设计和IO端口,及其控制的准确性。单片机的最小系统包括电源、时钟电路、复位电路,搭建最小系统是实现单片操作的最基本的硬件电路要求。时钟信号通常用两种电路形式电路得到:内部震荡方式和外部中断方式。在引脚XTAL1和XTAL2外部接晶振电路器(简称晶振)或陶瓷晶振器,就构成了内部晶振方式。由于单片机内部有一个高增益反相放大器,当外接晶振后,就构成了自激振荡器并产生振荡时钟脉冲。内部振荡方式的外部电路的起振电容值一般在5~30pf, 晶振频率的典型值为12MHz,采用6MHz的情况也比较多。由于程序上需要使用串口工作在11920的波特率,为了更好地匹配该波特率,晶振采用11.0592MHz的晶振而不是常用的12MHz晶振。内部振荡方式所得的时钟信号比较稳定实用。显示部分则用用PO口接上拉电阻再接LCD液晶显示器,用P2.0接使能端EN,P2. 1接读写信号RW, P2.2接寄存器选择端口RS,再接.上一个滑动变阻器来调节LCD。按键部分实际上就是把每个按键所对应的值经过处理后发给单片机,再在单片机内把数字当作指针指向所对应的数字或运算符。

2.2 具体功能模块电路设计

1)LCD1602液晶显示电路

图2 LCD液晶显示电路

如图2所示,为了便于计算器的计算过程以及结果的显示,方案采用了LCD1602的液晶来显示。使用液晶比数码管的优势很多,占用较少的I0口、更低的功耗、更简单的控制过程、更强大的显示能力。由于液晶显示器每一一个点在收到信号后就一直保持那种色彩和亮度,恒定发光,而不像阴极射线管显示器(CRT)那样需要不断刷新新亮点。因此,液晶显示器画质高且不会闪烁,通过显示屏上的电极控制液晶分子状态来达到显示的目的,在重量上比相同显示面积的传统显示器要轻得多,相对而言,液晶显示器的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器也要要少得多。原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示,这样即可以显示出图形。

2)矩阵键盘输入

图3 矩阵键盘

键盘是单片机系统中最常用的人机对话输入设备,用户通过键盘向单片机输入数据或指令。键盘控制程序需完成的任务有:监测是否有键按下,有键按下时,在无硬件去抖的动电路时,应用软件延时方法消除按键抖动影响;当有多个键同时按下时,只处理一一个按键,不管一次按键持续多长时间,仅执行一次按键功能程序。

矩阵按键扫描程序是一种节省I0口的方法,按键数目越多节省I0口就越可观,思路:先判断某一列(行)是否有按键按下,再判断该行(列)是那-一只键按下。但是,在程序的写法上,采用了最简单的方法,使得程序效率最高。本程序中,如果检测到某键按下了,就不再检测其它的按键,这完全能满足绝大多数需要,又能节省大量的CPU时间。

本键盘扫描程序的优点在于:不用专门的按键延时程序,提高了CPU 效率,也不用中断来扫描键盘,节省了硬件资源。另外,本键盘扫描程序,每次扫描占用CPU时最短,不论有键按下或者无键按下都可以在很短的时间完成一次扫描。

6)最小单片机系统

图4 最小单片机系统

STC89C52单片机性能稳定,拥有1.4KBytc程序存储器,内置两个16位定时计数器,利用单片机周期工作,方便控制且可靠性高,无需再扩展外部存储器,并且可将4个并行口全部作为输入/输出接口使用。CPU模块主要依靠 AT89C52单片机强大的I/O口读写功能通过地址线和数据线实现对其他各模块工作的管理。包含了全双工串行接口,方便与电脑或其它终端通信。STC89C52有40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外中断口,3个16位可编程定时计数器,2个全双工串行通信口,2 个读写口线,AT89C52可以按照常规方法进行编程,也可以在线编程。其将通用的微处理器和Flash存储器结合在一起,特别是可反复擦写的 Flash存储器可有效地降低开发成本。

3. 程序设计
3.1 程序结构
图5 程序结构框图
程序过程为:开始时,LCD初始化,LCD右边显示“0.”,接下来向液晶屏输入命令子函数以及数据子函数,通过在液晶屏上显示数组元素和字符串子函数,把数据显示出来,然后判断数据是否显示完,若显示完则返回,若没有则继续传送命令和数据。该系统程序主要由输入模块、运算模块和显示模块组成。编程是分模块来调试,这样方便调试方面修改,最后把各个模块集合起来联调。这也是编程调试中最重要的一个环节也是最耗时的。

3.2具体功能程序设计
1)主程序

图6 主程序结构框图

系统主程序主要处理各模块程序,开始时先执行初始化,将显示模块和按键模块初始化。接着当按键按下去时进行判断如果有按键按下则一方面输出按下的数字一方面将信息传递给数字、字符处理模块,接着由处理模块输出给显示器。

  • 运算模块
7 运算子程序结构框图
运算模块是根据你输入的运算符来运算你输入数据的结果。此系统有三个运算符(平方、开方和阶乘)只要就按下运算符就直接得到运算结果,剩下的运算都是等“=”按下之后才显示出结果。其中开方和X的n次方是调用了集成环境的math函数。此系统的运算只在整数的基础上运算。流程图如上。
4.系统运行或调试
4.1功能电路调试
1)加法的运算调式

图8 加法运算示例

当正常开机后直接按键依次输入“15+6=”之后即可显示“=21”的字样。如果输入错误需要重新输入的话按键盘上对应的“C”键即可清除。

  • 乘法的运算调试
图9 乘法运算示例

和加法的运算过程相同,当正常开机后直接按键依次输入“56*8=”之后即可显示“=448”的字样。如果输入错误需要重新输入的话按键盘上对应的“C”键即可清除。


4.2系统综合调试

图10 实物图
由于只支持整数的运算,当在进行除法时运算结果为小数时会报错显示“ERROR”的字样。这是一个不足之处,此后需要再代码中完善此功能。当给此单片机输入hex工程文件后单片机内的ROM会将程序保存下来。也就是说第一次运行成功之后每次需要用时只需接通电源即可自动运行。
                              总结
通过这次单片机设计实训,让我更加深刻掌握了51单片机的原理和做实物PCB板的过程,同时也让我学习了做一个完整的项目所需要的知识与技能。本次实训我选择的是计算器项目。刚拿到这项目时我还没有太多的想法,后来查阅了一下相关资料,就慢慢地有自己的思路和想法。后来就开始着手于这次的设计。为了提高效率和成功率了,先通过软件来仿真调试电路及软件。在软件.上就比较容易完成电路的连接和调试,编写的程序也可以在仿真电路上调试,方便快捷。有了调好的仿真图及程序,再做PCB板来,根据实物再调试。这样会有事半功倍的效果。此项目的程序让我最费时的是变化的显示位数,即根据你输入数的位数或运算出来的结果判定其数的位数来动态扫描显示。经过反复的调试,最后发现问题出在两行程序的位置处,只更换这两行的位置就有不一样的效果。所以,有些时候不单看程序的逻辑、指令等,也要换一下思维,从别的方面考虑考虑,要各方面都要想好,要严谨行事。调好了软件就开始做硬件了,由于之前有过做硬件的检验,所以做起硬件来就很娴熟。最后就是实物的调试了。有个很现实的问题,就是软件仿真的板子不能完成仿真出实物的情况。所以最后面还是要结合实物来调一下程序。
这次实训我真的学到了很多知识,也更清楚地知道实践要有扎实的理论基础,这样才能引导实践,更快地完成项目。
附录A完整电路图
图11 完整电路图
完整程序
  1. #include <reg51.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <math.h>
  6. #define uint unsigned int
  7. #define uchar unsigned char
  8. sbit pinRS=P2^6;
  9. sbit pinRW=P2^5;
  10. sbit pinE=P2^7;
  11. #define pindata P0
  12. #define clearscreen() writeinstruc(0x01)
  13. #define cursorreturn() writeinstruc(0x02)
  14. #define inputmode(temp) writeinstruc(temp)
  15. #define dispcontrol(temp) writeinstruc(temp)
  16. #define dispshift(temp) writeinstruc(temp)
  17. #define functionset(temp) writeinstruc(temp)
  18. #define setCGRAM_Add(address) writeinstruc(0x40|address)
  19. #define setDDRAM_Add(address) writeinstruc(0x80|address)
  20. #define uchar unsigned char
  21. uchar k=0,result1;
  22. void shortdelay(uchar i)
  23. {
  24. for(;i>0;i--);
  25. }
  26. void longdelay(uint i)
  27. {
  28. uint j;
  29. for(;i>0;i--)
  30. {for(j=100;j>0;j--);}
  31. }
  32. void delay(int i)
  33. {int j;
  34. for(;i>0;i--)
  35.    for(j=0;j<100;j++);
  36. }
  37. void io_init()
  38. {P1=0xff;
  39. }
  40. unsigned char key_scan()
  41. { unsigned char key;
  42.   unsigned char temp;
  43.   uint flag;
  44.   io_init();
  45.    P1=0xf0;
  46.    flag=0;
  47. loop: temp=P1^0xf0;
  48.    while(temp)
  49.     {
  50.      P1=0xfe;
  51.      delay(1);
  52.      if((P1&0xfe)!=0xfe)
  53.      switch(P1)
  54.      {
  55.      case 0xee: key=0x11;flag=1;break;
  56.      case 0xde: key=0x12;flag=1;break;
  57.      case 0xbe: key=0x13;flag=1;break;
  58.      case 0x7e: key=0x14;flag=1;break;
  59.      }
  60.   if(flag)
  61.   goto exit;
  62.   else
  63.      P1=0xfd;
  64.      delay(1);
  65.      if((P1&0xfd)!=0xfd)
  66.      switch(P1)
  67.      {
  68.      case 0xed: key=0x21;flag=1;break;
  69.      case 0xdd: key=0x22;flag=1;break;
  70.      case 0xbd: key=0x23;flag=1;break;
  71.      case 0x7d: key=0x24;flag=1;break;
  72.      }
  73.      if(flag)
  74.   goto exit;
  75.   else
  76.      P1=0xfb;
  77.      delay(1);
  78.      if((P1&0xfb)!=0xfb)
  79.      switch(P1)
  80.      {
  81.      case 0xeb: key=0x31;flag=1;break;
  82.      case 0xdb: key=0x32;flag=1;break;
  83.      case 0xbb: key=0x33;flag=1;break;
  84.      case 0x7b: key=0x34;flag=1;break;
  85.      }
  86.      if(flag)
  87.   goto exit;
  88.   else
  89.   P1=0xf7;
  90.      delay(1);
  91.      if((P1&0xf7)!=0xf7)
  92.      switch(P1)
  93.      {
  94.      case 0xe7: key=0x41;flag=1;break;
  95.      case 0xd7: key=0x42;flag=1;break;
  96.      case 0xb7: key=0x43;flag=1;break;
  97.      case 0x77: key=0x44;flag=1;break;
  98.      }

  99. exit: return key;
  100.    }
  101.   if(temp==0)
  102.   goto loop;
  103.   }
  104. void initpindata(bit i)
  105. {
  106. if(i==1) pindata=0xff;
  107. else pindata=0X00;
  108. }
  109. void setRS(bit i)
  110. {
  111. ..........限于篇幅见word文档..................
复制代码

以上的Word格式文档51黑下载地址:
单片机开发技能训练51hei.doc (867.38 KB, 下载次数: 11)

评分

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

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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