51单片机之大杂烩
扫描二维码
随时随地手机看文章
/************************************************************
程序实现的功能:
用矩阵按键控制8*8LED点阵和数码管,
实现按下1到9的数字键数码管从100或200。。。或900的
倒计时,一秒钟减1,直到减到0为止。
同时LED点阵以呼吸灯的方式渐明渐暗,显示“王”字,
当按下数字键0时,LED点阵关闭,同时数码管停止计数
并显示结果。
作者:宁静致远
************************************************************/
#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周期计数值
ucharhighRH=0;//高电平重载值的高字节
ucharhighRL=0;//高电平重载值的低字节
ucharlowRH=0;//低电平重载值的高字节
ucharlowRL=0;//低电平重载值的低字节
ucharsumRH=0;
ucharsumRL=0;
ucharT1RH=0;//T1重载值的高字节
ucharT1RL=0;//T1重载值的低字节
bitenChange=1;
bitenLED1=1;
uintrate,rate2Cnt;
uintnumberShow=100;
ucharcodedutyCycle[13]={//占空比调整表
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[]={//数码管显示字符转换表
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
};
ucharLEDBuff[6]={//数码管显示缓冲区
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
ucharcodekeyCodeMap[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键、回车键、向右键
};
ucharkeyState[4][4]={//全部矩阵按键的当前状态
{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;//设置T0抢占优先
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;//定时器计数频率
tmp=(tmp*ms2)/1000;//计算所需的计数值
tmp=65536-tmp;//计算定时器重载值
tmp=tmp+12;//补偿中断响应延时造成的误差
T1RH=tmp>>8;//定时器重载值拆分为高低字节
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;//到达1秒所需的计数值
periodCnt=11059200/12/fr;//计算一个周期所需的计数值
high=periodCnt*dc/100;//计算高电平所需的计数值
low=periodCnt-high;//计算低电平所需的计数值
high=65536L-high+12;//计算高电平的定时器重载值并补偿中断延时
low=65536L-low+12;//计算低电平的定时器重载值并补偿中断延时
sum=65536L-periodCnt+12;
highRH=high>>8;//高电平重载值拆分为高低字节
highRL=high;
lowRH=low>>8;//低电平重载值拆分为高低字节
lowRL=low;
sumRH=sum>>8;
sumRL=sum;
TMOD&=0xF0;//清零T0的控制位
TMOD|=0x01;//配置T0为模式1
TH0=highRH;//加载T0重载值
TL0=highRL;
ET0=1;//使能T0中断
TR0 = 1;