|
本帖最后由 dabing89 于 2018-10-14 19:04 編輯
用定時器來模擬實(shí)現(xiàn)PWM實(shí)現(xiàn)呼吸燈的效果--20181012
眾所周知,PWM的應(yīng)用是及其廣泛的,現(xiàn)在很多高速的單片機(jī)內(nèi)部都集成了硬件PWM,使用起來也很簡單,配置好頻率和裝入計數(shù)值就可以工作了,但是在一些低成本的場合,我們選擇的單片機(jī)沒有硬件PWM功能模塊,但是我們還存在這個需求怎么辦呢?這個時候,我們需要用PWM來模擬實(shí)現(xiàn)他,但實(shí)現(xiàn)PWM必須要了解PWM的原理,這里我們先了解下。
PWM全稱是脈沖寬度調(diào)制解調(diào),比如1個小燈,按照500MS亮一次,500MS滅一次,周期是1S,頻率是1HZ,在這里,1個周期說明白了就是2個方波,有高電平和低電平組成,在周期固定的情況下,我們通過不斷的調(diào)整高電平所占的整個周期比例,即所謂的占空比,就可以實(shí)現(xiàn)小燈”不是那么亮“的效果,如果連續(xù)起來,就可以實(shí)現(xiàn)呼吸燈的效果了,先來用定時器0實(shí)現(xiàn)小燈500MS閃爍的效果,通過DEBUG來看下波形。我們把下面的代碼拷貝進(jìn)去,看下現(xiàn)象
單片機(jī)源碼:
方針.jpg (163.53 KB, 下載次數(shù): 155)
下載附件
2018-10-12 09:05 上傳
從DEBUG可以看到,是500MS變化一次,說明我們的設(shè)置是對的,但是在這里還是說明一點(diǎn),我們用的而是STC15W系列的芯片,但是定時器我配置成了12T模式,和STC89C52是一樣使用的。既然我們實(shí)現(xiàn)了這個500MS高電平,500MS低電平的效果,我們再來實(shí)現(xiàn)下200MS亮,800MS滅的效果吧,程序代碼如下:
仿真效果如下圖所示:
方針2.jpg (173.91 KB, 下載次數(shù): 174)
下載附件
2018-10-12 09:06 上傳
我們可以看到高電平占到了80,低電平占到了20,但是把代碼下載進(jìn)單片機(jī),怎么不是我們想要的那種狀態(tài)呢?這里普及一個知識點(diǎn),前面帖子說過的,人類的眼睛不能分辨這種刷新速度低于10MS的物體,如果物體的刷新速度高于10MS,我們的眼睛就會感覺到明顯的閃爍了,所以我們看到了下載進(jìn)開發(fā)板的現(xiàn)象就是亮200MS,滅800MS的效果,但是我們想實(shí)現(xiàn)我們想要的那種不是太亮的效果怎么辦呢?其實(shí)只要把刷新頻率高于100HZ就OK了,也就是周期要控制在10MS之內(nèi),改變高低電平所占的比例即可實(shí)現(xiàn)這樣的效果,我們寫一個讓小燈2MS亮8MS滅的程序,看看啥效果,程序如下:
方針3.jpg (180.36 KB, 下載次數(shù): 160)
下載附件
2018-10-12 09:07 上傳
將程序下載進(jìn)板子上,可以很明顯的看到小燈變的不是那么亮了,用邏輯分析儀看下,我們的周期是10MS,實(shí)現(xiàn)了我們想要的變的不是那么亮的效果,可是距離我們想要的呼吸燈還是沒有實(shí)現(xiàn)。吭趺崔k呢?答案很簡單,只要在在定時器中裝入不同的初值即可實(shí)現(xiàn)這樣的效果,不過要實(shí)現(xiàn)呼吸燈的效果,一個定時器是不夠的,還要再用一個定時器1才可以,寫好的程序如下:
- /********************************************************
- *描述:工程模板 PWM呼吸燈代碼
- ********************************************************/
- #include "stc15w.h"
- /*******************************************************************************
- * 文件名:位定義
- * 描 述:
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.05.23)
- *******************************************************************************/
- bit flag200ms = 0;
- bit flag800ms = 0;
- sbit LED0 = P1^0;//
- sbit DATA0 = P2^0;//
- void Bsp_Power_Init(void);
- void TIM0_Init(void);
- void TIM1_Init(void);
- /*******************************************************************************
- * 文件名:數(shù)據(jù)類型定義
- * 描 述:
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.05.23)
- *******************************************************************************/
- typedef unsigned char uint8;
- typedef unsigned int uint16;
- typedef unsigned long uint32;
- uint8 i = 0;
- code uint16 PWM_H[] = {
- 100,300,500,700,1000,1300,1500,1700,2000,2300,2500,2700,
- 3000,3300,3500,3700,4000,4300,4500,4700,5000,5300,5500,
- 5700,6000,6300,6500,6700,7000,7300,7500,7700,8000,8300,
- 8500,8700,9000,9300,9500,9700,9900 //高電平重裝值
- };
- code uint16 PWM_L[] = {
- 9900,9700,9500,9300,9000,8700,8500,8300,8000,7700,7500,
- 7300,7000,6700,6500,6300,6000,5700,5500,5300,5000,4700,
- 4500,4300,4000,3700,3500,3300,3000,2700,2500,2300,2000,
- 1700,1500,1300,1000,700,500,300,100//低電平重裝值
- };
- /*******************************************************************************
- * 文件名:主循環(huán)入口
- * 描 述:
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.05.23)
- *******************************************************************************/
- void main(void)
- {
- Bsp_Power_Init();//LED端口初始化
- TIM0_Init();
- TIM1_Init();
- LED0 = 1;
- while(1)
- {
- if(flag200ms)
- {
- flag200ms = 0;
- DATA0 = 0;
- }
- if(flag800ms)
- {
- flag800ms = 0;
- DATA0 = 1;
- }
- }
- }
- /*******************************************************************************
- * 文件名:void Bsp_Power_Init()
- * 描 述: 數(shù)碼管上電顯示
- * 功 能:編程模塊化
- * 作 者:大核桃
- * 版本號:1.0.1(2017.05.23)
- *******************************************************************************/
- void Bsp_Power_Init(void)
- {
- P0M1 = 0xFC;
- P0M0 = 0X03;
- P0 = 0X00;
- P1M1 = 0xE0;
- P1M0 = 0X1F;
- P1 = 0X00;
- //P2口開漏輸出
- P2M1 = 0XFF;
- P2M0 = 0XFF;
- P2 = 0Xff;
- // //P54,P55口為推挽輸出
- P5M1 = 0X00;
- P5M0 = 0X00;
- P5 = 0xFF;
- //P37,P36,3.2,P3.3 P3.4口為推挽輸出
- P3M1 = 0X00;
- P3M0 = 0XFC;
- P3 = 0X23;
- }
- /*******************************************************************************
- * 文件名:void Timer0Init(void)
- * 描 述: 數(shù)定時器0初始化
- * 功 能:編程模塊化
- * 作 者:大核桃
- * 版本號:1.0.1(2017.05.23)
- *******************************************************************************/
- void TIM0_Init(void)
- {
- AUXR &= 0x7F;//定時器時鐘12T模式
- TMOD &= 0XF0;//配置定時器0為工作模式1
- TMOD |= 0X01;
- TH0 = (65535 - 1000) / 256;//高八位重載值溢出1000次定時1ms
- TL0 = (65535 - 1000) % 256;//低八位重載值
- ET0 = 1;//打開定時器0中斷使能位
- TR0 = 1;//打開定時器,使之工作
- EA = 1;//打開總中斷
- }
- /*******************************************************************************
- * 文件名:void TIM1_Init(void)
- * 描 述:定時器1初始化配置
- * 功 能:初始化
- * 作 者:大核桃
- * 版本號:1.0.1(2016.07.23)
- *******************************************************************************/
- void TIM1_Init(void)
- {
- AUXR &= 0xBF;//定時器時鐘12T模式
- TMOD &= 0X0F;//配置定時器1為工作模式1
- TMOD |= 0X10;
- TH1 = (65535 - 10000) / 256;//高八位重載值溢出1000次定時1ms
- TL1 = (65535 - 10000) % 256;//低八位重載值
- ET1 = 1;//打開定時器1中斷使能位
- TR1 = 1;//打開定時器,使之工作
- EA = 1;//打開總中斷
- }
- /*******************************************************************************
- * 文件名:中斷服務(wù)函數(shù)
- * 描 述:定時器1中斷服務(wù)函數(shù)
- * 功 能: 中斷標(biāo)號對應(yīng) 參考數(shù)據(jù)手冊560頁
- * 中斷名稱
- * 作 者:大核桃
- * 版本號:1.0.1(2016.11.15)
- *******************************************************************************/
- void TIM1_IRQ_Handler(void) interrupt 3
- {
- static uint16 tmr50ms = 0;
- static bit a = 0;
- TH1 = (65535 - 10000) / 256;
- TL1 = (65535 - 10000) % 256;//10ms溢出一次
- tmr50ms++;
- if(tmr50ms >= 5)//50ms改變一次PWM重裝值
- {
- tmr50ms = 0;
- if(a)
- {
- i--;
- if(i == 0)
- {
- a = 0;
- }
-
- }
- else
- {
- i++;
- if(i >= 40)
- {
- a = 1;
- }
-
- }
- }
-
- }
- /*******************************************************************************
- * 文件名:void TIMER0_INTER(void) interrupt 1
- * 描 述: 中斷處理程序
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.05.23)
- *******************************************************************************/
- void TIM0_IRQ_Handler(void) interrupt 1
- {
- static bit index = 0;
- if(index)
- {
- TH0 = (65536 - PWM_H[i]) / 256;
- TL0 = (65536 - PWM_H[i]) % 256;//12MHZ下溢出1000次定時1ms
- flag200ms = 1;
- index = 0;
- }
- else
- {
- TH0 = (65536 - PWM_L[i]) / 256;
- TL0 = (65536 - PWM_L[i]) % 256;//12MHZ下溢出1000次定時1ms
- flag800ms = 1;
- index = 1;
- }
-
- }
復(fù)制代碼
我們用了定時器1每隔50MS改變1次定時器的初值,做了2個數(shù)組,分別存放PWM的高電平計數(shù)初值和低電平計數(shù)初值,在12MHZ下計數(shù)10000個,恰好是10MS,這樣我們就實(shí)現(xiàn)了呼吸燈的效果,如果你想讓呼吸燈變的更平滑更均勻,可以將定時器的初值更加細(xì)化就可以了,如果你對這個程序有啥疑問,可以留言,好了,就介紹到這里吧,代碼奉獻(xiàn)上。
全部資料51hei下載地址:
009 實(shí)用PWM的使用.rar
(35.08 KB, 下載次數(shù): 213)
2018-10-12 09:02 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
|