按键和液晶,可以组成我们最简易的计算器。下面我们来写一个简易整数计算器提供给大家学习。为了让程序不过于复杂,我们这个计算器不考虑连加,连减等连续计算,不考虑小数情况。加减乘除分别用上下左右来替代,回车表示等于,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;