找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51单片机的多功能计算器全套设计资料下载(PCB+源码+仿真+论文)

  [复制链接]
跳转到指定楼层
楼主
lcd1602 51单片机计算器 5*4键盘扫描,下面是制作出来的实物图:

图3.2 浮点数运算





全部资料51hei下载地址:
计算器 5乘4.zip (5.75 MB, 下载次数: 622)




单片机课程设计
设计课题     基于51单片机的多功能计算器设计
【摘要】 当今社会,随着人们物质生活的不断提高,电子产品已经走进了家家户户,无论是生活或学习,还是娱乐和消遣几乎样样都离不开电子产品,大型复杂的计算能力是人脑所不能胜任的,而且人脑比较容易出错。计算器作为一种快速通用的计算工具方便了用户的使用。计算器可谓是我们最亲密的电子伙伴之一。本设计着重在于分析计算器设计开发过程中的环节和步骤,并从实践经验出发对计算器设计做了详细的分析和研究。
本设计是以STC89C52单片机为核心的计算器模拟系统设计,输入采用5×8矩阵键盘,可以进行加、减、乘、除等十几种数字运算,同时支持括号的嵌套使用级浮点数的运算,并在LCD1602上显示操作过程。
本次设计注重设计方法及流程,首先根据原理设计电路,利用keil编程,借助实验开发平台进行仿真实验,进而利用altium designer 制作PCB,最后到焊接元器件,直至调试成功。在设计的同时,特别注重keil软件和altium designer软件的使用方法和技巧以及常用的LCD显示器和矩阵键盘的设计和使用方法。

目录
1  系统方案设计
1.1 设计目的及要求
1.1.1 设计目的
1.1.2 设计要求
1.2 方案论证及选择
1.2.1 方案一 采用FPGA控制
1.2.2 方案二 采用STC89C52
1.2.3 方案比较及选择
2  单元电路设计
2.1  工作原理
2.2  硬件电路设计
2.2.1  单片机电路设计
2.2.2  键盘模块电路
2.2.3  蜂鸣器提示电路
2.2.4  液晶显示电路
2.3 软件设计
2.3.1 键盘扫描
2.3.2 表达式的处理
2.4  altium designer 原理图设计及PCB制作
2.4.1  原理图设计
2.4.2              PCB制作
2.4.3              设计结果
3系统测试
3.1 整数运算
3.2 浮点数运算
3.3 输入出错的情况
4  结论与心得体会
5  参考文献
附录1  元器件清单
附录2  程序清单

1  系统方案设计
1.1 设计目的及要求
1.1.1 设计目的

通过本次课题设计,应用《单片机应用基础》、《数据结构》等所学相关知识及查阅资料,完成实用计算器的设计,以达到理论与实践更好的结合、进一步提高综合运用所学知识和设计的能力的目的。

通过本次设计的训练,可以使我在基本思路和基本方法上对基于MCS-51单片机的嵌入式系统设计有一个比较感性的认识,并具备一定程度的设计能力。

1.1.2 设计要求

在本次课程设计中,主要完成如下方面的设计要求:

1、掌握MCS-51系列某种产品(例如8051)的最小电路及外围扩展电路的设计方法;

2、计算器能实现加、减、乘、除、平方、开方、N次方、开N次方、正弦函数、                                  余弦函数、正切函数、反正弦、反余弦、反正切、对数运算、阶乘(N<=34)、排列、                 组合、累加等十九种功能。

3、支持浮点数运算;

4、较为友好的界面显示,对输入实时显示,对计算结果输出显示;

5、能够具备比较完善的报错系统

1.2 方案论证及选择

基于设计要求,笨设计考虑了两种设计方案,他们均可以实现计算器的功能,但基于设计目的及微控制器的广泛运用,比较两种方案的优劣,最终选择基于51单片机的计算器设计。

1.2.1 方案一 采用FPGA控制
FPGA是一种高密度的可编程逻辑器件,自从Xilinx公司1985年推出第一片FPGA以来,FPGA的集成密度和性能提高很快,其集成密度最高达500万门/片以上,系统性能可达200MHz。由于FPGA器件集成度高,方便易用,开发和上市周期短,在数字设计和电子生产中得到迅速普及和应用,并一度在高密度的可编程逻辑器件领域中独占鳌头。
但是而基于 SRAM编程的FPGA,其编程信息需存放在外部存储器上 ,需外部存储器芯片 ,且使用方法复杂 ,保密性差,而其对于一个简单的计算器而言,实用FPGA有点大材小用,成本太高。

1.2.2 方案二 采用STC89C52
单片机是单片微型机的简称,故又称为微控制器MCU(Micro Control Unit)。通常由单块集成电路芯片组成,内部包含有计算机的基本功能部件:中央处理器CPU,存储器和I/O接口电路等。因此,单片机只要和适当的软件及外部设备相结合,便可成为一个单片机控制系统。单片机广泛用于智能产品,智能仪表,测控技术,智能接口等,具有操作简单,实用方便,价格便宜等优点,而其中AT89S52以MCS-51为内核,是单片机中最典型的代表,应用于各种控制领域。
1.2.3 方案比较及选择
通过以上两种方案论证和比较,从设计的实用性,方便性和成本出发,选择了以STC89C52单片机作为中央处理单元进行计算器的设计,这样设计能够实现对六位浮点数的加减和三位浮点数的乘除运算。


2  单元电路设计

2.1  工作原理

利用矩阵键盘进行按键的输入,通过对矩阵键盘的扫描,获取用户的输入,并实时的显示在1602液晶上,每次获取到输入时,根据软件设计的相应方法对输入进行处理、运算,输入结束后(以“=“为标志),将最终的运算结果输出的液晶上。

系统组成及整体框图如图2.1所示。

图2.1 系统组成及总体框图(见附件)


2.2  硬件电路设计
2.2.1  单片机电路设计

为使单片机正常工作,除电源供电部分外,还需提供晶振电路和复位电路。具体电路如下:

图2.2 单片机工作电路

由图2.2可知,9脚外接的是按键复位电路,18,19脚外接的是晶振电路,这样,就构成了单片机正常工作的必备电路。同时,为使P0口正常工作,并增加其带负载能力,P0口需接了上拉电阻。图中EA为外部访问允许,欲使CPU仅访问外部程序存储器(地址为0000H-FFFFH),EA端必须保持低电平(接地)。在这里,STC89C52单片机8k的程序存储器已经够本设计使用,无需外部程序储存器,故EA直接接高电平。


2.2.2  键盘模块电路

图2.3是键盘电路,共20个按键,用来实现人机交互和运算表达式的输入,S0~S3、S5~S8、S10~S13、S15~S18共16个按键组成一组4*4的矩阵键盘,行线第一行到第四行分别接在P3.0~P3.3口,列线第一列到第四列分别接在P3.4~P3.7口,这样P3口就完成了对4*4的矩阵键盘的接线。同时,注意到按键数量还达不到要求,故增加了四个独立按键S4,S9,S14,S19。他们依次接在P20~P23口。可见,矩阵键盘相对来讲更节省I/O口,但本着学习的目的,加之本设计并不需要太多的I/O口,故为充分学习和利用资源,在这里也设计了4个这样的独立按键。

图2.3  键盘模块电路

2.2.3  蜂鸣器提示电路

蜂鸣器主要用于按键时发出声音,提示当前的按键操作,电路如图2.5所示,三极管主要用于驱动蜂鸣器,因为单片机I/O的驱动能力有限。同时单片机I/O口还在这里还起到开关作用,为‘0’时打开蜂鸣器通道,使蜂鸣器发声。

图2.4  蜂鸣器提示电路

2.2.4  液晶显示电路

LCD也是本次设计的重要组成部分之一,主要用于显示输入和输出。电路如图2.5所示,LCD数据端与单片机P0口相连,控制端与P24~P26连接,电位器用于调节对比度。


图2.5  LCD显示电路


至此,整个电容测量仪的硬件设计部分就基本设计完成,接下来,需要的就是与之相匹配的软件支持了。


2.3 软件设计

软件编程平台选择最常用的keil软件。由于该程序并未涉及到底层的驱动问题,因此选择方便快捷的C语言编程。在编程中,将该程序分为四个模块:延时模块、1602显示模块、用于处理计算表达式的对战模块及主函数模块。采用模块化设计,方便调试与理解。具体程序见附录二。在这里重点介绍软件核心的表达式处理程序算法。

2.3.1 键盘扫描

独立键盘很好实现,只需不停的检测即可,出现低电平即出现按键,在经过一定的延时消抖,再确认判断即可。

矩阵键盘扫描程序,首先读出P3的低四位,然后读出P3口的高四位。然后确定键值并显示缓存,最终将按键的值通过一个预先定义好的数组转换为相应的ASCII码值送给LCD显示和与表达式相应的堆栈进行处理,读键程序使用的是反转法读键,不管键盘矩阵的规模大小,均进行两次读键。第一次所有行线均输出高电平,从P3口的值读入键盘信息(行信息);第二次所有列线均输出高电平,从P3口的值读入键盘信息(列信息)。

2.3.2 表达式的处理

表达式包含加、减、乘、除、括号等,必须按照相应的优先级运算,才可能得出正确的结果。在这儿采用栈结构,可以有效的进行表达式的处理。

栈结构具有“后进先出”的固有属性,借助这个属性我们可以随时对刚输入的元素进行操作,从而实现边输入边计算。

为了实现算符优先算法。可以使用两个工作栈。一个称为OPTR,用以寄存运算符,另一个称做OPND,用以寄存操作数或运算结果。

1.首先置操作数栈为空栈,表达式起始符”#”为运算符栈的栈底元素;

2.依次读入表达式,若是操作符即进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权后作相应的操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为”#”)。

在这里,相应的处理指的是,如果当前符号的优先级比栈顶优先级低,则将该符号继续压入堆栈,不做其它操作;如果当前符号的优先级比栈顶优先级高,则依次取出操作数栈的栈顶两个数据和符号栈的栈顶符号进行这两个数的运算,运算结果数据再压入操作数栈中。若优先级相等,则弹出符号栈栈顶符号。算符间的优先关系如下(‘#‘表示开始和结束):


+

-

*

/

(

)

#

+

>

<

<

<

<

>

>

-

>

>

<

<

<

>

>

*

>

>

>

>

<

>

>

/

>

>

>

>

<

>

>

(

<

<

<

<

<

=


)

>

>

>

>


>

>

#

<

<

<

<

<


=

表2.1 运算符优先级表


2.4  altium designer 原理图设计及PCB制作
2.4.1  原理图设计

图2.6 原理图设计(1)——单片机部分

图2.7 原理图设计(2)——键盘、蜂鸣器部分

2.4.2          PCB制作

图2.8 PCB设计(1)——单片机部分

图2.9 原理图设计(2)——键盘、蜂鸣器部分

注:在此并没有布双层板,红色的线仅仅只是为了标志出跳线或者本质上实物已经连接上了。


2.4.3          设计结果

图2.10   设计结果实物图


如图所示,各个按键功能如图中文字说明,电源为5V直流电源。


3系统测试

测试主要测试其运算是否正确,及检错能力。

3.1 整数运算

在此以整数运算为例,介绍计算器的使用方法即流程。首先打开电源,看到LCD打开显示,说明运行正常,接着,输入表达式:12*(56+23)*2,其结果本身应为1896。

输入结束后,点“=”按键,即可在第二行显示出运算结果,由图可见运算完全正确。在使用时,可以通过声音开关按钮控制按键音的打开和关闭,在LCD上也有显示,如果再第二行第一个位置没有显示,则没有打开声音,可以通过按钮打开。若有显示,则声音已经打开,可以通过按钮关闭声音。如图3.1所示,此时已经打开声音。

图3.1  整数运算




3.2 浮点数运算

由图可以看出,可以进行浮点数运算,还可以从第二行第一个字符,蜂鸣器处于关闭状态。


3.3 输入出错的情况

输入一个错误的表达式,如图3.3所示。

图3.3 输入错误的情况下


再按“=”号,将会出现出错画面。如图3.4所示。

图3.4 输入错误的显示


由以上测试可知,整个设计运行正常,能够正确的进行运算和出错提示。由此可得,整个设计是成功的。




4  结论与心得体会

总之,通过一系列仿真和设计,基于单片机的计算器设计还是比较成功的做出来了。一路下来还是比较坎坷,从原理到实物,从调试到调试成功,遇到了很多问题,特别是在软件编程时,开始以为既然单片机具有数据处理与运算的能力,那么用它来做一个计算器应该很简单了,可是,后面实际操作才知道,当计算表达式时,优先级问题非常重要,一开始用了很多if语句来实现,程序繁琐复杂,且效果不是很好,很容易出错,最后通过查阅相关资料,了解到利用数据结构中栈的思想来解决这一问题就很方便。但在实际写程序时也遇到了很多问题,但最终还是克服难关,将整个软件比较完善的实现了。

在硬件的原理图及PCB设计中,也遇到了很多问题,先做模块后做主板,导致我后面的布线就很麻烦,这也教会了我一些经验,在PCB分模块设计中,模块与模块之间的连接也是必须考虑到的,从左端连接还是从右端连接,都直接影响到整个PCB板的设计。

总之,通过这次设计也收获了很多,知识层面上,学得了很多新知识,解决问题的新方法,思考问题的新方向。实践方面,提高了动手能力,提高了解决实际问题的能力等等。在思想上,更加明白的坚持不懈的重要性,学习探索的重要性,实践动手的重要性。


5  参考文献

【1】  《单片机基础》第三版 李广弟 朱月秀 冷祖祁 编著 北京航天大学出版社,2007

【2】 《数据结构》严蔚敏 编著  清华大学出版社


附录1  元器件清单

(1)晶振12M一个

(2)stc89c52芯片一片

(3)30pf 2个;10uf 1个;

(4)40脚活动底座一个

(5)LCD液晶一个

(6)按键21个

(7)发光二极管1个

(8)9引脚排阻 1个

(9)680Ω 1个;10k 2个;1k  1个;10k滑动变阻器 1个; 10Ω 1个;

(10) 开关1个

(11) 5V有源蜂鸣器1个

(12) 三极管S8550一个

(13)排针若干,杜邦线若干


单片机源程序如下:


  1. #include <REGX51.H>
  2. #include<intrins.h>
  3. #include<stdio.h>
  4. #include<string.h>
  5. #include<math.h>
  6. sbit RS = P2^5;
  7. sbit RW = P2^6;
  8. sbit E  = P2^7;

  9. #define Data  P0//数据端口
  10. //全局变量
  11. float num1;//第一操作数num1     (初始为零)
  12. float num2;//第二操作数num2     (初始为零)
  13. char yun_flag='+';//运算符号 yun_flag    (默认为+ )
  14. char key_last;//上次按键状态标志 key_last
  15. char sqrt_flag;//开方键按下标志   sqrt_flag
  16. unsigned long pos_flag=1;//小数位权pos_flag      (默认为1)
  17. char neg_flag;//正负标志 neg_flag
  18. char data c_num1[15]=" ";//c_num1 字符型第一操作数 (数组不定义大小与其他变量冲突)
  19. char data c_num2[15]=" ";//c_num2 字符型第二操作数
  20. char error;//运算法则错误;
  21. char len;//小数点后位数
  22. /*                    微秒延时函数                                */
  23. /******************************************************************/
  24. void DelayUs(unsigned char us)//delay us
  25. {
  26. unsigned char uscnt;
  27. uscnt=us>>1;        /*12MHz频率*/
  28. while(--uscnt);
  29. }
  30. /******************************************************************/
  31. /*                    毫秒函数声明                                */
  32. /******************************************************************/
  33. void DelayMs(unsigned char ms)
  34. {
  35. while(--ms)
  36.    {
  37.      DelayUs(250);
  38.      DelayUs(250);
  39.          DelayUs(250);
  40.          DelayUs(250);
  41.    }
  42. }
  43. /******************************************************************/
  44. /*                   写入命令函数                                 */
  45. /******************************************************************/
  46. void WriteCommand(unsigned char c)
  47. {
  48. DelayMs(5);//操作前短暂延时,保证信号稳定
  49. E=0;
  50. RS=0;
  51. RW=0;
  52. _nop_();
  53. E=1;
  54. Data=c;
  55. E=0;
  56. }
  57. /******************************************************************/
  58. /*                   写入数据函数                                 */
  59. /******************************************************************/
  60. void WriteData(unsigned char c)
  61. {
  62. DelayMs(5);  //操作前短暂延时,保证信号稳定
  63. E=0;
  64. RS=1;
  65. RW=0;
  66. _nop_();
  67. E=1;
  68. Data=c;
  69. E=0;
  70. RS=0;
  71. }
  72. /******************************************************************/
  73. /*                   写入字节函数                                 */
  74. /******************************************************************/
  75. void ShowChar(unsigned char pos,unsigned char c)
  76. {
  77. unsigned char p;
  78. if (pos>=0x10)
  79.     p=pos+0xb0; //是第二行则命令代码高4位为0xc
  80. else
  81.     p=pos+0x80; //是第二行则命令代码高4位为0x8
  82. WriteCommand (p);//写命令
  83. WriteData (c);   //写数据
  84. }
  85. /******************************************************************/
  86. /*                   写入字符串函数                               */
  87. /******************************************************************/
  88. void ShowString (unsigned char line,char *ptr)
  89. {
  90. unsigned char l,i;
  91. l=line<<4;
  92. for (i=0;*(ptr+i)!='\0';i++)
  93.   ShowChar (l++,*(ptr+i));//循环显示16个字符
  94. }
  95. /******************************************************************/
  96. /*                   初始化函数                                   */
  97. /******************************************************************/
  98. void InitLcd()
  99. {
  100. DelayMs(15);
  101. WriteCommand(0x38); //display mode
  102. WriteCommand(0x38); //display mode
  103. WriteCommand(0x38); //display mode
  104. WriteCommand(0x06); //显示光标移动位置
  105. WriteCommand(0x0c); //显示开及光标设置
  106. WriteCommand(0x01); //显示清屏

  107. }
  108. /*************按键扫描****************************/
  109. char scan()
  110. {

  111.   char h_data,l_data,i,key_num;
  112.   P2=P2&0XE0;//P2低5位送0
  113.   P1=P1|0X0F;//P1低4位送1
  114.   while((P1|0xf0)==0xff)//判断P1低4位是否全为1
  115.   {
  116.    while((P1|0xf0)==0xff);
  117.    DelayMs(10);//延时10ms
  118.   }
  119.    l_data=~(P1|0xf0);//记入列标志
  120.    P2=P2|0X1F;//P2低五位送1
  121.    P1=P1&0XF0;//P1低四位送0
  122.    h_data=~(P2|0xe0);//记入行标志
  123.    for(i=0;i<=4;i++)//计算行号(0~4)
  124.             {
  125.            if(h_data==1)break;
  126.            h_data=h_data>>1;
  127.          }
  128. h_data=i;//行号
  129.   for(i=1;i<=4;i++)//计算列号(1~4)
  130.          {
  131.           if(l_data==1)break;
  132.           l_data=l_data>>1;
  133.         }
  134. l_data=i;//列号
  135.    key_num=h_data*4+l_data;        

  136.   P2=P2&0XE0;//P2低5位送0
  137.   P1=P1|0X0F;//P1低4位送1
  138.   while((P1|0xf0)!=0xff)//判断P1低4位是否全为1
  139.   {
  140.    while((P1|0xf0)!=0xff);
  141.    DelayMs(10);//延时10ms
  142.   }
  143.   return key_num;
  144. }
  145. void float_to_char(float a,char* p)
  146. {
  147.   char i,flag,length;
  148.   flag=0;
  149.   sprintf(p,"%f",a);
  150.   length=strlen (p);
  151.   for(i=0;i<length;i++)
  152.   {
  153.     if(*(p+i)=='.')flag=1;
  154.   }
  155.   if(flag==1)
  156.   for(i=length-1;i>=0;i--)
  157.   {
  158.     if(*(p+i)=='.'){*(p+i)='\0';break;}
  159.     if(*(p+i)!='0'){*(p+i+1)='\0';break;}
  160.   }
  161. }
  162. /**********************更新液晶*************************/
  163. void refresh()//更新液晶
  164. {
  165.   char length,i,j;
  166.   char dot;
  167.   dot=0;
  168.          
  169.   float_to_char(num2,c_num2);//num2转为字符型
  170.   length=strlen(c_num2);
  171.   for(i=0,j=0;i<length;i++)        
  172.   {
  173.     if(c_num2[i]=='.')
  174.         dot=1;
  175.         if(dot==1)
  176.     j++;
  177.   }
  178.   if(j<len)
  179.   {
  180.           if(dot==1)
  181.           {        
  182.             for(i=length;i<(length+len-j);i++)
  183.                  {
  184.                    c_num2[i]='0';
  185.         
  186.                  }
  187.                  c_num2[i]='\0';
  188.           }
  189.           else
  190.                 {
  191.                   
  192.                   c_num2[length]='.';
  193.                   if(len-j>1)
  194.                   {
  195.                     for(i=length+1;i<(length+len-j);i++)
  196.                          c_num2[i]='0';
  197.                   }
  198.                   c_num2[length+len-j]='\0';
  199.                 }  
  200.   }

  201.   if(neg_flag==1)//'+/-'按下首位加‘-’
  202.    {
  203.       length=strlen(c_num2);//计算c_num2长度         
  204.                     for(i=length-1;i>=0;i--)
  205.                   {
  206.                           c_num2[i+1]=c_num2[i];
  207.                   }
  208.                   c_num2[length+1]='\0';
  209.                   c_num2[0]='-';
  210.    }
  211.    
  212.    if(sqrt_flag==1)
  213.            {
  214.       length=strlen(c_num2);//计算c_num2长度
  215.              for(i=length-1;i>=0;i--)
  216.           {
  217.                   c_num2[i+1]=c_num2[i];
  218.           }
  219.           c_num2[length+1]='\0';
  220.           c_num2[0]=0xe8;//字符根号
  221.    }
  222.    
  223.    
  224.    if(error==0)
  225.    {
  226.            float_to_char(num1,c_num1);//num1转为字符型
  227.            WriteCommand(0x01); //显示清屏
  228.            ShowString(0,c_num1);
  229.            ShowString(1,c_num2);  
  230.            ShowChar(15,yun_flag);
  231.    }else
  232.    {
  233.        WriteCommand(0x01); //显示清屏
  234.            ShowString(0,"error!!!");
  235.    }
  236. }
  237. //键值处理
  238. void operation1(char keynum)//按下 ’+、-、*、/处理
  239. {
  240.   if(key_last==1)//上次按键为 数字、小数点、+/-、sqrt
  241.    {
  242.      if(neg_flag==1)num2=-num2;//'+/-'按下
  243.          if(sqrt_flag==1)//sqrt按下
  244.          {
  245.          if(num2>=0)
  246.          num2=sqrt(num2);
  247.          else
  248.          error=1;
  249.          }
  250.          if(yun_flag=='+')num1=num1+num2; //按下的是‘+’
  251.          if(yun_flag=='-')num1=num1-num2;//按下的是‘-’
  252.          if(yun_flag=='*')num1=num1*num2;//按下的是‘*’
  253.          if(yun_flag=='/')//按下的是‘/’
  254.          {
  255.            if(num2!=0)
  256.            num1=num1/num2;
  257.            else
  258.            error=1;
  259.          }
  260.          num2=0;//num2清零
  261.          sqrt_flag=0;//sqrt_flag清零
  262.      neg_flag=0;//neg_flag清零
  263.          pos_flag=1;//pos_flag回1
  264.    }
  265.    if(keynum==4)yun_flag='+';//yun_flag更新
  266.    if(keynum==8)yun_flag='-';
  267.    if(keynum==12)yun_flag='*';
  268.    if(keynum==16)yun_flag='/';
  269.    len=0;
  270.    key_last=0;//key_last更新   
  271.    refresh();
  272. }
  273. //////////////////////////////////////////////////////
  274. void operation2(char keynum)//输入数字
  275. {
  276.   float Data1;
  277.    
  278.   if(keynum==1)Data1=7;//分析输入数字
  279.   if(keynum==2)Data1=8;
  280.   if(keynum==3)Data1=9;
  281.   if(keynum==5)Data1=4;
  282.   if(keynum==6)Data1=5;
  283.   if(keynum==7)Data1=6;
  284.   if(keynum==9)Data1=1;
  285.   if(keynum==10)Data1=2;
  286.   if(keynum==11)Data1=3;
  287.   if(keynum==13)Data1=0;
  288.   if(pos_flag==1)//更新num2
  289.   num2=num2*10+Data1;
  290.   else
  291.   {            
  292.     num2=num2+(Data1/pos_flag);
  293.         pos_flag=pos_flag*10;
  294.         len++;
  295.   }
  296.   key_last=1;//更新key_last        
  297.   refresh();
  298. }
  299. ////////////////////////////////////////////////////////////
  300. void operation3()//输入小数点
  301. {
  302.   if(pos_flag==1)//首次出现小数点
  303.   {
  304.    pos_flag=pos_flag*10;//小数位权*10
  305.    len++;
  306.   }
  307.   key_last=1;//更新key_last
  308.   refresh();//更新液晶
  309. }
  310. /////////////////////////////////////////////////////
  311. void operation4()//输入'='
  312. {
  313.      if(neg_flag==1)num2=-num2;//'+/-'按下
  314.          if(sqrt_flag==1)//sqrt按下
  315.          {
  316.          if(num2>=0)
  317.          num2=sqrt(num2);
  318.          else
  319.          error=1;
  320.          }
  321.          if(yun_flag=='+')num1=num1+num2; //按下的是‘+’
  322.          if(yun_flag=='-')num1=num1-num2;//按下的是‘-’
  323.          if(yun_flag=='*')num1=num1*num2;//按下的是‘*’
  324.          if(yun_flag=='/')//按下的是‘/’
  325.          {
  326.            if(num2!=0)
  327.            num1=num1/num2;
  328.            else
  329.            error=1;
  330.          }
  331.          num2=0;//num2清零
  332.          sqrt_flag=0;//sqrt_flag清零
  333.      neg_flag=0;//neg_flag清零
  334.          pos_flag=1;//pos_flag回1
  335.      yun_flag='+';//yun_flag更新
  336.          len=0;
  337.    key_last=0;//key_last更新   
  338.    refresh();
  339. }
  340. ////////////////////////////////////////////////////
  341. void operation5()//输入clear all
  342. {

  343.    num1=0;// num1清零
  344.    num2=0;//num2清零
  345.    sqrt_flag=0;//清sqrt_flag
  346.    neg_flag=0;// 清neg_flag
  347.    pos_flag=1;// Pos_flag=1
  348.    yun_flag='+';// yun_flag(为'+')
  349.    error=0;//清error
  350.    len=0;
  351.    key_last=0;//更新key_flag
  352.    refresh();//更新液晶
  353. }
  354. ///////////////////////////////////////////////////////
  355. void operation6()//输入'C'
  356. {
  357. num2=0;//num2清零
  358. sqrt_flag=0;//清sqrt_flag
  359. neg_flag=0;//清neg_flag
  360. pos_flag=1;//pos_flag=1
  361. len=0;
  362. key_last=0;//key_last
  363. refresh();//更新液晶
  364. }
  365. ////////////////////////////////////////////////////////////
  366. void operation7()//输入'+/-'
  367. {
  368.   if(neg_flag==0)//neg_flag反转
  369.   neg_flag=1;
  370.   else neg_flag=0;
  371.   key_last=1;//key_last
  372.   refresh();// 更新液晶
  373. }
  374. /////////////////////////////////////////////////////////////
  375. void operation8()//输入'sqrt'
  376. {
  377. if(sqrt_flag==0)//sqrt_flag反转
  378.   sqrt_flag=1;
  379. else sqrt_flag=0;
  380. key_last=1;//更新key_last
  381. refresh();//更新液晶
  382. }
  383. //键值分析
  384. void key(char keynum)
  385. {
  386.   switch(keynum)
  387.   {
  388.     case 4 :
  389.         case 8 :
  390.         case 12:
  391.         case 16://+、-、*、/
  392.                     {
  393.                          if(error==0)
  394.                  operation1(keynum);
  395.                  break;}
  396.                         
  397.         case 1  : //数字7
  398.         case 2  : //数字8
  399.         case 3  : //数字9
  400.         case 5  : //数字4
  401.         case 6  : //数字5
  402.         case 7  : //数字6
  403.         case 9  : //数字1
  404.         case 10 : //数字2
  405.         case 11 : //数字3
  406.         case 13 : //数字0
  407.                  {
  408.                          if(error==0)
  409.                          operation2(keynum);
  410. …………
  411. …………
  412. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码


评分

参与人数 2黑币 +56 收起 理由
胡来的馒头 + 6 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:342386 发表于 2018-6-13 19:10 | 只看该作者
非常感谢 很有帮助!
回复

使用道具 举报

板凳
ID:314053 发表于 2018-12-25 21:14 | 只看该作者
牛人啊,大神啊。。。。厉害,膜拜
回复

使用道具 举报

地板
ID:450548 发表于 2018-12-26 08:37 | 只看该作者
非常有用,感谢楼主!!
回复

使用道具 举报

5#
ID:450548 发表于 2018-12-26 10:05 | 只看该作者
大神啊,写的真详细,里边还有具体的说明。小白进阶专用啊!!!
回复

使用道具 举报

6#
ID:404045 发表于 2018-12-27 12:39 | 只看该作者
很强  感谢分享

回复

使用道具 举报

7#
ID:461954 发表于 2019-1-4 22:07 来自手机 | 只看该作者
这里边的程序没有蜂鸣的
回复

使用道具 举报

8#
ID:481555 发表于 2019-3-1 20:44 | 只看该作者
写的真详细,里边还有具体的说明。小白进阶专用啊!!!
回复

使用道具 举报

9#
ID:262632 发表于 2019-3-20 19:15 | 只看该作者
感谢楼主,给楼主点赞
回复

使用道具 举报

10#
ID:679940 发表于 2020-1-4 10:53 | 只看该作者
xbdbox 发表于 2018-12-26 10:05
大神啊,写的真详细,里边还有具体的说明。小白进阶专用啊!!!

那他这个到底怎么连接啊,我用的单片机开发仪,不显示东西啊
回复

使用道具 举报

11#
ID:374009 发表于 2020-4-8 12:44 | 只看该作者
感谢感谢,好想学习
回复

使用道具 举报

12#
ID:281879 发表于 2020-4-8 14:34 | 只看该作者
牛啊 很详细 学习了
回复

使用道具 举报

13#
ID:743480 发表于 2020-5-3 18:03 | 只看该作者
这个可以烧进89C51吗?
回复

使用道具 举报

14#
ID:677756 发表于 2020-5-23 18:54 | 只看该作者
感谢,帮助很大,就是发现的太晚了
回复

使用道具 举报

15#
ID:763852 发表于 2020-5-28 22:57 | 只看该作者
谢谢楼主分享,帮助很大
回复

使用道具 举报

16#
ID:704379 发表于 2020-6-2 11:47 | 只看该作者
写的真的太好了,一直想找的内容
回复

使用道具 举报

17#
ID:701252 发表于 2020-10-17 09:20 | 只看该作者
高手呀!!!
正在学习中!!!我一直想学习一下计算器的编程呢!谢谢楼主分享!
回复

使用道具 举报

18#
ID:861681 发表于 2020-12-19 13:59 来自手机 | 只看该作者
程序里没有括号()啊,怎么混合四则运算
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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