目錄 一、前言 1,、什么是呼吸燈 2、如何實現(xiàn)呼吸燈 二,、利用for循環(huán)實現(xiàn)呼吸燈 三,、利用定時器實現(xiàn)呼吸燈 1.利用定時器中斷實現(xiàn) 2.利用定時器輸出PWM波實現(xiàn) 四、總結 一,、前言 提示:本文使用的芯片并非STM32系列,,利用定時器實現(xiàn)呼吸燈是從寄存器層面講解的,但是對于不同芯片以及是否使用庫函數(shù)開發(fā)來說,,基本原理是相同的,。 1、什么是呼吸燈 顧名思義,,呼吸燈是指燈能夠像人的呼吸一樣,,實現(xiàn)由暗到亮或由亮到暗的變化,通常用于消息提示功能,,或者作為系統(tǒng)正在運行的提示,。 2、如何實現(xiàn)呼吸燈 其實無論哪種實現(xiàn)方法,,基本思想都是通過脈沖寬度調(diào)制(PWM)實現(xiàn),,即通過調(diào)節(jié)占空比來對模擬信號電平進行數(shù)字編碼。關于何為PWM,,何為占空比,,這里就不再贅述了,簡單理解就是,,占空比越高,,LED兩端電壓越大,LED越亮,。這里用一張圖簡單的介紹一下呼吸燈的實現(xiàn)原理,。 人眼的分辨率為1秒24幀,即人眼看到的圖像滯留時間為0.04s左右,,就按40ms計算,。也就是說,,一個周期為40ms,,人眼是看不出其中的亮滅變化的。但是為了讓呼吸燈效果看起來更好,,建議選則周期長度小于40ms,,這里選則25ms。 二,、利用for循環(huán)實現(xiàn)呼吸燈 利用for循環(huán)實現(xiàn)呼吸燈主要有兩個關鍵變量,,一個是周期T,,一個是占空比的值t,他們的含義如下圖所示: 圖中T為一個周期(脈沖寬度),,t為占空比,。 利用for循環(huán)實現(xiàn)呼吸燈的程序如下:int main(void) { uint32 T = 1600; // 周期(脈沖寬度) uint32 i=0,m=0,n=0,t=0; PT0OES_D9 = 1; // 輸出使能 PT0DAT_D9 = 1; // 滅 while (1) { for (i=0;i= T) { for (i=0;i<t;i++) {="" pt0dat_d9 =" 0; // 亮" for (m="0;m<t;m++);" for (n="0;n<T-t;n++);" t--;="" }="" }="" 這里程序邏輯比較容易理解,就不再贅述,,有需要討論的小伙伴可以留言討論,。雖然利用for循環(huán)能夠很簡單的實現(xiàn)呼吸燈,但是這種方法是利用for循環(huán)來控制亮滅時間,,時間控制并不精確,。 三、利用定時器實現(xiàn)呼吸燈 1.利用定時器中斷實現(xiàn) 利用定時器中斷實現(xiàn)呼吸燈的程序如下:uint32 count= 0; uint32 flag = 0; uint32 t = 0; int main(void) { Osc_Setup(); // 初始化系統(tǒng)時鐘 EnableGlobalInterrupt(); // 使能全局中斷 PT0OES_D9 = 1; // 輸出使能 PT0DAT_D9 = 1; // 滅 TMR1_TCR_CRST = 1; // 復位定時器計數(shù)值寄存器和預分頻計數(shù)值寄存器 while (TMR1_TCR_CRST); // 等待復位完成 TMR1_PR_PR = 49; // 設置預分頻系數(shù) TMR1_MCR_MR0I = 1; // 產(chǎn)生匹配中斷 TMR1_MCR_MR0R = 1; // 產(chǎn)生計數(shù)器復位 TMR1_MCR_MR0S = 0; // 計數(shù)器不停止計數(shù) TMR1_MR0 = 250; // 設置匹配值 TMR1_IR = 0xffffffff; // 清除匹配中斷標志位 NVIC_ISER_TMR1 = 1; TMR1_TCR_CEN = 1; //定時器定時,,捕捉功能啟動 while (1) { if (t <= count) { PT0DAT_D9 = 1; // 滅 } else if (t > count) { PT0DAT_D9 = 0; // 亮 } } } void __attribute__((isr)) ISR_TMR1(void) // 匹配中斷服務函數(shù) { count = count + 1; if (count >= 100 && flag <= 100) // 由暗到亮 { count = 0; t = t + 1; flag = flag + 1; } if (count >= 100 && flag > 100) // 由亮到暗 { count = 0; t = t - 1; flag = flag + 1; } if (flag > 200) { count = 0; t = 0; flag = 0; } TMR1_IR = 0xffffffff; } 配置TMR1來實現(xiàn)呼吸燈功能,,配置TMR1時預分頻系數(shù)設置為49,匹配值設置為250,,配置產(chǎn)生匹配中斷,,中斷后產(chǎn)生計數(shù)器復位,計數(shù)器不停止計數(shù),,然后開啟定時器1,。這里需要注意的是要配置中斷后產(chǎn)生計數(shù)器復位,否則計數(shù)器會等到計數(shù)到最大值后才清零,,此時的現(xiàn)象是LED依然可是像呼吸燈一樣由暗變亮,,再由亮變暗,但是期間會不斷閃爍,。 假設進入匹配中斷的時間為t,,系統(tǒng)主時鐘頻率為Fsys,預分頻系數(shù)為PR,,匹配值為n,,那么進入一次匹配中斷的時間t= ((PR + 1)/Fsys)*n。因為開頭提到過,,本程序設置的脈沖寬度為25ms,,系統(tǒng)主時鐘頻率為50MHz,所以這里將預分頻系數(shù)設置為49和匹配值設置為250,,計算后可知,,每0.25ms進入一次匹配中斷,進入100次更改一次占空比,,即25ms更改一次,,總的脈沖寬度為25ms。如果想更改脈沖寬度只需要調(diào)整count的值即可。 2.利用定時器輸出PWM波實現(xiàn) 相比于前兩種方法來說,,初學單片機的人更加熟悉的是利用定時器輸出PWM波來實現(xiàn)呼吸燈,,因為正點原子或普中科技等等教程中都有詳細介紹,這里就不再贅述了,。 四,、總結 雖然利用for循環(huán)能夠比較簡單地實現(xiàn)呼吸燈,但是其時間控制沒有利用定時器實現(xiàn)準確,,建議使用定時器來實現(xiàn)呼吸燈功能,。 當然,上面給出的程序存在不好的地方,,在中斷中執(zhí)行了太多語句,,這是平時開發(fā)需要注意的??梢灾辉谥袛嘀斜A鬰ount自加操作,,其他放在主函數(shù)地while(1)中進行,這樣可以減少在中斷中執(zhí)行的程序,。 PS:本人也屬于技術小白級別,,本文如有寫的不合適的地方,歡迎各位在評論區(qū)討論,。 |
|
來自: Ricky_圖書館 > 《軟件編程/MCU》