|
我們?cè)谶@里使用4*4的矩陣按鍵KEYPAD-SMALLCALC與1602液晶屏LMO16L在單片機(jī)上實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器仿真實(shí)驗(yàn)。
首先我們定義一個(gè)字符數(shù)組存儲(chǔ)按鍵對(duì)應(yīng)的鍵值,使用程序查詢的方法掃描矩陣按鍵;當(dāng)結(jié)束輸入時(shí),我們就對(duì)字符串進(jìn)行處理了并將結(jié)果顯示在液晶屏上。
在程序中,適當(dāng)?shù)氖褂靡恍⿴?kù)函數(shù)可以大大提高我們的編程效率,在這里,我們主要對(duì)字符串進(jìn)行操作,使用了stdlib.h、ctype.h庫(kù)中的一些函數(shù),如下:
atoi:將字符串轉(zhuǎn)換成整數(shù)
atof:將字符串轉(zhuǎn)換成浮點(diǎn)數(shù)
isalnum:測(cè)試是否為字母數(shù)字
0.png (122.55 KB, 下載次數(shù): 64)
下載附件
2019-1-31 23:31 上傳
0.png (9.44 KB, 下載次數(shù): 61)
下載附件
2019-2-1 01:47 上傳
單片機(jī)源程序如下:
- #include<reg51.h>
- #include<intrins.h>
- #include<ctype.h>
- #include<stdlib.h>
- #include<stdio.h>
- #include<math.h>
- #include<string.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit LCDEN=P3^4;
- sbit RS=P3^5;
- sbit RW=P3^6;
- sbit BF=P0^7;
- sbit BEEP=P1^0;
- uchar str[17];
-
- uchar code keyval[]="789/456*123-c0=+"; //按鍵對(duì)應(yīng)的符號(hào)
- void delay(unsigned int xms)
- {
- int i,j;
- for(i=xms;i>0;i--)
- for(j=110;j>0;j--);
- }
- uchar keypad4_4()//按鍵掃描函數(shù):要去抖,若有按鍵按下,返回對(duì)應(yīng)的按鍵值(0-15),沒(méi)有按鍵按下返回16
- {
- uchar i,row,temp;
- uchar key=16;//按鍵號(hào),初值設(shè)置為16,目的是:沒(méi)有按鍵按下時(shí)返回16;
- //若不設(shè)初值(默認(rèn)值為0),沒(méi)有按鍵按下時(shí),將返回0,會(huì)誤認(rèn)為0被按下
- row=0xef; //從第一列開(kāi)始
- for(i=0;i<4;i++)
- {
- P2=0xff;
- P2=row; //第i列信號(hào),對(duì)應(yīng)列為低,其他全為高
- row=_crol_(row,1); //生成下一列信號(hào)
- temp=P2; //讀入掃描信號(hào)
- temp=temp&0x0f; //屏蔽高4位列信號(hào),只保留低4位行信號(hào)
- if(temp!=0x0f)//有按鍵被按下,因?yàn)榈趇列某行有按鍵按下,則低4位中有一位為低
- {
- delay(20); //延時(shí)去抖
- temp=P2;
- temp=temp&0x0f;
- if(temp!=0x0f) //再次確認(rèn)有按鍵被按下
- {
- switch(temp) //根據(jù)低4位行信號(hào),判斷哪個(gè)按鍵被按下
- {
- case 0x0e:key=0+i;break; //第i列第1行按鍵被按下
- case 0x0d:key=4+i;break; //第i列第2行按鍵被按下
- case 0x0b:key=8+i;break; //第i列第3行按鍵被按下
- case 0x07:key=12+i; //第i列第4行按鍵被按下
- }
-
- do
- {
- temp=P2; //再次掃描按鍵
- temp=temp&0x0f;
- }while(temp!=0x0f); //等待按鍵釋放
- }
- }
- }
- return(key);//掃面結(jié)束,返回按鍵值
- }
- uchar RdACAdr()//讀當(dāng)前光標(biāo)地址
- {
- uchar result;
- P2 = 0xff; //讀地址前先置高電平,防止誤判
- RS = 0;
- delay(5);
- RW = 1;
- LCDEN = 1;
- delay(5);
- result=P2&0x7f; //去掉最高位忙閑標(biāo)記,只保留低7位地址值
- LCDEN = 0;
- return result;
- }
- uchar DectectBusyBit(void)//狀態(tài)判斷函數(shù)(忙/閑?)
- {
- bit result;
- P0 = 0xff; //讀狀態(tài)前先置高電平,防止誤判
- RS = 0;
- delay(5);
- RW = 1;
- LCDEN = 1;
- delay(5);
- result=BF; //若LCM忙,則反復(fù)測(cè)試,在此處原地踏步;當(dāng)LCM閑時(shí),才往下繼續(xù)
- LCDEN = 0;
- return result;
- }
- void WrComLCD(unsigned char ComVal)//寫(xiě)命令函數(shù)
- {
- while(DectectBusyBit()==1); //先檢測(cè)LCM是否空閑
- RS = 0;
- delay(1);
- RW = 0;
- LCDEN = 1;
- P0 = ComVal;
- delay(1);
- LCDEN = 0;
- }
- void WrDatLCD(uchar DatVal)//寫(xiě)數(shù)據(jù)函數(shù)
- {
- while(DectectBusyBit()==1);
- RS = 1;
- delay(1);
- RW = 0;
- LCDEN = 1;
- P0 = DatVal;
- delay(1);
- LCDEN = 0;
- }
- void WrStrDat(uchar *p)//顯示英文字符串(長(zhǎng)度不超過(guò)32)
- {
- uchar i=0,t;
-
- while(p[i]!='\0')
- {
- WrDatLCD(p[i]);
- i++;
- delay(5);
-
- t=RdACAdr();
- if(t==0x10) WrComLCD(0xc0);//讀當(dāng)前坐標(biāo),如果第1行寫(xiě)完換行到第2行
- if(t==0x50) WrComLCD(0x80);//讀當(dāng)前坐標(biāo),如果第2行寫(xiě)完換行到第1行
- }
- }
- void LCD_Init(void)//1602初始化函數(shù)
- {
- //delay(15);
- WrComLCD(0x38);
- //delay(5); // 功能設(shè)定:16*2行、5*7點(diǎn)陣、8位數(shù)據(jù)接口
- WrComLCD(0x38);
- //delay(5);
- WrComLCD(0x38);
- //多次重復(fù)設(shè)定功能指令,因?yàn)長(zhǎng)CD啟動(dòng)后并不知道使用的是4位數(shù)據(jù)接口還是8位的,所以開(kāi)始時(shí)總是默認(rèn)為4位,這樣剛開(kāi)始寫(xiě)入功能設(shè)定指令時(shí),低4位被忽略,為了可靠,最好多寫(xiě)幾遍該指令
- WrComLCD(0x01); // 清屏
- WrComLCD(0x06); // 光標(biāo)自增、屏幕不動(dòng)
- delay(1); // 延時(shí),等待上面的指令生效,下面再顯示,防止出現(xiàn)亂碼
- WrComLCD(0x0C); // 開(kāi)顯示、關(guān)光標(biāo)
- }
- double str2num(uchar* str)
- {
- uint i=0,j=0,index=0;
- uchar ch[10];
- long a1=atol(str),b1=0;
- double a2=atof(str),b2=0,c=0;
- for(i=0;str[i]!='\0';i++)
- {
- if(!isalnum(str[i]))
- {
- index=i;
- break;
- }
- }
- for(j=0,i=index+1;i<=strlen(str);i++)
- ch[j++]=str[i];
- b1=atol(ch);
- b2=atof(ch);
- switch(str[index])
- {
- case '+':c=a1+b1;break;
- case '-':c=a1-b1;break;
- case '*':c=a2*b2;break;
- case '/':c=a2/b2;break;
- default:c=a2;break;
- }
- return c;
- }
- void main()
- {
-
- uchar i=0,j=0,y=16;
- uchar flag=0;
- uchar end=0;
- LCD_Init();
- delay(5); //延時(shí),等待初始化完成
- WrComLCD(0x80); //設(shè)置顯示地址第一行第一位:0X00(0x80+0x00)
- delay(1);
- WrComLCD(0xc0);
- delay(1);
- WrDatLCD('0');
- delay(1);
- WrComLCD(0x80);
- while(1)
- {
- y=keypad4_4();
-
- if(y<16)
- {
- if(y!=12)
- {
- if(end==1)
- {
- end=0;
- flag=0;
- WrComLCD(0x01);
- delay(1);
- WrComLCD(0xc0);
- delay(1);
- WrDatLCD('0');
- delay(1);
- WrComLCD(0x80);
- }
- str[strlen(str)]=keyval[y];
- WrDatLCD(keyval[y]);
- if(y==14)
- {
- uchar ch[17];
- flag=1;
- end=1;
- str[strlen(str)]='\0';
- WrComLCD(0xc0);
-
- sprintf(ch,"%.2f",str2num(str));
- WrStrDat(ch);
- for(i=0;i<17;i++)
- str[i]='\0';
- }
- }
- else
- {
- ……………………
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
51簡(jiǎn)單計(jì)算器.zip
(141.66 KB, 下載次數(shù): 159)
2019-1-31 23:33 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|