|
#include <reg52.h>
#include <oled.h>
#include <math.h>
#define GPIO_KEY P0//薄膜按鍵所用I/O口,P1^0~P1^7
unsigned char KeyValue=13;//矩陣鍵盤按鍵默認值
unsigned int error=0;//非法運算標志
unsigned int bei=0;//標志變量,若被加(減、乘、除)數未輸入,則bei為0
unsigned char x=0;//儲存運算符
unsigned int xf=0;//標志變量,若運算符剛被輸入,則置為1
unsigned char dan;//儲存剛輸入的單個數位上的字符型數字
unsigned int y=0;//標志變量,若要輸出運算結果則置為1
unsigned char e[9]=" Error!!!";
void LcdDisplay_1(long number);//用于在第一行輸出被加減乘除數
void LcdDisplay_2(long number);//用于在第二行輸出結果
void Delay_ms(unsigned int ms);
void main()
{
// UsartConfiguration();
//設置NVIC中斷分組2:2位搶占優先級,2位響應優先級
OLED_Init(); //初始化OLED
OLED_Clear() ; //初始化LCD1602
while(1)
{
static long key=0,result=0,temp=0,a=0,b=0,c=0,d=0;//設置靜態局部變量,可保留上一次運算的值
unsigned char i=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)//讀取按鍵是否按下
{
Delay_ms(10);//延時消抖
if(GPIO_KEY!=0x0f)//再次檢測鍵盤是否按下
{
//測試列
GPIO_KEY=0X0f;
switch(GPIO_KEY)
{
case(0X07): KeyValue=0;break;
case(0X0b): KeyValue=1;break;
case(0X0d): KeyValue=2;break;
case(0X0e): KeyValue=3;break;
}
//測試行
GPIO_KEY=0Xf0;
switch(GPIO_KEY)
{
case(0X70): KeyValue=KeyValue+0;break;
case(0Xb0): KeyValue=KeyValue+4;break;
case(0Xd0): KeyValue=KeyValue+8;break;
case(0Xe0): KeyValue=KeyValue+12;break;
}
while((i<60)&&(GPIO_KEY!=0xf0)) //松手檢測
{
Delay_ms(10);
i++;
}
switch (KeyValue)
{
//key計算最新鍵入的值,用temp存放被加(減、乘、除)數,result存放最新鍵入的值或計算結果
case 0:dan='1';key=key*10+1;result=key;break;//鍵入1,dan儲存剛輸入的單個數位上的數字
case 1:dan='2';key=key*10+2;result=key;break;//鍵入2
case 2:dan='3';key=key*10+3;result=key;break;//鍵入3
case 3:x='+';xf=1;temp=result;key=0;a=1;break; //選擇加法,x儲存選擇的運算符,選擇后xf置為1
case 4:dan='4';key=key*10+4;result=key;break;//鍵入4
case 5:dan='5';key=key*10+5;result=key;break;//鍵入5
case 6:dan='6';key=key*10+6;result=key;break;//鍵入6
case 7:x='-';xf=1;temp=result;key=0;b=1;break; //選擇減法,
case 8:dan='7';key=key*10+7;result=key;break;//鍵入7
case 9:dan='8';key=key*10+8;result=key;break;//鍵入8
case 10:dan='9';key=key*10+9;result=key;break;//鍵入9
case 11:x='*';xf=1;temp=result;key=0;c=1;break; //選擇乘法
case 12:temp=key=result=0;a=b=c=d=0;x=dan=0;xf=y=bei=0;break;//所有清零
case 13:dan='0';key=key*10+0;result=key;break;//鍵入0
case 14:if(a==1) {result=temp+result;a=0;key=0;} //計算運算結果
if(b==1) {result=temp-result;b=0;key=0;}
if(c==1) {result=temp*result;c=0;key=0;}
if(d==1)
{
if (result==0) //若除數為0,運算非法,error置為1
{error=1;result=0;d=0;key=0;}
else
{result=temp/result;d=0;key=0;}
}
y=1; //將要輸出運算結果,則y置為1
break;
case 15:x='/';xf=1;temp=result;key=0;d=1;break; //選擇除法
}
//LCD顯示
if (y==0)//若y為0,則不是輸出結果,而是輸出等式的左邊
{
if (KeyValue==12) OLED_Clear() ;//清零則清屏
else if(x==0&&bei==0) bei=1,OLED_Clear() ,OLED_WR_Byte(dan, 1);//若x和bei都為0,則當前正開始輸入被加(減、乘、除)數,要清屏再輸出,同時bei置為1
else if(x==0&&bei==1) OLED_WR_Byte( dan, 1);//若x為0,bei為1,則運算符未選擇,即當前仍然在輸入被加(減、乘、除)數,繼續逐位輸出顯示
else if(x!=0&&xf==1) xf=0,bei=0,OLED_Clear() ,LcdDisplay_1(result),OLED_WR_Byte(x,1);//若x和xf都不為0,則為剛選擇運算符,將運算符輸出且xf重新置為0,此時被加(減、乘、除)數已輸完,bei也要重新置為0
else if(x!=0&&xf==0) OLED_WR_Byte( dan,1);//若運算符已選但不是剛選,則當前正輸入加(減、乘、除)數,逐位輸出顯示
}
else //否則輸出結果
{
LcdDisplay_2(result); //輸出結果
x=0; //運算符已選,重新置為0
y=0; //輸出結果后,重新置為0
}
}
}
}
}
void LcdDisplay_1(long number)//在第一行輸出被加(減、乘、除)數
{
int i,n[5]={0}; //不能設成unsigned
if (number<0)
OLED_WR_Byte('-',1);
number=abs(number); //取絕對值
if (number-10000>=0) i=5; //判斷有效位數
else if (number-1000>=0) i=4;
else if (number-100>=0) i=3;
else if (number-10>=0) i=2;
else i=1;
n[4]=number/ 10000; //提取各位上的數
n[3]=number % 10000 / 1000;
n[2]=number % 1000 / 100;
n[1]=number % 100 / 10;
n[0]=number % 10;
for (i=i-1;i>=0;i--) //若設成unsigned,此處形成死循環!!!
{
OLED_WR_Byte(n[i]+48,1);//輸出
}
}
void LcdDisplay_2(long number)//在第二行輸出結果
{
int i,n[5]; //不能設成unsigned
//判斷運算是否合法
if (error==1) //若error為1,則運算非法
{
error=0; //error重新置為0
OLED_Clear() ; //清屏
OLED_WR_Byte(0x80,0); //數據指針返回首位
for (i=0;i<9;i++) //輸出提示
OLED_WR_Byte( e[i],1);
Delay_ms(1500);
OLED_Clear() ; //再次清屏
}
else //合法則輸出結果
{
OLED_WR_Byte('=',1); //先在第一行輸出'='
OLED_WR_Byte( 0xc0,0); //數據指針設置在第二行首位
if (number<0) //負數則輸出負號
OLED_WR_Byte('-',1);
number=abs(number);
if (number-10000>=0) i=5; //判斷有效位數
else if (number-1000>=0) i=4;
else if (number-100>=0) i=3;
else if (number-10>=0) i=2;
else i=1;
n[4]=number/10000;
n[3]=number%10000/1000;
n[2]=number%1000/100;
n[1]=number%100/10;
n[0]=number%10;
for (i=i-1;i>=0;i--) //若設成unsigned,此處形成死循環!!!
{
OLED_WR_Byte(n[i]+48,1);
}
}
/*
SBUF = '0'+m; //將接收到的數據放入到發送寄存器
while (!TI); //等待發送數據完成
TI = 0; //發送完成標志位清零
*/
}
void Delay_ms(unsigned int ms)//延時函數,延時1ms
{
int j;
for(;ms>0;ms--)
for(j=140;j>0;j--);
}
LCD和OLED頭文件的代碼在附件里。
|
|