按键和液晶,可以组成我们最简易的计算器。下面我们来写一个简易整数计算器提供给大家学习。为了让程序不过于复杂,我们这个计算器不考虑连加,连减等连续计算,不考虑小数情况。加减乘除分别用上下左右来替代,回车表示等于,ESC 表示归 0。程序共分为三部分,一部分是 1602 液晶显示,一部分是按键动作和扫描,一部分是主函数功能。
 
-   
- #include <reg52.h>  
- #define LCD1602_DB P0  
- sbit LCD1602_RS = P1^0;  
- sbit LCD1602_RW = P1^1;  
- sbit LCD1602_E = P1^5;  
-   
-   
- void LcdWaitReady(){  
-     unsigned char sta;  
-     LCD1602_DB = 0xFF;  
-     LCD1602_RS = 0;  
-     LCD1602_RW = 1;  
-     do {  
-         LCD1602_E = 1;  
-         sta = LCD1602_DB;   
-         LCD1602_E = 0;  
-       
-     }while (sta & 0x80);  
- }  
-   
- void LcdWriteCmd(unsigned char cmd){  
-     LcdWaitReady();  
-     LCD1602_RS = 0;  
-     LCD1602_RW = 0;  
-     LCD1602_DB = cmd;  
-     LCD1602_E = 1;  
-     LCD1602_E = 0;  
- }  
-   
- void LcdWriteDat(unsigned char dat){  
-     LcdWaitReady();  
-     LCD1602_RS = 1;  
-     LCD1602_RW = 0;  
-     LCD1602_DB = dat;  
-     LCD1602_E = 1;  
-     LCD1602_E = 0;  
- }  
-   
- void LcdSetCursor(unsigned char x, unsigned char y){  
-     unsigned char addr;  
-     if (y == 0){   
-         addr = 0x00 + x;   
-     }else{  
-         addr = 0x40 + x;   
-     }  
-     LcdWriteCmd(addr | 0x80);   
- }  
-   
- void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str){  
-     LcdSetCursor(x, y);   
-     while (*str != '\0'){   
-         LcdWriteDat(*str++);  
-     }  
- }  
-   
- void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len){  
-     LcdSetCursor(x, y);   
-     while (len--){   
-         LcdWriteDat(' ');  
-     }  
- }  
-   
- void LcdFullClear(){  
-     LcdWriteCmd(0x01);  
- }  
-   
- void InitLcd1602(){  
-     LcdWriteCmd(0x38);   
-     LcdWriteCmd(0x0C);   
-     LcdWriteCmd(0x06);   
-     LcdWriteCmd(0x01);   
- }   
 
  Lcd1602.c 文件中根据上层应用的需要增加了 2 个清屏函数:区域清屏——LcdAreaClear,整屏清屏——LcdFullClear。
 
-   
- #include <reg52.h>  
- sbit KEY_IN_1 = P2^4;  
- sbit KEY_IN_2 = P2^5;  
- sbit KEY_IN_3 = P2^6;  
- sbit KEY_IN_4 = P2^7;  
- sbit KEY_OUT_1 = P2^3;  
- sbit KEY_OUT_2 = P2^2;  
- sbit KEY_OUT_3 = P2^1;  
- sbit KEY_OUT_4 = P2^0;  
-   
- unsigned char code KeyCodeMap[4][4] = {   
-     { '1', '2', '3', 0x26 },   
-     { '4', '5', '6', 0x25 },   
-     { '7', '8', '9', 0x28 },   
-     { '0', 0x1B, 0x0D, 0x27 }   
- };  
- unsigned char pdata KeySta[4][4] = {   
-     {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}  
- };  
-   
- extern void KeyAction(unsigned char keycode);  
-   
-   
- void KeyDriver(){  
-     unsigned char i, j;  
-     static unsigned char pdata backup[4][4] = {   
-         {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}  
-     };  
-      
-     for (i=0; i<4; i++){   
-         for (j=0; j<4; j++){  
-             if (backup[i][j] != KeySta[i][j]){   
-                 if (backup[i][j] != 0){   
-                     KeyAction(KeyCodeMap[i][j]);   
-                 }  
-                 backup[i][j] = KeySta[i][j];   
-             }  
-         }  
-     }  
- }  
-   
- void KeyScan(){  
-     unsigned char i;  
-     static unsigned char keyout = 0;   
-     static unsigned char keybuf[4][4] = {   
-         {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},  
-         {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}  
-     };  
-      
-       
-     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){  
-               
-             KeySta[keyout][i] = 0;  
-         }else if ((keybuf[keyout][i] & 0x0F) == 0x0F){  
-               
-             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;  
-     }  
- }   
 
  keyboard.c 是对之前已经用过多次的矩阵按键驱动的封装,具体到某个按键要执行的动作函数都放到上层的 main.c 中实现,在这个按键驱动文件中只负责调用上层实现的按键动作函数即可。 
 
-   
- #include <reg52.h>  
- unsigned char step = 0;   
- unsigned char oprt = 0;   
- signed long num1 = 0;   
- signed long num2 = 0;   
- signed long result = 0;   
- unsigned char T0RH = 0;   
- unsigned char T0RL = 0;   
-   
- 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);   
-     InitLcd1602();   
-     LcdShowStr(15, 1, "0");   
-     while (1){  
-         KeyDriver();   
-     }  
- }  
-   
- 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;   
-     while (i-- > 0){   
-         *str++ = buf[i] + '0';  
-     }  
-     *str = '\0';   
-     return len;   
- }  
-   
- void ShowOprt(unsigned char y, unsigned char type){  
-     switch (type){  
-         case 0: LcdShowStr(0, y, "+"); break;   
-         case 1: LcdShowStr(0, y, "-"); break;   
-         case 2: LcdShowStr(0, y, "*"); break;   
-         case 3: LcdShowStr(0, y, "/"); break;   
-         default: break;  
-     }  
- }  
-   
- void Reset(){  
-     num1 = 0;  
-     num2 = 0;  
-     step = 0;  
-     LcdFullClear();  
- }  
-   
- 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);   
-     }  
- }  
-   
- 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");   
-         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);  
-     }  
- }  
-   
- 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){   
-         Reset();  
-         LcdShowStr(15, 1, "0");  
-     }  
- }  
-   
- 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;