找回密码
 注册
关于网站域名变更的通知
查看: 118|回复: 2
打印 上一主题 下一主题

单片机+LCD1602矩阵键盘的计算器程序

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-6-22 09:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
51的LCD1602+矩阵键盘的简易计算器+ l9 y% O5 b7 C6 s' N3 G

3 l+ ?) S2 f5 u; J$ F! |代码有优化
- F# ]2 e, k3 D2 e% K; w/ f& j/ G5 P2 f. U; D0 b% P
7 ~5 E5 Q0 \7 A9 [
单片机源程序如下:
  e% g( i1 m" ?
  • #include <reg52.h>
  • #include <intrins.h>
  • #include <stdio.h>
  • #include "lcd1602.h"
  • typedef unsigned char uchar;
  • typedef unsigned int uint;
  • void Init_Time0(void);
  • uchar Change(uchar x,uchar y);
  • void KeyScan(void);
  • uchar KeyDriver(void);
  • sbit KEY_OUT_1 = P1^4;
  • sbit KEY_OUT_2 = P1^5;
  • sbit KEY_OUT_3 = P1^6;
  • sbit KEY_OUT_4 = P1^7;
  • sbit KEY_IN_1  = P1^0;
  • sbit KEY_IN_2  = P1^1;
  • sbit KEY_IN_3  = P1^2;
  • sbit KEY_IN_4  = P1^3;
  • uchar KeySta[4][4] = {  //全部按键状态
  •     {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
  • };
  • uchar backup[4][4] = {  //按键备份值,保存前一次的值
  • {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
  •                                 };
  • void main()
  • {
  •         uchar num=0,i=0,sign=0;
  •         uchar temp[16]={0};
  •         bit first_flag=0;
  •         float a=0,b=0;
  •         uchar s=0;
  •         LCD_Init();
  •         LCD_Clear();
  •         Init_Time0();
  •         LCD_Write_String(0,0,"LCD Calculator");
  •         LCD_Write_String(0,1,"    Yanglizidi ");
  •         while(1)
  •         {
  •                 num=KeyDriver();
  •                 if(num!=0xff)   //如果扫描是按键有效值则进行处理
  •                 {
  •                         if(i==0)
  •             LCD_Clear();
  •   //输入是第一个字符的时候需要把改行清空,方便观看
  •                         if( (num=='+')||(num=='-')||(num=='x')||(num=='/')||(num=='=')||(i==16))   //输入数字最大值16,输入符号表示输入结束
  •                         {
  •                                 i=0;                //计算器复位
  •                                 if(first_flag==0)   //如果是输入的第一个数据,赋值给a,并把标志位置1,到下一个数据输入时可以跳转赋值给b
  •                                 {
  •                                         sscanf(temp,"%f",&a);
  •                                         first_flag=1;
  •                                 }
  •                                 else
  •                                         sscanf(temp,"%f",&b);
  •                                 for(s=0;s<16;s++)  //赋值完成后把缓冲区清零,防止下次输入影响结果
  •                                  temp=0;
  •                                 LCD_Write_Char(0,1,num);
  •                                 if(num!='=')
  •                                         sign=num;                //如果不是等号记下标志位
  •                                 else
  •                                 {
  •                                         first_flag=0;                 //检测到输入=号,判断上次读入的符合
  •                                         switch (sign)
  •                                                 {
  •                                                         case '+':a=a+b;break;
  •                                                         case '-':a=a-b;break;
  •                                                         case 'x':a=a*b;break;
  •                                                         case '/':a=a/b;break;
  •                                                         default:break;
  •                                                 }
  •                                         sprintf(temp,"%g",a);    //输出浮点型,无用的0不输出
  •                                         LCD_Write_String(1,1,temp);        //显示
  •                                         sign=0;
  •                                         a=0;
  •                                         b=0;
  •                                         for(s=0;s<16;s++)
  •                                          temp=0;
  •                                 }
  •                         }
  •                 else if(i<16)
  •                 {
  •                          if((i==1)&&(temp[0]=='0'))  //如果第一个字符是0,判读第二个字符
  •                         {
  •                                 if(num=='.')  //如果是小数点则正常输入,光标位置加1
  •                                 {
  •                                         temp[1]='.';
  •                                         LCD_Write_Char(1,0,num);   //输出数据
  •                                         i++;
  •                                 }
  •                                 else
  •                                 {
  •                                         temp[0]=num;   //如果是1-9数字,说明0没有用,则直接替换第一位0
  •                                         LCD_Write_Char(0,0,num);        //输出数据
  •                                 }
  •                         }
  •                         else
  •                         {
  •                                 temp=num;
  •                                 LCD_Write_Char(i,0,num);                //输出数据
  •                                 i++;    //输入数值累加
  •                         }
  •                 }
  •         }
  • }
  • }
  • void Init_Time0()
  • {
  •         TMOD |=0X01;                //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
  •         TH0=0XFC;
  •         TL0=0X66;                        //1ms
  •         EA=1;
  •         ET0=1;
  •         TR0=1;
  • }
  • void Time0() interrupt 1
  • {
  •         TH0=0XFC;
  •         TL0=0X66;                        //1ms
  •         KeyScan();
  • }
  • //   转换成矩阵上的数
  • uchar Change(uchar x,uchar y)
  • {
  •         switch(y*4+x)
  •         {
  •                 case 0:return '1';break;//0 按下相应的键显示相对应的码值
  •                 case 1:return '2';break;//1
  •                 case 2:return '3';break;//2
  •                 case 3:return '+';break;//3
  •                 case 4:return '4';break;//4
  •                 case 5:return '5';break;//5
  •                 case 6:return '6';break;//6
  •                 case 7:return '-';break;//7
  •                 case 8:return '7';break;//8
  •                 case 9:return '8';break;//9
  •                 case 10:return '9';break;//a
  •                 case 11:return 'x';break;//b
  •                 case 12:return '0';break;//c
  •                 case 13:return '.';break;//d
  •                 case 14:return '=';break;//e
  •                 case 15:return '/';break;//f
  •                 default:return 0xff;break;
  •         }
  • }
  • /*------------------------------------------------
  •           按键值处理函数,返回扫键值
  •            可以根据需要改变返回值
  •                           | 1 | 2 | 3 | + |
  •                           | 4 | 5 | 6 | - |
  •                           | 7 | 8 | 9 | * |
  •                           | 0 | . | = | / |
  • ------------------------------------------------*/
  • //  按键驱动,检查按键动作
  • uchar KeyDriver()
  • {
  •         bit flag2=0;
  •         uchar p,num2,q;
  •         for(p=0;p<4;p++)
  •                 {
  •                         for(q=0;q<4;q++)
  •                         {
  •                                 if(backup[p][q] != KeySta[p][q])  //检测按键动作
  •                                 {
  •                                         if(backup[p][q] != 0)                //按键按下时执行的操作
  •                                         {
  •                                                 num2 = Change(p,q);
  •                                                 flag2=1;
  •                                         }
  •                                   backup[p][q] = KeySta[p][q];   //更新前一次的备份值
  •                                 }
  •                         }
  •                 }
  •                 if(flag2==1)
  •                   return num2;
  •                 else
  •                         return (0xff);
  • }
  • //    按键扫描,间隔1ms
  • void KeyScan()
  • {
  •         uchar i;
  •         static uchar keyout=0;  //索引
  •         static uchar keybuf[4][4] = {
  •    {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF},
  •    {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF}
  •     };
  •         //缓存区
  •   keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
  •   keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
  •   keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
  •   keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
  •         for(i=0;i<4;i++)
  •         {
  •                 if((keybuf[keyout] &0x0f) == 0x00)
  •                 {
  •                         //连续检测4次,四次都为0,可认为按键按下
  •       KeySta[keyout] = 0;
  •                 }
  •                 else if((keybuf[keyout] &0x0f) ==0x0f)
  •                 {
  •                         //连续检测4次,四次都为1,可认为按键弹起
  •       KeySta[keyout] = 1;
  •                 }
  •         }
  •         keyout++;   //变更下一次扫描的行
  •         keyout &= 0x03;
  •         switch (keyout)                //释放引脚
  •         {
  •           case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
  •     case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
  •     case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
  •     case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
  •     default: break;
  •         }
  • }) ~8 N* U' A$ }# Q- `, U' o

+ U; R' l2 u' ^

该用户从未签到

2#
发表于 2022-6-22 10:11 | 只看该作者
你好,请问这个是实时显示的吗?比如我输入5.23
& i( o3 r, Y, N1 o按下5 显示5
7 q. c+ A, e0 N9 P- p按下 . 显示5.
& X! P5 E( s: I* Z按下2 显示5.2. U% d7 H6 r; s' `) w' d8 q2 z
按下3 显示5.23

该用户从未签到

3#
发表于 2022-6-22 11:10 | 只看该作者
去看LCD1602的命令集,命令集里有显示光标和不显示光标的,我觉得有光标比较帅,就打开了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-8 15:21 , Processed in 0.078125 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

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