STC89C52定时器实现呼吸灯
基本思路
💡 小灯的亮度不能直接控制,但是在足够小的单位时间内,控制小灯的亮灭时间比例,就可以在人的视觉上呈现出不同的亮度。可以使用定时器实现PWM波形。
-
闪烁周期
共2s,前1s内由灭到亮,后1s由亮到暗。
-
PWN周期
1s之内100个PWM周期,每个周期10ms。
-
占空比highValPro变化
使用定时器1中断,每10ms,即一个PWM周期变化一次,前1s逐渐增大到1,后1s逐渐减小到0。
void highValProChange() interrupt 3 // 1ms *10 { TL1 = 0x66; TH1 = 0xFC; T1OverflowTimes++; if(T1OverflowTimes>=10){ if(flag==0) highValPro++; else highValPro--; T1OverflowTimes = 0; if( highValPro==100||highValPro==0) flag=!flag; } }
-
PWN内高低电平转换
使用定时器0中断,通过全局变量time在一个PWN周期内计时(计数),当time<highValPro时,输出高电平小灯亮,否则输出低电平,小灯灭。time每一百分之一个PWN周期即100us自增一次。
void timeChange() interrupt 1 //100us * 100 { TL0 = 0xA4; TH0 = 0xFF; if(time<100) time++; else time = 0; }
整体代码
#include<reg52.h>
#include<intrins.h>
typedef unsigned int u16;
typedef unsigned char u8;
void Timer0Init(void);
void Timer1Init(void);
u8 highValPro =1; //Proportion of hignval
u8 time = 0; //every 100us ++
u8 T1OverflowTimes = 0;
u8 flag=0;
void main()
{
EA =1; //打开中断总使能
Timer0Init(); //定时器0初始化
Timer1Init(); //定时器1初始化
TMOD = 0x11;
while(1){
if(time<highValPro) //占空比内区域
P2 = 0xEF;
else P2 = 0xFF; //超出占空比部分
}
}
void Timer0Init(void) //100us
{
//AUXR &= 0x7F;
//TMOD &= 0xF0;
TMOD |= 0x01; //设置工作方式为16位
TL0 = 0xA4;
TH0 = 0xFF;
TF0 = 0;
TR0 = 1; //开始计时
ET0 = 1; //允许中断
}
void Timer1Init(void) //1ms@11.0592MHz
{
//AUXR &= 0xBF;
//TMOD &= 0x0F;
TMOD |= 0x10; //设置工作方式为16位
TL1 = 0x66;
TH1 = 0xFC;
TF1 = 0;
TR1 = 1; //开始计时
ET1 = 1; //允许中断
}
void timeChange() interrupt 1 //100us * 100;控制PWN周期内分时time计数
{
TL0 = 0xA4;
TH0 = 0xFF;
if(time<100)
time++;
else time = 0; //每满100开始新周期计数
}
void highValProChange() interrupt 3 // 1ms *10;改变一次
{
TL1 = 0x66;
TH1 = 0xFC;
T1OverflowTimes++;
if(T1OverflowTimes>=10){
if(flag==0)
highValPro++;
else highValPro--;
T1OverflowTimes = 0;
if( highValPro==100||highValPro==0) flag=!flag; //每一秒,flag变化,控制占空比变化方向
}
}