背景
最近做的项目中,有要求要实现LED灯光强弱变化控制的,之前有了解过呼吸灯的概念,也知道通过PWM来控制,但也只是停留在概念上面,以前也没有真正去做过这方面的,所以就在网上再搜罗了一番,感觉还是有些云里雾里的,最后只好自己静下心来,从原理上弄懂先。
原理
了解到要想改变LED亮度改变LED的电流,就需要,一则改变限流电阻,二则改变供电电压值
。
前者一般电阻都是选定,无法再做实时更改,就算可以实时(如数字电位器)在此也是大材小用。
后者则是一个良好的选择,电压怎么变,如下:
- 该图展示了方波(PWM)与其电压有效值或者平均值的关系。
t/T
的值可以改变输出的电压有效值或者平均值,t则是高电平时间
,T则是方波(PWM)的周期值
。
我们只要固定方波周期值,固定高电平时间,即固定了占空比,也就固定了输出电压值。
实践
- 例程代码:
//灯亮度控制
void Light_LuxAssign(unsigned char Lux_Strenth)//亮度配置(实设置高电平时长)
{static unsigned char breath_rt; //呼吸计时器static const unsigned char breath_Ta=20;这里就先固定一下周期值(周期值不能超过22ms.否则会有闪烁现象,视觉暂留)static unsigned char breath_Ton; //高电平时间breath_Ton=Lux_Strenth;//注意Lux_Strenth不能超过周期值breath_Taif(breath_Ta<breath_rt)//计时器累加到一个周期{breath_rt=0; //计时器归零 } else {breath_rt++;//计时器继续累加}(breath_Ton>breath_rt)?(LED7_O(1)):(LED7_O(0));//灯亮灭时间控制
}
这段函数功能是实现输入一个固定的高电平时间值(即固定占空比),然后LED就实现了LED的亮度控制。
-
按此思路,然后就来呼吸灯的实现步骤:
- 实现呼吸灯的效果,即运行过程中,就需要实现占空比(高电平时长)如同呼吸一样消长。因为如上言,改变占空比,即改变LED两端的电压有效值,也就改变了驱动LED的有效电流值,从而实现LED暗亮的渐变效果。即动态占空比的实现
-
实现代码如下:
void Breath_Light(unsigned char breath_speed,unsigned char breath_Ta)// 呼吸速率(us)|呼吸时间(us)
{#define BREATH_TASK_TIME 200 //时基200usstatic unsigned char breath_dir;//呼吸方向(呼气/吸气)static unsigned char breath_rt;//呼吸计时器static unsigned char breath_speed_cnt;//呼吸速率累加器static unsigned char breath_Ton;//高电平时间if(!breath_dir){if(breath_Ta<breath_rt)//计时器累加到一个周期{breath_rt=0; //计时器归零if(0==breath_speed_cnt++%breath_speed) {breath_speed_cnt=0;breath_Ton++;//占空比加大} } else //{breath_rt++;//计时器继续累加}if(breath_Ton>=breath_Ta){ breath_dir=1;breath_Ton=breath_Ta;} (breath_Ton>breath_rt)?(LED7_O(1)):(LED7_O(0)); //Ton导通时间区 }else{if(breath_Ta<breath_rt)//计时器累加到一个周期{breath_rt=0; //计时器归零if(0==breath_speed_cnt++%breath_speed) {breath_speed_cnt=0;breath_Ton--;//占空比减小} } else //{breath_rt++;//计时器继续累加}if(0>=breath_Ton){ breath_dir=0;breath_Ton=0;}(breath_Ton>breath_rt)?(LED7_O(1)):(LED7_O(0)); }
}
-
上面函数是在定时器(定时时基为200us)中运行的.
-
定时器中断如下:
void TIM1_ISR() interrupt 3
{
// Breath_Light(5,100);//呼吸灯Light_LuxAssign(20);//暗弱控制
}