/************************************************************
程序?qū)崿F(xiàn)的功能:
用矩陣按鍵控制8*8LED點陣和數(shù)碼管,
實現(xiàn)按下1到9的數(shù)字鍵數(shù)碼管從100或200。。?;?00的
倒計時,一秒鐘減1,直到減到0為止。
同時LED點陣以呼吸燈的方式漸明漸暗,顯示“王”字,
當(dāng)按下數(shù)字鍵0時,LED點陣關(guān)閉,同時數(shù)碼管停止計數(shù)
并顯示結(jié)果。
作者:寧靜致遠(yuǎn)
************************************************************/
#include
typedefunsignedcharuchar;
typedefunsignedintuint;
typedefunsignedlongulong;
sbitADDR0=P1^0;
sbitADDR1=P1^1;
sbitADDR2=P1^2;
sbitADDR3=P1^3;
sbitENLED=P1^4;
sbitKEY_OUT_3=P2^0;
sbitKEY_OUT_2=P2^1;
sbitKEY_OUT_1=P2^2;
sbitKEY_OUT_0=P2^3;
sbitKEY_IN_0=P2^4;
sbitKEY_IN_1=P2^5;
sbitKEY_IN_2=P2^6;
sbitKEY_IN_3=P2^7;
ulongperiodCnt=0;//PWM周期計數(shù)值
ucharhighRH=0;//高電平重載值的高字節(jié)
ucharhighRL=0;//高電平重載值的低字節(jié)
ucharlowRH=0;//低電平重載值的高字節(jié)
ucharlowRL=0;//低電平重載值的低字節(jié)
ucharsumRH=0;
ucharsumRL=0;
ucharT1RH=0;//T1重載值的高字節(jié)
ucharT1RL=0;//T1重載值的低字節(jié)
bitenChange=1;
bitenLED1=1;
uintrate,rate2Cnt;
uintnumberShow=100;
ucharcodedutyCycle[13]={//占空比調(diào)整表
5,18,30,41,51,60,68,75,81,86,90,93,95
};
ucharpdatahRHi[13],pdatahRLi[13],pdatalRHi[13],pdatalRLi[13];
ucharcodeimage[8]={
0x81,0x81,0xE7,0xC3,0xC3,0xE7,0x81,0x81
};
ucharcodeLEDChar[]={//數(shù)碼管顯示字符轉(zhuǎn)換表
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
};
ucharLEDBuff[6]={//數(shù)碼管顯示緩沖區(qū)
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
ucharcodekeyCodeMap[4][4]={//矩陣按鍵編號到標(biāo)準(zhǔn)鍵盤鍵碼的映射表
{0x31,0x32,0x33,0x26},//數(shù)字鍵1、數(shù)字鍵2、數(shù)字鍵3、向上鍵
{0x34,0x35,0x36,0x25},//數(shù)字鍵4、數(shù)字鍵5、數(shù)字鍵6、向左鍵
{0x37,0x38,0x39,0x28},//數(shù)字鍵7、數(shù)字鍵8、數(shù)字鍵9、向下鍵
{0x30,0x1B,0x0D,0x27}//數(shù)字鍵0、ESC鍵、回車鍵、向右鍵
};
ucharkeyState[4][4]={//全部矩陣按鍵的當(dāng)前狀態(tài)
{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
};
voidconfigTmr0(uintfr,uchardc);
voidconfigTmr1(uintms1,ucharms2);
voidcalcRldVal(ucharidx);
voidkeyScan();
voidkeyAction(ucharkeyCode);
voidkeyDriver();
voidmain(){
uchari;
EA=1;//開總中斷
PT0=1;//設(shè)置T0搶占優(yōu)先
ADDR3=0;//選中LED點陣
ENLED=0;
configTmr0(1000,dutyCycle[0]);//配置并啟動PWM
for(i=0;i<13;i++)
calcRldVal(i);
configTmr1(50,1);
while(1){
keyDriver();
}
}
//配置并啟動T1,ms1:呼吸燈的變化間隔,ms2:矩陣按鍵的掃描間隔(T1溢出時間)
voidconfigTmr1(uintms1,ucharms2){
ulongtmp;//臨時變量
rate=ms1/ms2;
tmp=11059200/12;//定時器計數(shù)頻率
tmp=(tmp*ms2)/1000;//計算所需的計數(shù)值
tmp=65536-tmp;//計算定時器重載值
tmp=tmp+12;//補償中斷響應(yīng)延時造成的誤差
T1RH=tmp>>8;//定時器重載值拆分為高低字節(jié)
T1RL=tmp;
TMOD&=0x0F;//清零T1的控制位
TMOD|=0x10;//配置T1為模式1
TH1=T1RH;//加載T1重載值
TL1=T1RL;
ET1=1;//使能T1中斷
TR1=1;//啟動T1
}
/*配置并啟動PWM,fr-頻率,dc-占空比*/
voidconfigTmr0(uintfr,uchardc){
uinthigh,low,sum;
rate2Cnt=fr-1;//到達(dá)1秒所需的計數(shù)值
periodCnt=11059200/12/fr;//計算一個周期所需的計數(shù)值
high=periodCnt*dc/100;//計算高電平所需的計數(shù)值
low=periodCnt-high;//計算低電平所需的計數(shù)值
high=65536L-high+12;//計算高電平的定時器重載值并補償中斷延時
low=65536L-low+12;//計算低電平的定時器重載值并補償中斷延時
sum=65536L-periodCnt+12;
highRH=high>>8;//高電平重載值拆分為高低字節(jié)
highRL=high;
lowRH=low>>8;//低電平重載值拆分為高低字節(jié)
lowRL=low;
sumRH=sum>>8;
sumRL=sum;
TMOD&=0xF0;//清零T0的控制位
TMOD|=0x01;//配置T0為模式1
TH0=highRH;//加載T0重載值
TL0=highRL;
ET0=1;//使能T0中斷
TR0 = 1;