51单片机 LED点阵的呼吸灯效果
扫描二维码
随时随地手机看文章
STC 89C52RC
#include
typedefunsignedcharuchar;
typedefunsignedintuint;
typedefunsignedlongulong;
sbitADDR0=P1^0;
sbitADDR1=P1^1;
sbitADDR2=P1^2;
sbitADDR3=P1^3;
sbitENLED=P1^4;
ulongperiodCnt=0;//PWM周期计数值
ucharhighRH=0;//高电平重载值的高字节
ucharhighRL=0;//高电平重载值的低字节
ucharlowRH=0;//低电平重载值的高字节
ucharlowRL=0;//低电平重载值的低字节
ucharT1RH=0;//T1重载值的高字节
ucharT1RL=0;//T1重载值的低字节
ucharcodedutyCycle[13]={//占空比调整表
5,18,30,41,51,60,68,75,81,86,90,93,95
};
ucharcodeimage[8]={
0x81,0x81,0xE7,0xC3,0xC3,0xE7,0x81,0x81
};
ucharhRHi[13],hRLi[13],lRHi[13],lRLi[13];
voidconfigTmr1(uintms);
voidconfigPWM(uintfr,uchardc);
voidcalcRldVal(ucharidx);
voidmain(){
uchari;
EA=1;//开总中断
ADDR3=0;//选中LED点阵
configPWM(1000,dutyCycle[0]);//配置并启动PWM
for(i=0;i<13;i++)
calcRldVal(i);
configTmr1(50);//用T1定时调整占空比
while(1);
}
/*配置并启动T1,ms-定时时间*/
voidconfigTmr1(uintms){
ulongtmp;//临时变量
tmp=11059200/12;//定时器计数频率
tmp=(tmp*ms)/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-占空比*/
voidconfigPWM(uintfr,uchardc){
uinthigh,low;
periodCnt=11059200/12/fr;//计算一个周期所需的计数值
high=periodCnt*dc/100;//计算高电平所需的计数值
low=periodCnt-high;//计算低电平所需的计数值
high=65536-high+12;//计算高电平的定时器重载值并补偿中断延时
low=65536-low+12;//计算低电平的定时器重载值并补偿中断延时
highRH=high>>8;//高电平重载值拆分为高低字节
highRL=high;
lowRH=low>>8;//低电平重载值拆分为高低字节
lowRL=low;
TMOD&=0xF0;//清零T0的控制位
TMOD|=0x01;//配置T0为模式1
TH0=highRH;//加载T0重载值
TL0=highRL;
ET0=1;//使能T0中断
TR0=1;//启动T0
}
/*占空比调整函数,频率不变只调整占空比*/
voidcalcRldVal(ucharidx){
uinthigh,low;
high=periodCnt*dutyCycle[idx]/100;//计算高电平所需的计数值
low=periodCnt-high;//计算低电平所需的计数值
high=65536-high+12;//计算高电平的定时器重载值并补偿中断延时
low=65536-low+12;//计算低电平的定时器重载值并补偿中断延时
hRHi[idx]=high>>8;//高电平重载值拆分为高低字节
hRLi[idx]=high;
lRHi[idx]=low>>8;//低电平重载值拆分为高低字节
lRLi[idx]=low;
}
voidLED1_Scan(){
staticuchari=0;
P0=0xFF;
P1=(P1&0xF8)|i;
P0=image[i];
i=++i&0x07;
}
/*T0中断服务函数,产生PWM输出*/
voidinterruptTimer0()interrupt1{
if(ENLED==1){
TH0=lowRH;
TL0=lowRL;
ENLED=0;
LED1_Scan();
}
else{
TH0=highRH;
TL0=highRL;
ENLED=1;
}
}
/*T1中断服务函数,定时动态调整占空比*/
voidinterruptTimer1()interrupt3{
staticbitdir=0;
staticucharindex=0;
TH1=T1RH;//重新加载T1重载值
TL1=T1RL;
highRH=hRHi[index];
highRL=hRLi[index];
lowRH=lRHi[index];
lowRL=lRLi[index];
if(dir==0){
index++;
if(index==12)
dir=1;
}
else {