1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
| /\* Main.c file generated by New Project wizard \*简易加法计算器 \* Created: 周二 6月 14 2022 \* Processor: AT89C52 \* Compiler: Keil for 8051 \*/
#include <reg52.h> sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4; 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 LedChar[] = { //数码管显示字符转换表 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E }; unsigned char LedBuff[6]={0xff,0xff,0xff,0xff,0xff,0xff}; //数码管显示缓冲区 unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表 { 0x31, 0x32, 0x33, 0x26 }, //数字键 1、数字键 2、数字键 3、向上键 { 0x34, 0x35, 0x36, 0x25 }, //数字键 4、数字键 5、数字键 6、向左键 { 0x37, 0x38, 0x39, 0x28 }, //数字键 7、数字键 8、数字键 9、向下键 { 0x30, 0x1B, 0x0D, 0x27 } //数字键 0、ESC 键、 回车键、 向右键 }; unsigned char KeySta[4][4] = { //全部矩阵按键的当前状态 {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} }; unsigned char THR0,TLR0; void KeyDriver(); void ConfigTimer(unsigned long ms); void main() { EA = 1; //使能总中断 ENLED = 0; ADDR3 = 1; ConfigTimer(1); //计算定时1ms,需要赋的初值,存在在 THR0,TLR0中 TMOD = TMOD & 0xF0; TMOD = TMOD | 0x01; //设置定时器模式1 ,不影响高四位 TH0 = THR0; //定时器赋初值 TL0 = TLR0; ET0= 1; //使能T0中断 TR0 = 1; //启动定时器T0 LedBuff[0] = LedChar[0]; //数码管默认显示0 while(1) { KeyDriver(); } } void ConfigTimer(unsigned long ms) { unsigned long temp; temp = 65536 - ms\*11059200/1000/12; //ms最大定时71ms THR0 = (unsigned char)(temp>>8); //取计数值高八位 ,计数值不会超过65535,最多占用16位。 TLR0 = (char)temp; //取计数值低八位 } void ShowNumber(unsigned long num) { signed char i; unsigned char buf[6]; //将num六位数字按顺序放入buf数组中 for(i=0;i<=5;i++) { buf[i]=num%10; num = num/10; } for(i=5;i>=1;i--) //从高位到低位依次扫描,直到某一位不为0 { if(buf[i]==0) { LedBuff[i]=0xff; //如果高位为0,则关闭此对应数码管显示,否则跳出,保留buf[]中不为0的下角标在i中 } else { break; } } for(;i>=0;i--) { LedBuff[i]=LedChar[buf[i]]; //将各位数字取出,转换成数码管显示字符放入公有数组变量LedBuff[6]中 } } void KeyAction(unsigned char keycode) { static unsigned long result = 0; static unsigned long addend = 0; if((keycode>=0x30)&&(keycode<=0x39)) //输入的是数字 { addend = (addend\*10)+(keycode-0x30); //将原有数字顶上去 ShowNumber(addend); } else if(keycode == 0x26) //上键,执行加法操作 { result += addend; //将上一个数字addend存在result中,清空addend,等待下一次数字 addend = 0; ShowNumber(result); } else if(keycode == 0x0D) //回车键,作用和上键等同 { result += addend; //将上一个数字addend存在result中,清空addend,等待下一次数字 addend = 0; ShowNumber(result); } else if(keycode == 0x1B) //esc键,清零 { addend = 0; result = 0; ShowNumber(addend); } } void KeyDriver() { unsigned char i,j; static unsigned char backup[4][4]={ //一定定义成静态,否则bug {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(KeySta[i][j]!=backup[i][j]) //当前按键状态和之前按键状态不一致,证明按键已经按下或者抬起 { if(KeySta[i][j]==0) //如果当前按键状态为0,说明按键按下;在此我们只对按键按下动作响应 { KeyAction(KeyCodeMap[i][j]); //将对应的按键转换成标准键盘码传入KeyAction中,根据传入的键盘码执行相应动作 } backup[i][j]=KeySta[i][j]; //保存当前按键状态 } } } } void LedScan() { static unsigned char i = 0; P0=0xff; switch(i) { case 0: ADDR2=0;ADDR1=0;ADDR0=0;P0=LedBuff[i];i++;break; case 1: ADDR2=0;ADDR1=0;ADDR0=1;P0=LedBuff[i];i++;break; case 2: ADDR2=0;ADDR1=1;ADDR0=0;P0=LedBuff[i];i++;break; case 3: ADDR2=0;ADDR1=1;ADDR0=1;P0=LedBuff[i];i++;break; case 4: ADDR2=1;ADDR1=0;ADDR0=0;P0=LedBuff[i];i++;break; case 5: ADDR2=1;ADDR1=0;ADDR0=1;P0=LedBuff[i];i=0;break; default:break; } } void KeyScan() { static unsigned char keyout = 0; unsigned char i; 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<=3;i++) { if((keybuf[keyout][i]&0x0f)==0x00) { KeySta[keyout][i]=0; } else if((keybuf[keyout][i]&0x0f)==0x0f) { KeySta[keyout][i]=1; } else {} } keyout++; if(keyout>=4) {keyout=0;} 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; } } void InterruptTimer0() interrupt 1 { TH0=THR0; TL0=TLR0; LedScan(); KeyScan(); }
|