(相關資料圖)
這節太難了,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();}//課后作業在下一篇
關鍵詞: