|
51的LCD1602+矩陣鍵盤(pán)的簡(jiǎn)易計(jì)算器
代碼有優(yōu)化
capture_20210714204142920.jpg (39.36 KB, 下載次數(shù): 98)
下載附件
2021-7-14 21:05 上傳
單片機(jī)源程序如下:
- #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] = { //全部按鍵狀態(tài)
- {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) //如果掃描是按鍵有效值則進(jìn)行處理
- {
- if(i==0)
- LCD_Clear();
- //輸入是第一個(gè)字符的時(shí)候需要把改行清空,方便觀看
- if( (num=='+')||(num=='-')||(num=='x')||(num=='/')||(num=='=')||(i==16)) //輸入數(shù)字最大值16,輸入符號(hào)表示輸入結(jié)束
- {
- i=0; //計(jì)算器復(fù)位
- if(first_flag==0) //如果是輸入的第一個(gè)數(shù)據(jù),賦值給a,并把標(biāo)志位置1,到下一個(gè)數(shù)據(jù)輸入時(shí)可以跳轉(zhuǎn)賦值給b
- {
- sscanf(temp,"%f",&a);
- first_flag=1;
- }
- else
- sscanf(temp,"%f",&b);
- for(s=0;s<16;s++) //賦值完成后把緩沖區(qū)清零,防止下次輸入影響結(jié)果
- temp[s]=0;
-
- LCD_Write_Char(0,1,num);
-
- if(num!='=')
- sign=num; //如果不是等號(hào)記下標(biāo)志位
- else
- {
- first_flag=0; //檢測(cè)到輸入=號(hào),判斷上次讀入的符合
- 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); //輸出浮點(diǎn)型,無(wú)用的0不輸出
- LCD_Write_String(1,1,temp); //顯示
- sign=0;
- a=0;
- b=0;
- for(s=0;s<16;s++)
- temp[s]=0;
- }
- }
- else if(i<16)
- {
- if((i==1)&&(temp[0]=='0')) //如果第一個(gè)字符是0,判讀第二個(gè)字符
- {
- if(num=='.') //如果是小數(shù)點(diǎn)則正常輸入,光標(biāo)位置加1
- {
- temp[1]='.';
- LCD_Write_Char(1,0,num); //輸出數(shù)據(jù)
- i++;
- }
- else
- {
- temp[0]=num; //如果是1-9數(shù)字,說(shuō)明0沒(méi)有用,則直接替換第一位0
- LCD_Write_Char(0,0,num); //輸出數(shù)據(jù)
- }
- }
- else
- {
- temp[i]=num;
- LCD_Write_Char(i,0,num); //輸出數(shù)據(jù)
- i++; //輸入數(shù)值累加
- }
- }
- }
- }
- }
- void Init_Time0()
- {
- TMOD |=0X01; //使用模式1,16位定時(shí)器,使用"|"符號(hào)可以在使用多個(gè)定時(shí)器時(shí)不受影響
- TH0=0XFC;
- TL0=0X66; //1ms
- EA=1;
- ET0=1;
- TR0=1;
- }
- void Time0() interrupt 1
- {
- TH0=0XFC;
- TL0=0X66; //1ms
- KeyScan();
- }
- // 轉(zhuǎn)換成矩陣上的數(shù)
- uchar Change(uchar x,uchar y)
- {
- switch(y*4+x)
- {
- case 0:return '1';break;//0 按下相應(yīng)的鍵顯示相對(duì)應(yīng)的碼值
- 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;
- }
- }
-
- /*------------------------------------------------
- 按鍵值處理函數(shù),返回掃鍵值
- 可以根據(jù)需要改變返回值
- | 1 | 2 | 3 | + |
- | 4 | 5 | 6 | - |
- | 7 | 8 | 9 | * |
- | 0 | . | = | / |
- ------------------------------------------------*/
- // 按鍵驅(qū)動(dòng),檢查按鍵動(dòng)作
- 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]) //檢測(cè)按鍵動(dòng)作
- {
- if(backup[p][q] != 0) //按鍵按下時(shí)執(zhí)行的操作
- {
- 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}
- };
-
- //緩存區(qū)
- 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][i] &0x0f) == 0x00)
- {
- //連續(xù)檢測(cè)4次,四次都為0,可認(rèn)為按鍵按下
- KeySta[keyout][i] = 0;
- }
- else if((keybuf[keyout][i] &0x0f) ==0x0f)
- {
- //連續(xù)檢測(cè)4次,四次都為1,可認(rèn)為按鍵彈起
- KeySta[keyout][i] = 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;
- }
- }
復(fù)制代碼
本人初學(xué),僅供參考,存在錯(cuò)誤和不足之處,請(qǐng)大家回帖多多指教,切勿照搬,Keil代碼下載:
LCD1602智能計(jì)算器1.0.7z
(37.46 KB, 下載次數(shù): 186)
2021-7-14 21:03 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|