天天看點

呼吸燈的實作

最近做的項目中,有要求要實作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);//暗弱控制
}