#include <reg51.h>
#include <stdio.h>
#include <intrins.h>
#define u8 unsigned char
#define u16 unsigned char
sbit LCDEN=P3^4;
sbit RS=P3^5;
sbit RW=P3^6;
sbit BF=P0^7;
u8 code keyval[]="789/456*123-c0=+"; //按鍵對應的符號
u8 data1[10];
u8 k=0;
char m[10]={0};
double sum=0;
void delay(u16 x) //延時x毫秒
{
u16 i,j;
for(i=0;i<x;i++)
for(j=0;j<115;j++)
;
}
u8 keypad4_4()//按鍵掃描函數(shù):要去抖,若有按鍵按下,返回對應的按鍵值(0-15),沒有按鍵按下返回16
{
u8 i,row,temp;
u8 key=16;//按鍵號,初值設置為16,目的是:沒有按鍵按下時返回16;
//若不設初值(默認值為0),沒有按鍵按下時,將返回0,會誤認為0被按下
row=0xef; //從第一列開始
for(i=0;i<4;i++)
{
P1=0xff;
P1=row; //第i列信號,對應列為低,其他全為高
row=_crol_(row,1); //生成下一列信號
temp=P1; //讀入掃描信號
temp=temp&0x0f; //屏蔽高4位列信號,只保留低4位行信號
if(temp!=0x0f)//有按鍵被按下,因為第i列某行有按鍵按下,則低4位中有一位為低
{
delay(20); //延時去抖
temp=P1;
temp=temp&0x0f;
if(temp!=0x0f) //再次確認有按鍵被按下
{
switch(temp) //根據(jù)低4位行信號,判斷哪個按鍵被按下
{
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=P1; //再次掃描按鍵
temp=temp&0x0f;
}while(temp!=0x0f); //等待按鍵釋放
}
}
}
return(key);//掃面結束,返回按鍵值
}
unsigned char DectectBusyBit(void)//狀態(tài)判斷函數(shù)(忙/閑?)
{
bit result;
P0 = 0xff; //讀狀態(tài)前先置高電平,防止誤判
RS = 0;
delay(5);
RW = 1;
LCDEN = 1;
delay(5);
result=BF; //若LCM忙,則反復測試,在此處原地踏步;當LCM閑時,才往下繼續(xù)
LCDEN = 0;
return result;
}
void WrComLCD(unsigned char ComVal)//寫命令函數(shù)
{
while(DectectBusyBit()==1); //先檢測LCM是否空閑
RS = 0;
delay(1);
RW = 0;
LCDEN = 1;
P0 = ComVal;
delay(1);
LCDEN = 0;
}
void WrDatLCD(unsigned char DatVal)//寫數(shù)據(jù)函數(shù)
{
while(DectectBusyBit()==1);
RS = 1;
delay(1);
RW = 0;
LCDEN = 1;
P0 = DatVal;
delay(1);
LCDEN = 0;
}
void LCD_Init(void)//1602初始化函數(shù)
{
WrComLCD(0x38); // 功能設定:16*2行、5*7點陣、8位數(shù)據(jù)接口
WrComLCD(0x38);
WrComLCD(0x38);
//多次重復設定功能指令,因為LCD啟動后并不知道使用的是4位數(shù)據(jù)接口還是8位的,所以開始時總是默認為4位
WrComLCD(0x01); // 清屏
WrComLCD(0x06); // 光標自增、屏幕不動
delay(1); // 延時,等待上面的指令生效,下面再顯示,防止出現(xiàn)亂碼
WrComLCD(0x0c); // 開顯示
}
void compute(){
u8 i,j=0,k,n=0;
char data3[10]={0};
int sum1,data2[10]={0};
sum=0;
for(i=0;data1[i]!='\0';i++){
if(data1[i]!='+' && data1[i]!='-' && data1[i]!='*' && data1[i]!='/'){
data2[j] =data2[j]*10+(data1[i]-'0');
}
else{
data3[n++] = data1[i];
j++;
}
}
for(i=0;i<n;i++){
if(i==0){
if(data3[0]=='+') sum = data2[0] + data2[1];
if(data3[0]=='-') sum = data2[0] - data2[1];
if(data3[0]=='*') sum = data2[0] * data2[1];
if(data3[0]=='/') sum = data2[0] / (double)data2[1];
}
if(i==1){
if(data3[1]=='+') sum = sum+data2[2];
if(data3[1]=='-') sum = sum-data2[2];
if(data3[1]=='*') sum = sum*data2[2];
if(data3[1]=='/') sum = sum/((float)data2[2]);
}
if(i==2){
if(data3[2]=='+') sum = sum+data2[3];
if(data3[2]=='-') sum = sum-data2[3];
if(data3[2]=='*') sum = sum*data2[3];
if(data3[2]=='/') sum = sum/((float)data2[3]);
}
}
//判斷是小數(shù)輸出還是整數(shù)輸出
sum1 = sum;
if(sum1==sum){
sprintf(m,"%d",sum1);
}
else{
sprintf(m,"%f",sum);
}
//把結果輸出出來
for(k=0;m[k]!='\0';k++){
WrDatLCD(m[k]);
}
}
void main()
{
u8 y;
LCD_Init();
delay(5); //延時,等待初始化完成
WrDatLCD('0');
WrComLCD(0x80); //設置顯示地址第一行第一位:0X00(0x80+0x00)
while(1){
y= keypad4_4();
if(y==12) { k=0;WrComLCD(0x01);WrDatLCD('0'); WrComLCD(0x80);} //清屏
if(y==14) {
WrComLCD(0xC0); WrDatLCD(keyval[y]); WrDatLCD(' '); data1[k]='\0';compute();//調(diào)用出結果函數(shù)
}
if(y<16 && y!=12 && y!=14)
{
WrDatLCD(keyval[y]);
data1[k++]= keyval[y];
}
}
}
僅供大家參考,大家可以多多回復及評論,😄
|