【资料图】
这节太难了,2个多小时分成
由于代码量大,把跟堂作业也搬过来了课上例子,单键中断消抖读取#include <>typedef unsigned char uchar;typedef unsigned int uint;typedef unsigned long ulong;sbit ADDR0 = P1 ^ 0;sbit ADDR1 = P1 ^ 1;sbit ADDR2 = P1 ^ 2;sbit ADDR3 = P1 ^ 3;sbit ENLED = P1 ^ 4;sbit KEY1 = P2 ^ 4;sbit KEY2 = P2 ^ 5;sbit KEY3 = P2 ^ 6;sbit KEY4 = P2 ^ 7;// 数码管codeuchar code LedChar[] ={ 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};bit KeySta=1;//中断读取按键后放到这儿void main(void){ uchar cnt = 0; bit backup = 1; bit keybuf = 1; ENLED = 0; ADDR3 = 1; ADDR2 = 0; ADDR1 = 0; ADDR0 = 0; TMOD=0x01; TH0=0xF8; TL0=0xCD; ET0=EA=TR0=1; P2 = 0xF7; P0 = LedChar[cnt]; while (1) { if(KeySta != backup) { if(backup==0) { //松开 cnt++; if(cnt>=10) { cnt=0; } P0=LedChar[cnt]; } else { //按下 } backup=KeySta;//保存方便,下次比对 } }}void Timer0_ISR(void)interrupt 1{ static uchar keybuf=0xFF; TH0=0xF8; TL0=0xCD; keybuf=(keybuf<<1)|KEY4;//读取按键状态,累计到这个类似FIFO变量里面 if(keybuf==0) { //按下 KeySta=0; } else if(keybuf==0xFF) { //松开 KeySta=1; } else { //抖动 }}课上例子,矩阵按键中断消抖读取#include <>typedef unsigned char u8;typedef unsigned int u16;typedef unsigned long u32;typedef signed char i8;typedef signed int i16;typedef signed long i32;sbit ADDR0 = P1 ^ 0;sbit ADDR1 = P1 ^ 1;sbit ADDR2 = P1 ^ 2;sbit ADDR3 = P1 ^ 3;sbit ENLED = P1 ^ 4;//4个列,要读取sbit KEYIN1=P2^4;sbit KEYIN2=P2^5;sbit KEYIN3=P2^6;sbit KEYIN4=P2^7;//4个行,要拉低sbit KEYOUT1=P2^3;sbit KEYOUT2=P2^2;sbit KEYOUT3=P2^1;sbit KEYOUT4=P2^0;//保存中断消抖后,读取按键状态u8 KeySta[4][4]={ {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};// 数码管codeu8 code LedChar[] ={ 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};void main(void){ //保存上一次按键的状态 u8 backup[4][4]= { {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1} }; u8 i,j,cnt; ENLED = 0; ADDR3 = 1; ADDR2 = 0; ADDR1 = 0; ADDR0 = 0; TMOD=0x01; TH0=0xF8; TL0=0xCD; ET0=EA=TR0=1; P0 = LedChar[cnt]; while (1) { //扫描上一次状态和现在状态,有区别吗 for(i=0; i<4; i++) //out { for(j=0; j<4; j++) //in { if(backup[i][j]!=KeySta[i][j]) { if(backup[i][j]==0) { //松开 P0=LedChar[i*4+j]; } else { //按下 } backup[i][j]=KeySta[i][j]; } } } }}void Timer0_ISR(void)interrupt 1{ static u8 keyout=0;//控制4个线拉低的 u8 i=0; //保存按键每一次读取的值 static u8 keybuf[4][4]={ {0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF} }; TH0=0xF8; TL0=0xCD; //读keyout拉低行的,4个列按键状态 keybuf[keyout][0]=(keybuf[keyout][0]<<1)|KEYIN1;//读第1列按键 keybuf[keyout][1]=(keybuf[keyout][1]<<1)|KEYIN2;//读第2列按键 keybuf[keyout][2]=(keybuf[keyout][2]<<1)|KEYIN3;//读第3列按键 keybuf[keyout][3]=(keybuf[keyout][3]<<1)|KEYIN4;//读第4列按键 //判断刚读取的4个按键,是否稳定 for(i=0; i<4; i++) { if((keybuf[keyout][i] & 0x0F) == 0x00)//稳定为0 { KeySta[keyout][i]=0; } else if((keybuf[keyout][i] & 0x0F) == 0x0F)//稳定为1 { KeySta[keyout][i]=1; } else { //抖动 } } //切换下一行拉低,方便下次读取 keyout++; keyout&=0x03; switch(keyout) { case 0: KEYOUT4=1; KEYOUT1=0; break; case 1: KEYOUT1=1; KEYOUT2=0; break; case 2: KEYOUT2=1; KEYOUT3=0; break; case 3: KEYOUT3=1; KEYOUT4=0; break; }}//分析,太费内存了把,使用了16*3约50个字节的变量课上例子,加法器,up=加;enter是等于;#include <>typedef unsigned char u8;typedef unsigned int u16;typedef unsigned long u32;typedef signed char i8;typedef signed int i16;typedef signed long i32;sbit ADDR0 = P1 ^ 0;sbit ADDR1 = P1 ^ 1;sbit ADDR2 = P1 ^ 2;sbit ADDR3 = P1 ^ 3;sbit ENLED = P1 ^ 4;// 4个列,要读取sbit KEYIN1 = P2 ^ 4;sbit KEYIN2 = P2 ^ 5;sbit KEYIN3 = P2 ^ 6;sbit KEYIN4 = P2 ^ 7;// 4个行,要拉低sbit KEYOUT1 = P2 ^ 3;sbit KEYOUT2 = P2 ^ 2;sbit KEYOUT3 = P2 ^ 1;sbit KEYOUT4 = P2 ^ 0;// 保存中断消抖后,读取按键状态u8 KeySta[4][4] = { {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};// 数码管codeu8 code LedChar[16] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};// 数码管缓冲区u8 LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};u8 code KeyCodeMap[4][4] = { {0x31, 0x32, 0x33, 0x26}, // 数字1,2,3,UP {0x34, 0x35, 0x36, 0x25}, // 数字4,5,6,LEFT {0x37, 0x38, 0x39, 0x28}, // 数字7,8,9,DOWN {0x30, 0x1B, 0x0D, 0x27}, // 数字0,ESC,ENTER,RIGHT};void KeyDriver();void main(void){ TMOD = 0x01; TH0 = 0xFC; TL0 = 0x66; ET0 = EA = TR0 = 1; ENLED = 0; ADDR3 = 1; LedBuff[0] = LedChar[0]; while (1) { KeyDriver(); }}void ShowNumber(u32 num){ u8 buf[6]; u8 i,j; for (i = 0; i < 6; i++) { buf[i] = num % 10; num /= 10; } for (i = 5; i >= 1; i--) { if (buf[i] == 0) { LedBuff[i] = 0xFF; // 不显示 } else { break; } } for (j=0; j<=i;j++) { LedBuff[j] = LedChar[buf[j]]; }}void KeyAction(u8 keycode){ static u32 result = 0; static u32 addend = 0; if ((keycode >= 0x30) && (keycode <= 0x39)) { // num addend = (addend * 10) + (keycode - 0x30); ShowNumber(addend); } else if (keycode == 0x26) // up,+ { result += addend; addend = 0; ShowNumber(result); } else if (keycode == 0x0D) // enter = { result += addend; addend = 0; ShowNumber(result); } else if (keycode == 0x1B) // esc clear { addend = 0; result = 0; ShowNumber(0); }}void KeyDriver(void){ // 保存上一次按键的状态 static u8 backup[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}}; u8 i, j; // 扫描上一次状态和现在状态,有区别吗 for (i = 0; i < 4; i++) // out { for (j = 0; j < 4; j++) // in { if (backup[i][j] != KeySta[i][j]) { if (backup[i][j] == 0) { KeyAction(KeyCodeMap[i][j]); } else { // 按下 } backup[i][j] = KeySta[i][j]; } } }}void KeyScan(void){ static u8 keyout = 0; // 控制4个线拉低的 u8 i = 0; // 保存按键每一次读取的值 static u8 keybuf[4][4] = {{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}}; // 读keyout拉低行的,4个列按键状态 keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEYIN1; // 读第1列按键 keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEYIN2; // 读第2列按键 keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEYIN3; // 读第3列按键 keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEYIN4; // 读第4列按键 // 判断刚读取的4个按键,是否稳定 for (i = 0; i < 4; i++) { if ((keybuf[keyout][i] & 0x0F) == 0x00) // 稳定为0 { KeySta[keyout][i] = 0; } else if ((keybuf[keyout][i] & 0x0F) == 0x0F) // 稳定为1 { KeySta[keyout][i] = 1; } else { // 抖动 } } // 切换下一行拉低,方便下次读取 keyout++; keyout &= 0x03; switch (keyout) { case 0: KEYOUT4 = 1; KEYOUT1 = 0; break; case 1: KEYOUT1 = 1; KEYOUT2 = 0; break; case 2: KEYOUT2 = 1; KEYOUT3 = 0; break; case 3: KEYOUT3 = 1; KEYOUT4 = 0; break; }}void LedScan(void){ static u8 i = 0; P0 = 0xFF; // 消影 switch (i) { case 0: ADDR2 = 0; ADDR1 = 0; ADDR0 = 0; i++; P0 = LedBuff[0]; break; case 1: ADDR2 = 0; ADDR1 = 0; ADDR0 = 1; i++; P0 = LedBuff[1]; break; case 2: ADDR2 = 0; ADDR1 = 1; ADDR0 = 0; i++; P0 = LedBuff[2]; break; case 3: ADDR2 = 0; ADDR1 = 1; ADDR0 = 1; i++; P0 = LedBuff[3]; break; case 4: ADDR2 = 1; ADDR1 = 0; ADDR0 = 0; i++; P0 = LedBuff[4]; break; case 5: ADDR2 = 1; ADDR1 = 0; ADDR0 = 1; P0 = LedBuff[5]; i = 0; break; }}void Timer0_ISR(void) interrupt 1{ TH0 = 0xFC; TL0 = 0x66; LedScan(); KeyScan();}//课后作业在下一篇
标签: