STM8S003F3通過PWM波實現(xiàn)三基色呼吸燈
前段時間使用STM8S003F3實現(xiàn)了一個三基色燈的各種效果,故寫一篇文章作為一個記錄。
1 綜述我們知道,要是的LED燈亮直接通電即可。而要改變燈的亮度,我們有兩種方法:改變電流和PWM調光。
我們首先想到的就是改變它的驅動電流,因為LED的亮度是幾乎和它的電流直接成正比關系。然而用調正向電流的方法來調節(jié)亮度會產生一個問題:在調亮度的同時也會改變它的光譜和色溫,這樣就會會產生色偏。因為目前白光LED都是用藍光LED加黃色熒光粉而產生,當正向電流減小時,藍光LED亮度增加而黃色熒光粉的厚度并沒有按比例減薄,從而使其光譜的主波長增長。這個問題對于一般的照明是沒有問題的,因為色溫的變化量畢竟不是很大。但是對電源來說當電流過小時會產生閃爍,除非電源的恒流范圍很寬,完全可以從0到最大。這樣才沒有問題。簡而言之,電流調光有色溫變化和電源電流過小產生閃爍的問題。曾經做過一個項目,用于某設備上需要非常非常平穩(wěn)的調光,顯然電流調光是無法實現(xiàn)。同時像本文介紹的三基色調光有顏色要求的顯然也不行。因此我們使用PWM調光。
既然PWM調光可以避免上面的兩個問題,為什么不直接都用PWM調光呢?因為我們畢竟是做產品,要考慮成本問題。使用PWM調光至少需要一顆能支持PWM的芯片(當然還有外圍電路,但是電流調光也是有電路的。我們也應該知道PWM信號也可以由脈沖發(fā)生器提供),另外它需要編寫程序。所以只有在需要的場合才使用PWM調光(使用PWM調光需要注意的問題是頻率不能太低或者太高,推薦150-400Hz之間。)。PWM的優(yōu)點如下:
●PWM調光就不會產生色偏,因為它總是工作在0或者最大兩種狀態(tài)。
●PWM的占空比很好控制,而且精度高
●對電源沒有影響,因為不會改變電源的工作條件,只是給電源開或者關。
脈寬調制(PWM)是利用微處理器的數(shù)字輸出來對模擬電路進行控制的的技術,廣泛應用在從測量、通信到功率控制與變換及LED照明等許多領域中。通過以數(shù)字方式控制模擬電路,可以大幅度降低系統(tǒng)的成本和功耗。此外,許多微控制器和DSP已經在芯片上包含了PWM控制器,這使數(shù)字控制的實現(xiàn)變得更加容易了。簡言之,PWM是一種對模擬信號電平進行數(shù)字編碼的方法。通過高分辨率計數(shù)器的使用,方波的占空比被調制用來對一個具體模擬信號的電平進行編碼。PWM信號仍然是數(shù)字的,因為在給定的任何時刻,滿幅值的直流供電要么完全有(ON),要么完全無(OFF)。電壓或電流源是以一種通(ON)或斷(OFF)的重復脈沖序列被加到模擬負載上去的。通的時候即是直流供電被加到負載上的時候,斷的時候即是供電被斷開的時候。只要帶寬足夠,任何模擬值都可以使用PWM進行編碼。
首先我們需要了解占空比,占空比的解釋可以歸納為如下幾種:
●在一串理想的脈沖序列中(如方波),正脈沖的持續(xù)時間與脈沖總周期的比值。例如:脈沖寬度1μs,信號周期4μs的脈沖序列占空比為0.25。
●在一段連續(xù)工作時間內脈沖占用的時間與總時間的比值。
●在周期型的現(xiàn)象中,現(xiàn)象發(fā)生的時間與總時間的比。
通俗一點講就是電路釋放能量的有效時間與總釋放時間的比。
然后我們需要了解調光比,調光比則是按下面的方法計算(Foper:工作頻率;Fpwm:調光頻率;):
調光比率 = Foper / Fpwm,(其實也就是調光的最低有效占空比)
比如Foper=100KHZ;Fpwm=200Hz,則調光比為:100K/200=500;這個指標在很多驅動芯片的規(guī)格書里會說明的。
● 若一個占空比為10%的PWM輸出,即10%的時間通,90%的時間斷;
● 若一個占空比為50%的PWM輸出,即50%的時間通,50%的時間斷;
● 若一個占空比為90%的PWM輸出,即90%的時間通,10%的時間斷;
我們知道,人眼是有視覺暫留的,打個比方,人眼只能識別1us((這個比方沒有任何科學依據(jù),僅僅為了便于理解)內光子的數(shù)量從而判斷亮暗,如果1us接收了1000個光子,那么我們就會認為是一個亮度,至于這1000個光子是在1us什么時候收到,是沒有任何影響的,也就是說,在0.1us的時候收到和0.2us的時候收到是沒有區(qū)別的,我們需要關心的只是數(shù)量。這就是為什么我們進行PWM調光的時候不能太慢(視覺暫留可以分辨)也不能太快(太快就沒有區(qū)別了,就一直是最亮的)。這樣就好理解了,占空比是10%,就相當于給它加了一個0.9V的電壓(因為10%通電時間里電流產生的效果和0.9V加在周內的時候是一樣的)。所以我們就可以通過占空比來條件亮度。
如果在50ms中,LED在這段時間中得到9V供電。如果在下一個50ms中將開關斷開,燈泡得到的供電將為0V。如果在1秒鐘內將此過程重復10次,燈泡將會點亮并象連接到了一個4.5V電池(9V的50%)上一樣。這種情況下,占空比為50%,調制頻率為10Hz(T=1/f = 1/10 = 0.1S )。大多數(shù)負載(無論是電感性負載還是電容性負載)需要的調制頻率高于10Hz。設想一下如果燈泡先接通5秒再斷開5秒,然后再接通、再斷開……。占空比仍然是50%,但燈泡在頭5秒鐘內將點亮,在下一個5秒鐘內將熄滅。要讓燈泡取得4.5V電壓的供電效果,通斷循環(huán)周期與負載對開關狀態(tài)變化的響應時間相比必須足夠短。要想取得調光燈(但保持點亮)的效果,必須提高調制頻率。在其他PWM應用場合也有同樣的要求。通常調制頻率為1kHz到200kHz之間。
通過上面的介紹,我們就知道了PWM調光的原理,那么我們來看看我們這個項目的原理。
2.3.2 三基色呼吸燈原理需求說明:我們需要設置一個燈,它具有常亮、長暗、快閃、慢閃、呼吸5鐘效果,并且要求這幾種狀態(tài)是可以變化的。燈的顏色可以變化。
需求分析:燈的顏色可以變化——確定使用三基色燈。狀態(tài)可以切換,我們使用串口調節(jié)燈的狀態(tài)和燈的顏色(通過串口給單片機發(fā)送數(shù)據(jù),然后將參數(shù)傳給燈控制函數(shù))。我們使用PWM調節(jié)燈的亮度,通過改變捕獲/比較寄存器的值來改變占空比從而改變亮度。
數(shù)學建模:三個燈和一個燈的控制是一樣的,由于我們使用的是PWM波調光所以燈只有兩種狀態(tài):斷和通。我們分析5種狀態(tài)可以抽象成數(shù)學模型:暗、上升、亮、下降4鐘狀態(tài)(長暗就是一直暗,常亮就是一直亮,快閃就是100%占空比而且頻率比較快,慢閃就是100%占空比而且頻率比較慢、呼吸就是占空比最低為10%然后以10%逐漸上升)。然后我們確定需要輸入的變量:Value_LED_Red(紅色燈的亮度)、Value_LED_Green(綠色燈的亮度)、Value_LED_Blue(藍燈的亮度)、Value_ChangeOnce(上升或下降的速度)、HoldTime_Min(在低電平狀態(tài)的持續(xù)時間)、HoldTime_Max(在高電平狀態(tài)的持續(xù)時間)。
3 實現(xiàn)過程下面是TSSOP20封裝的管腳圖。
首先,我們要確定硬件管腳,但是事實上,因為我用的最多的就是TIM2和TIM4,因此我選用的TIM2_1(PC5,Red)、TIM2_2(PD3,Green)、TIM2_3(PD2,Blue),但是發(fā)現(xiàn)除了綠色以外都無法用PWM波控制,但是能用IO控制亮暗,后來查資料發(fā)現(xiàn)TIM2_1和TIM2_3早使用的時候必須給存儲器地址分布重映射,也就是我們需要使用管腳的復用功能!我們通過看《數(shù)據(jù)手冊》發(fā)現(xiàn),使用TIM2只有一個管腳是復用功能,因此選擇TIM2。但是我因為電路限制,所以還是用的上面所說的管腳(注意,TIM2_3有復用和不復用兩種,我用的是復用)。這也沒有什么影響,我們可以學習一下管腳的復用功能。
3.1 使用復用功能我們首先看《數(shù)據(jù)手冊》中關于管腳的描述(第一行是TSSOP20封裝的管腳編號,第二行是UFQFPN20封裝的管腳b)
從上面的圖中我們可以看到,需要使用15、19管腳復用功能就需要設置AFR0和AFR1——使用復用功能就是設置AFR(Alternate function remapping bits,候補功能映射位)——我們繼續(xù)看芯片資料
其中OPT2【選項字節(jié)(Option byte)編程 】和NOPT2需要是相反的(可能是出于校驗考慮),我們從《數(shù)據(jù)手冊》中可以知道: 應用程序可直接向目標地址進行寫操作。所以我們直接對這兩個地址進行寫操作,那么數(shù)值是多少呢?我們繼續(xù)看《數(shù)據(jù)手冊》,如下圖所示
從上圖中我們可以看到,我們將AFR1設置為1,將AFR0設置成1。代碼如下:
/***************************************************************
*Function:FLASH_Init
*Calls:void
*CalledBy:All_Config.c
*Input:void
*OUTPUT:void
*Return:void
*DESCRIPTION:1.設置管腳復用功能(AFR0要設置為1AFR1要設置為1)
2.eeprom每一次只能操作一個字節(jié)
*Others:nothing
***************************************************************/
volatile unsigned char flash_OPT2 @0x4803;