最近做的項目中,有要求要實作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_Ta
if(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 //時基200us
static 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);//暗弱控制
}