|
#include <reg52.h>
unsigned char step = 0; //操作步驟
unsigned char oprt = 0; //運算類型
signed long num1 = 0; //操作數1
signed long num2 = 0; //操作數2
signed long result = 0; //運算結果
unsigned char T0RH = 0; //T0重載值的高字節
unsigned char T0RL = 0; //T0重載值的低字節
void ConfigTimer0(unsigned int ms);
extern void KeyScan();
extern void KeyDriver();
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
extern void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len);
extern void LcdFullClear();
void main()
{
EA = 1; //開總中斷
ConfigTimer0(1); //配置T0定時1ms
InitLcd1602(); //初始化液晶
LcdShowStr(15, 1, "0"); //初始顯示一個數字0
while (1)
{
KeyDriver(); //調用按鍵驅動
}
}
/* 長整型數轉換為字符串,str-字符串指針,dat-待轉換數,返回值-字符串長度 */
unsigned char LongToString(unsigned char *str, signed long dat)
{
signed char i = 0;
unsigned char len = 0;
unsigned char buf[12];
if (dat < 0) //如果為負數,首先取絕對值,并在指針上添加負號
{
dat = -dat;
*str++ = '-';
len++;
}
do { //先轉換為低位在前的十進制數組
buf[i++] = dat % 10;
dat /= 10;
} while (dat > 0);
len += i; //i最后的值就是有效字符的個數
while (i-- > 0) //將數組值轉換為ASCII碼反向拷貝到接收指針上
{
*str++ = buf[i] + '0';
}
*str = '\0'; //添加字符串結束符
return len; //返回字符串長度
}
/* 顯示運算符,顯示位置y,運算符類型type */
void ShowOprt(unsigned char y, unsigned char type)
{
switch (type)
{
case 0: LcdShowStr(0, y, "+"); break; //0代表+
case 1: LcdShowStr(0, y, "-"); break; //1代表-
case 2: LcdShowStr(0, y, "*"); break; //2代表*
case 3: LcdShowStr(0, y, "/"); break; //3代表/
default: break;
}
}
/* 計算器復位,清零變量值,清除屏幕顯示 */
void Reset()
{
num1 = 0;
num2 = 0;
step = 0;
LcdFullClear();
}
/* 數字鍵動作函數,n-按鍵輸入的數值 */
void NumKeyAction(unsigned char n)
{
unsigned char len;
unsigned char str[12];
if (step > 1) //如計算已完成,則重新開始新的計算
{
Reset();
}
if (step == 0) //輸入第一操作數
{
num1 = num1*10 + n; //輸入數值累加到原操作數上
len = LongToString(str, num1); //新數值轉換為字符串
LcdShowStr(16-len, 1, str); //顯示到液晶第二行上
}
else //輸入第二操作數
{
num2 = num2*10 + n; //輸入數值累加到原操作數上
len = LongToString(str, num2); //新數值轉換為字符串
LcdShowStr(16-len, 1, str); //顯示到液晶第二行上
}
}
/* 運算符按鍵動作函數,運算符類型type */
void OprtKeyAction(unsigned char type)
{
unsigned char len;
unsigned char str[12];
if (step == 0) //第二操作數尚未輸入時響應,即不支持連續操作
{
len = LongToString(str, num1); //第一操作數轉換為字符串
LcdAreaClear(0, 0, 16-len); //清除第一行左邊的字符位
LcdShowStr(16-len, 0, str); //字符串靠右顯示在第一行
ShowOprt(1, type); //在第二行顯示操作符
LcdAreaClear(1, 1, 14); //清除第二行中間的字符位
LcdShowStr(15, 1, "0"); //在第二行最右端顯示0
oprt = type; //記錄操作類型
step = 1;
}
}
/* 計算結果函數 */
void GetResult()
{
unsigned char len;
unsigned char str[12];
if (step == 1) //第二操作數已輸入時才執行計算
{
step = 2;
switch (oprt) //根據運算符類型計算結果,未考慮溢出問題
{
case 0: result = num1 + num2; break;
case 1: result = num1 - num2; break;
case 2: result = num1 * num2; break;
case 3: result = num1 / num2; break;
default: break;
}
len = LongToString(str, num2); //原第二操作數和運算符顯示到第一行
ShowOprt(0, oprt);
LcdAreaClear(1, 0, 16-1-len);
LcdShowStr(16-len, 0, str);
len = LongToString(str, result); //計算結果和等號顯示在第二行
LcdShowStr(0, 1, "=");
LcdAreaClear(1, 1, 16-1-len);
LcdShowStr(16-len, 1, str);
}
}
/* 按鍵動作函數,根據鍵碼執行相應的操作,keycode-按鍵鍵碼 */
void KeyAction(unsigned char keycode)
{
if ((keycode>='0') && (keycode<='9')) //輸入字符
{
NumKeyAction(keycode - '0');
}
else if (keycode == 0x26) //向上鍵,+
{
OprtKeyAction(0);
}
else if (keycode == 0x28) //向下鍵,-
{
OprtKeyAction(1);
}
else if (keycode == 0x25) //向左鍵,*
{
OprtKeyAction(2);
}
else if (keycode == 0x27) //向右鍵,÷
{
OprtKeyAction(3);
}
else if (keycode == 0x0D) //回車鍵,計算結果
{
GetResult();
}
else if (keycode == 0x1B) //Esc鍵,清除
{
Reset();
LcdShowStr(15, 1, "0");
}
}
/* 配置并啟動T0,ms-T0定時時間 */
void ConfigTimer0(unsigned int ms)
{
unsigned long tmp; //臨時變量
tmp = 11059200 / 12; //定時器計數頻率
tmp = (tmp * ms) / 1000; //計算所需的計數值
tmp = 65536 - tmp; //計算定時器重載值
tmp = tmp + 28; //補償中斷響應延時造成的誤差
T0RH = (unsigned char)(tmp>>8); //定時器重載值拆分為高低字節
T0RL = (unsigned char)tmp;
TMOD &= 0xF0; //清零T0的控制位
TMOD |= 0x01; //配置T0為模式1
TH0 = T0RH; //加載T0重載值
TL0 = T0RL;
ET0 = 1; //使能T0中斷
TR0 = 1; //啟動T0
}
/* T0中斷服務函數,執行按鍵掃描 */
void InterruptTimer0() interrupt 1
{
TH0 = T0RH; //重新加載重載值
TL0 = T0RL;
KeyScan(); //按鍵掃描
}
|
|