目录

  • 一、要实现什么功能
  • 二、怎样实现
  • 三、代码演示
  • 注意:一定要看

今天不打算学新知识了,把前段时间学的复习下。
用单片机按键实现计算器简单功能,开干!

一、要实现什么功能

多位显示,小数计算,连续计算,符号按错修改

二、怎样实现

LCD1602显示屏,矩阵键盘
为什么不用数码管呢?数码管需要扫描,而且对于加减乘除这些符号不是很好显示
矩阵键盘按键图如下:

三、代码演示

main.c

#include <REGX52.H>
#include "LCD1602.h"
#include "delay.h"
#include "anjian.h"
#include "Buzzer.h"/*
number1为第一次输入的按键
number2为第二次输入的按键
number3为第三次输入的按键
number4为第四次输入的按键
number为计算结果
password1和password3构成number1,password2和password4构成number2
count1,count2,count3,count4为避免输入的数字溢出的计数变量
计算的数字可能是:
整数与整数
整数与小数
小数与整数
小数与小数
按键说明:
键盘上的S1到S9分别是1到9,然后S10是0
S11为小数点,S12在第一次个数输入的时候为清除键,在第二个数输入后为等于键
S13到S16分别为加,减,乘,除。
*/float number,password1,password2;
unsigned long   number1,number2,number3,number4,password3,password4;
unsigned char symbol,count1,count2,count3,count4;
void main(){while(1){  LCD_Init();LCD_ShowString(1,1,"Calculator x4.0");LCD_ShowString(2,1,"Wellcome");password3=0;count2=0;while(1){if(symbol==13||symbol==14||symbol==15||symbol==16){break;}number1=jianpan();        if(number1){        Buzzer_Time(100);if(number1==12){LCD_ShowString(2,1,"            ");count1=0;password1=0;LCD_ShowNum(2,1,password1,8); }          if(number1<=10){if(count1<8){//最多输入8位,避免溢出password1=10*password1;//这里两行是关键,将输入的单个数字依次移位password1=number1%10+password1;                if(count1>=0)LCD_ShowNum(2,8,password1,1);LCD_ShowString(2,1,"       ");if(count1>=1)LCD_ShowNum(2,7,(unsigned long)(password1/10)%10,1);LCD_ShowString(2,1,"      ");if(count1>=2)LCD_ShowNum(2,6,(unsigned long)(password1/100)%10,1);LCD_ShowString(2,1,"     ");if(count1>=3)LCD_ShowNum(2,5,(unsigned long)(password1/1000)%10,1);LCD_ShowString(2,1,"    ");if(count1>=4)LCD_ShowNum(2,4,(unsigned long)(password1/10000)%10,1);LCD_ShowString(2,1,"   ");if(count1>=5)LCD_ShowNum(2,3,(unsigned long)(password1/100000)%10,1);LCD_ShowString(2,1,"  ");if(count1>=6)LCD_ShowNum(2,2,(unsigned long)(password1/1000000)%10,1);LCD_ShowString(2,1," ");if(count1>=7)LCD_ShowNum(2,1,(unsigned long)(password1/10000000)%10,1);}count1++;                                                                                           }if(number1==11)//不用switch,case可以提高容错率,多次改变符号的选择break;          if(number1==13){     LCD_ShowString(2,1,"            ");   LCD_ShowChar(2,1,'+');   symbol=number1;           break;}if(number1==14){           LCD_ShowString(2,1,"            ");LCD_ShowChar(2,1,'-');symbol=number1;               break;}if(number1==15){LCD_ShowString(2,1,"            ");LCD_ShowChar(2,1,'*');symbol=number1;              break;} if(number1==16){LCD_ShowString(2,1,"            ");LCD_ShowChar(2,1,'/');symbol=number1;             break;}             }
}       while(1){if(symbol==13){ LCD_ShowString(2,1,"        ");LCD_ShowChar(2,1,'+');                break;}if(symbol==14){ LCD_ShowString(2,1,"        ");LCD_ShowChar(2,1,'-');              break;}if(symbol==15){ LCD_ShowString(2,1,"        ");LCD_ShowChar(2,1,'*');              break;}if(symbol==16){ LCD_ShowString(2,1,"        ");LCD_ShowChar(2,1,'/');              break;}number2=jianpan(); if(number1==11){//如果上次输入的是小数点,那么进入此循环,否则不会进入(第一个数为整数时)          LCD_ShowChar(2,9,'.');                if(number2){Buzzer_Time(100);if(number2<=10){if(count2<3){//最多输入3位,避免溢出                   password3=10*password3;//这里两行是关键,将输入的单个数字依次移位password3=number2%10+password3;                                      if(count2>=0){LCD_ShowNum(2,10,password3,1); }if(count2>=1){ LCD_ShowNum(2,10,(password3/10)%10,1); LCD_ShowNum(2,11,password3,1);}if(count2>=2){LCD_ShowNum(2,12,password3,1); LCD_ShowNum(2,11,(password3/10)%10,1); LCD_ShowNum(2,10,(password3/100)%10,1);}//                                   LCD_ShowNum(2,10,password3,1);
//                                      LCD_ShowNum(2,11,(password3/10)%10,1);
//                                      LCD_ShowNum(2,12,(password3/100)%10,1);                 }count2++;                                                                                              }if(number2==13){//符号显示LCD_ShowString(2,1,"            ");     LCD_ShowChar(2,1,'+');symbol=number2;      break;}if(number2==14){           LCD_ShowString(2,1,"            ");LCD_ShowChar(2,1,'-');symbol=number2;                       break;}if(number2==15){LCD_ShowString(2,1,"            ");LCD_ShowChar(2,1,'*');symbol=number2;                      break;} if(number2==16){LCD_ShowString(2,1,"            ");LCD_ShowChar(2,1,'/');symbol=number2;                     break;}}        }elsebreak;
}password2=0;//(这里要注意一点是在进行连续运算的时候,第二次输入的数字要清零,不然的话到到后来第三次输入的数字是在第二次输入的基础上输入的)
password4=0;
count3=0;//(这里要注意一点是在进行连续运算的时候,计数变量要清零,不然的话到到后来可能输入不了数字**)
count4=0;while(1){number3=jianpan();      if(number3){Buzzer_Time(100);if(number3<=10){if(count3<8){//最多输入8位,避免溢出password2=10*password2;//这里两行是关键,将输入的单个数字依次移位password2=number3%10+password2;       if(count3>=0)LCD_ShowNum(2,8,password2,1);LCD_ShowString(2,1,"       ");if(count3>=1)LCD_ShowNum(2,7,(unsigned long)(password2/10)%10,1);LCD_ShowString(2,1,"      ");if(count3>=2)LCD_ShowNum(2,6,(unsigned long)(password2/100)%10,1);LCD_ShowString(2,1,"     ");if(count3>=3)LCD_ShowNum(2,5,(unsigned long)(password2/1000)%10,1);LCD_ShowString(2,1,"    ");if(count3>=4)LCD_ShowNum(2,4,(unsigned long)(password2/10000)%10,1);LCD_ShowString(2,1,"   ");if(count3>=5)LCD_ShowNum(2,3,(unsigned long)(password2/100000)%10,1);LCD_ShowString(2,1,"  ");if(count3>=6)LCD_ShowNum(2,2,(unsigned long)(password2/1000000)%10,1);LCD_ShowString(2,1," ");if(count3>=7)LCD_ShowNum(2,1,(unsigned long)(password2/10000000)%10,1);}count3++;}                                         if(number3==11){break;}if(number3==12){if(count2==1) password3=password3*100;//利用溢出变量,实现一位,二位小数的数据和三位小数的数据统一if(count2==2) password3=password3*10;switch (symbol){//整数(小数)x小数case 13:  number=(password1+password3*0.001)+(password2+password4*0.001);  break;  case 14:  number=(password1+password3*0.001)-(password2+password4*0.001);  break;case 15:  number=(password1+password3*0.001)*(password2+password4*0.001);  break;case 16:  number=(password1+password3*0.001)/(password2+password4*0.001);  break;}LCD_ShowString(2,1,"result:");LCD_ShowNum(2,8,number,1); LCD_ShowNum(2,7,(unsigned long)(number/10)%10,1); LCD_ShowNum(2,6,(unsigned long)(number/100)%10,1); LCD_ShowNum(2,5,(unsigned long)(number/1000)%10,1); LCD_ShowNum(2,4,(unsigned long)(number/10000)%10,1); LCD_ShowNum(2,3,(unsigned long)(number/100000)%10,1); LCD_ShowNum(2,2,(unsigned long)(number/1000000)%10,1); LCD_ShowNum(2,1,(unsigned long)(number/10000000)%10,1);LCD_ShowChar(2,9,'.');      LCD_ShowNum(2,10,(unsigned long)(number*1000)%1000,3);}if(number3==13||number3==14||number3==15||number3==16){ if(count2==1) password3=password3*100;//连续运算中利用溢出变量,实现一位,二位小数的数据和三位小数的数据统一      if(count2==2) password3=password3*10;switch (symbol){//整数(小数)x小数case 13:  number=(password1+password3*0.001)+(password2+password4*0.001);  break;    case 14:  number=(password1+password3*0.001)-(password2+password4*0.001);  break;case 15:  number=(password1+password3*0.001)*(password2+password4*0.001);  break;case 16:  number=(password1+password3*0.001)/(password2+password4*0.001);  break;}password1=number;symbol=number3;                         number=0;break;//结束小循环,重新进行第一步的输入操作}  }}        while(1){if(number3==13||number3==14||number3==15||number3==16){break;}number4=jianpan();       if(number3==11){   LCD_ShowChar(2,9,'.');              if(number4){ Buzzer_Time(100);if(number4<=10){if(count4<3){//最多输入3位,避免溢出                  password4=10*password4;//这里两行是关键,将输入的单个数字依次移位password4=number4%10+password4;                                      if(count4>=0){LCD_ShowNum(2,10,password4,1); }if(count4>=1){ LCD_ShowNum(2,10,(password4/10)%10,1); LCD_ShowNum(2,11,password4,1);}if(count4>=2){LCD_ShowNum(2,12,password4,1); LCD_ShowNum(2,11,(password4/10)%10,1); LCD_ShowNum(2,10,(password4/100)%10,1);}}count4++;                                                                                           } if(number4==12){if(count2==1) password3=password3*100;//利用溢出变量,实现一位,二位小数的数据和三位小数的数据统一if(count2==2) password3=password3*10;if(count4==1) password4=password4*100;if(count4==2) password4=password4*10;switch (symbol){//整数(小数)x小数case 13:  number=(password1+password3*0.001)+(password2+password4*0.001);  break;   case 14:  number=(password1+password3*0.001)-(password2+password4*0.001);  break;case 15:  number=(password1+password3*0.001)*(password2+password4*0.001);  break;case 16:  number=(password1+password3*0.001)/(password2+password4*0.001);  break;}LCD_ShowString(2,1,"result:");LCD_ShowNum(2,8,number,1); LCD_ShowNum(2,7,(unsigned long)(number/10)%10,1); LCD_ShowNum(2,6,(unsigned long)(number/100)%10,1); LCD_ShowNum(2,5,(unsigned long)(number/1000)%10,1); LCD_ShowNum(2,4,(unsigned long)(number/10000)%10,1); LCD_ShowNum(2,3,(unsigned long)(number/100000)%10,1); LCD_ShowNum(2,2,(unsigned long)(number/1000000)%10,1); LCD_ShowNum(2,1,(unsigned long)(number/10000000)%10,1);LCD_ShowChar(2,9,'.');      LCD_ShowNum(2,10,(unsigned long)(number*1000)%1000,3);       }if(number4==13||number4==14||number4==15||number4==16){if(count2==1) password3=password3*100;//连续运算中利用溢出变量,实现一位,二位小数的数据和三位小数的数据统一        if(count2==2) password3=password3*10;if(count4==1) password4=password4*100;if(count4==2) password4=password4*10;switch (symbol){//整数(小数)x小数case 13:  number=(password1+password3*0.001)+(password2+password4*0.001);  break;   case 14:  number=(password1+password3*0.001)-(password2+password4*0.001);  break;case 15:  number=(password1+password3*0.001)*(password2+password4*0.001);  break;case 16:  number=(password1+password3*0.001)/(password2+password4*0.001);  break;}password1=number;symbol=number4;                                 number=0;break;//结束小循环,重新进行第一步的输入操作  }          }}} }}

anjian.c

#include <REGX52.H>
#include "delay.h"
/*** @brief  矩阵键盘* @param  无* @retval 按下按键时进入if()和while()中,松开手的一瞬间,返回值生成,并返回原函数*         无按键按下时,返回初始值0(为什么主函数要加if?就是用来检测是否按下按键,只有按下才进入循环)*/
unsigned int jianpan(){unsigned int number=0;while(1){P1=0xFF;//在每一列前面都应该有,否则会出现反复按一个数时,出现和这个数一行的别的数P1_3=0;if(P1_7==0){delay(20);while(P1_7==0);delay(20);number=1;}if(P1_6==0){delay(20);while(P1_6==0);delay(20);number=5;}if(P1_5==0){delay(20);while(P1_5==0);delay(20);number=9;}if(P1_4==0){delay(20);while(P1_4==0);delay(20);number=13;}P1=0xFF;P1_2=0;if(P1_7==0){delay(20);while(P1_7==0);delay(20);number=2;}if(P1_6==0){delay(20);while(P1_6==0);delay(20);number=6;}if(P1_5==0){delay(20);while(P1_5==0);delay(20);number=10;}if(P1_4==0){delay(20);while(P1_4==0);delay(20);number=14;}P1=0xFF;P1_1=0;if(P1_7==0){delay(20);while(P1_7==0);delay(20);number=3;}if(P1_6==0){delay(20);while(P1_6==0);delay(20);number=7;}if(P1_5==0){delay(20);while(P1_5==0);delay(20);number=11;}if(P1_4==0){delay(20);while(P1_4==0);delay(20);number=15;}P1=0xFF;P1_0=0;if(P1_7==0){delay(20);while(P1_7==0);delay(20);number=4;}if(P1_6==0){delay(20);while(P1_6==0);delay(20);number=8;}if(P1_5==0){delay(20);while(P1_5==0);delay(20);number=12;}if(P1_4==0){delay(20);while(P1_4==0);delay(20);number=16;}return number;}
}

LCD1602.c

#include <REGX52.H>//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0//函数定义:
/*** @brief  LCD1602延时函数,12MHz调用可延时1ms* @param  无* @retval 无*/
void LCD_Delay()
{unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i);
}/*** @brief  LCD1602写命令* @param  Command 要写入的命令* @retval 无*/
void LCD_WriteCommand(unsigned char Command)
{LCD_RS=0;LCD_RW=0;LCD_DataPort=Command;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief  LCD1602写数据* @param  Data 要写入的数据* @retval 无*/
void LCD_WriteData(unsigned char Data)
{LCD_RS=1;LCD_RW=0;LCD_DataPort=Data;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief  LCD1602设置光标位置* @param  Line 行位置,范围:1~2* @param  Column 列位置,范围:1~16* @retval 无*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{if(Line==1){LCD_WriteCommand(0x80|(Column-1));}else if(Line==2){LCD_WriteCommand(0x80|(Column-1+0x40));}
}/*** @brief  LCD1602初始化函数* @param  无* @retval 无*/
void LCD_Init()
{LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动LCD_WriteCommand(0x01);//光标复位,清屏
}/*** @brief  在LCD1602指定位置上显示一个字符* @param  Line 行位置,范围:1~2* @param  Column 列位置,范围:1~16* @param  Char 要显示的字符* @retval 无*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{LCD_SetCursor(Line,Column);LCD_WriteData(Char);
}/*** @brief  在LCD1602指定位置开始显示所给字符串* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  String 要显示的字符串* @retval 无*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=0;String[i]!='\0';i++){LCD_WriteData(String[i]);}
}/*** @brief  返回值=X的Y次方*/
int LCD_Pow(int X,int Y)
{unsigned char i;int Result=1;for(i=0;i<Y;i++){Result*=X;}return Result;
}/*** @brief  在LCD1602指定位置开始显示所给数字* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  Number 要显示的数字,范围:0~65535* @param  Length 要显示数字的长度,范围:1~5* @retval 无*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');}
}

delay.c

void delay(unsigned int xms)     //@12.000MHz
{unsigned char i, j;
while(xms){i = 12;j = 169;do{while (--j);} while (--i);xms--;}
}

Buzzer.c

#include <REGX52.H>
#include <INTRINS.H>//蜂鸣器端口:
sbit Buzzer=P2^5;/*** @brief  蜂鸣器私有延时函数,延时500us* @param  无* @retval 无*/
void Buzzer_Delay500us()        //@12.000MHz
{unsigned char i;_nop_();i = 247;while (--i);
}/*** @brief  蜂鸣器发声* @param  ms 发声的时长,范围:0~32767* @retval 无*/
void Buzzer_Time(unsigned int ms)
{unsigned int i;for(i=0;i<ms*2;i++)//2x500us=1ms{Buzzer=!Buzzer;Buzzer_Delay500us();//发声频率1000Hz,一次循环用时0.5ms,故29行的ms要*2}//f=1/T,一个周期为2x500us=1ms(一个波峰和一个波谷),f=1/(1x10^-3)=1000Hz
}

注意:一定要看

千万不要直接复制代码,因为是模块化编写,模块的代码没有往上复制,大家一定要自己动手!!!!!

MCU-51:51单片机实现简单计算器功能相关推荐

  1. python实现简单计算器功能键介绍_Python实现的简单计算器功能详解

    本文实例讲述了Python实现的简单计算器功能.分享给大家供大家参考,具体如下: 使用python编写一款简易的计算器 计算器效果图 首先搭建计算器的面板: 计算器面板结构 建造一个继承于wx.Fra ...

  2. python实现简单计算器_Python实现的简单计算器功能详解

    本文实例讲述了Python实现的简单计算器功能.分享给大家供大家参考,具体如下: 使用python编写一款简易的计算器 计算器效果图 首先搭建计算器的面板: 计算器面板结构 建造一个继承于wx.Fra ...

  3. 2019.8.设计菜单,完成简单计算器功能。要求:设计5个菜单项,功能分别为加减乘除。

    1.题目: 设计菜单,完成简单计算器功能.要求:设计5个菜单项,功能分别为加减乘除. 2.代码展示(复制可直接运行) import java.util.Scanner;public class Y20 ...

  4. html制作计算器val,JavaScript实现的超简单计算器功能示例

    本文实例讲述了JavaScript实现的超简单计算器功能.分享给大家供大家参考,具体如下: 先来看看运行效果: 具体代码: www.ddpool.cn JS计算器 // window.onload 获 ...

  5. python简单计算器综合实验报告_Python实现的简单计算器功能详解

    本文实例讲述了Python实现的简单计算器功能.分享给大家供大家参考,具体如下: 使用python编写一款简易的计算器 计算器效果图 首先搭建计算器的面板: 计算器面板结构 建造一个继承于wx.Fra ...

  6. 用计算机怎么计算sh 3,Shell 实现简单计算器功能

    Shell 实现简单计算器功能,脚本如下: [root@nfs scripts]# cat jisuan.sh #!/bin/bash print_usage(){ printf $"USA ...

  7. 基于51单片机的简单计算器

    在上一篇中,我们已经说过了基于51单片机的简单拨号器,在下边,我们将写一个计算器程序,原理很简单,只需要在拨号器的基础上,算出拨号器所表示的数字,并进行计算即可. 代码如下: #include&quo ...

  8. c语言程序 实现简单计算器功能,C语言实现简单计算器小项目

    昨天刚安装上devc++,半夜想着练练C语言吧 于是就看到实验楼有一个计算器的项目 之前做过一次,这次写的主要是思路 首先我们先从原理思考jia,实现简单的计算器就要具备加减乘除这些,看普通的计算器也 ...

  9. html中实现简单计算器功能,js实现简易计算器功能

    制作能进行加减乘除的简易计算器,主要是练习动态注册事件.因以练习为主,所以包含了较多基础方法. 效果图 代码 简易计算器 window.onload = function(){ document.on ...

最新文章

  1. PHP的mongo扩展版本过低导致无法查询
  2. linux自动定时运行的脚本编写
  3. Django基本命令
  4. Java中的工厂方法模式
  5. windows动态库和静态库VS导入
  6. nginx的upstream实现负载均衡自带坏点自动剔除功能
  7. java.lang.StringBuffer源码分析
  8. 拓端tecdat|R语言可视化渐近正态性、收敛性:大数定律、中心极限定理、经验累积分布函数
  9. mysql 伪哈希_MySQL技巧--伪哈希索引
  10. Origin绘图使用自定义的RGB配色
  11. 50个C/C++面试题
  12. linux端口映射到内网机器,linux如何将公网IP映射到局域网IP?
  13. KVM实验二 pepsi-wyl
  14. 全景分割相关论文写作与准备笔记
  15. 中南大学上机:PIPI的DNA序列
  16. 计算机显示没有可以的ip地址,w7电脑提示没有有效ip地址怎么处理
  17. 艺赛旗(RPA)isrpa7.0 的 IE 自动 pagedown 到我们需要操作的地方
  18. Python爬虫实战,pyecharts模块,Python实现中国地铁数据可视化
  19. 请写出sfr和sbit的语句格式_KEIL中的SFR和SBIT用法
  20. JAVA读取X.509格式的cer公钥文件信息

热门文章

  1. 考研分数计算机总分,考研总分是多少
  2. 什么是MRTG、RRDTool、Cacti、CactiEZ?
  3. 1110. 删点成林
  4. Mac 访问端口 3306 被拒
  5. C语言UNIX时间戳4字节转北京时间
  6. cuDNN 的初始设计
  7. U盘分区合并的教程详解
  8. vr计算机组装,VR技术在计算机组装与维护中的应用研究
  9. php一年过去多少天,php 显示今天是星期几与一年的每几天代码
  10. html职业性格测试,职业性格测试小题目