? PWM是一種對模擬信號電平進行????數字編碼?????的方法。通過高????分辨率????計數器的使用,方波的占空比被調制用來對一個具體????模擬信號????的電平進行編碼。PWM信號仍然是數字的,因為在給定的任何時刻,滿幅值的直流供電要么完全有(ON),要么完全無(OFF)。電壓或電流源是以一種通(ON)或斷(OFF)的重復脈沖序列被加到模擬負載上去的。通的時候即是直流供電被加到負載上的時候,斷的時候即是供電被斷開的時候。只要帶寬足夠,任何模擬值都可以使用PWM進行編碼。
脈寬調制(PWM,Pulse Width Modulation)是利用微處理器的數字輸出來對模擬電路進行控制的一種非常有效的技術,廣泛應用在從測量、通信到功率控制與變換的許多領域中 。
?PWM的一個優點是從處理器到???被控系統???信號都是數字形式的,再進行數模轉換。可將噪聲影響降到最低(可以跟電腦一樣)。噪聲只有在強到足以將邏輯1改變為邏輯0或將邏輯0改變為邏輯1時,也才能對數字信號產生影響。
1.PWM模式
用戶可以使用 PWM 模式產生一個信號,其占空比由 TIMx_CCDATx 寄存器的值決定,其頻率由TIMx_AR 寄存器的值決定。 并且取決于 TIMx_CTRL1.CAMSEL 的值, TIM 可以在邊沿對齊模式或中央對齊模式下產生 PWM 信號。
用戶可以通過設置 TIMx_CCMODx. OCxMD=110 或設置 TIMx_CCMODx.OCxMD=111 來設置 PWM 模式 1 或 PWM 模式 2。 要使能預加載寄存器,用戶必須設置相應的 TIMx_CCMODx.OCxPEN。 然后設置 TIMx_CTRL1.ARPEN 自動重裝載預加載寄存器。
用戶可以通過設置 TIMx_CCEN.CCxP 來設置 OCx 的極性。當 TIM 處于 PWM 模式時, TIMx_CNT 和 TIMx_CCDATx 的值總是相互比較。
只有當更新事件發生時,預加載寄存器才會轉移到影子寄存器。 因此,用戶必須在計數器開始計數之前通過設置 TIMx_EVTGEN.UDGN 來復位所有寄存器。
1.1 PWM中央對齊模式
如果用戶設置 TIMx_CTRL1.CAMSEL 等于 01、 10 或 11, PWM 中央對齊模式將被激活。 比較標志的設置取決于 TIMx_CTRL1.CAMSEL 的值。 設置比較標志的情況有 3 種,僅當計數器向上計數時,僅當計數器向下計數時,或當計數器向上計數和向下計數時。 用戶不應通過軟件修改 TIMx_CTRL1.DIR,它是由硬件更新的。
中央對齊 PWM 波形示例如下,波形設置為: TIMx_AR=8, PWM 模式 1 ,當計數器向下計數對應TIMx_CTRL1.CAMSEL=01 時設置比較標志。
使用中央對齊模式時用戶應注意的事項如下:
計數器向上或向下計數取決于 TIMx_CTRL1.DIR 的值。 注意不要同時更改 DIR 和 CAMSEL 位
用戶在中央對齊模式下不要寫計數器,否則會導致意想不到的結果。 例如:
如果寫入計數器的值為 0 或者是 TIMx_AR 的值,則方向會被更新,但不會產生更新事件
如果寫入計數器的值大于自動重載的值,則方向不會更新
為了安全起見,建議用戶在啟動計數器之前設置 TIMx_EVTGEN.UDGN 以通過軟件生成更新,并且在計數器運行時不要寫入計數器。
1.2 PWM 邊沿對齊模式
邊沿對齊模式有兩種配置,向上計數和向下計數。
向上計數
用戶可以設置 TIMx_CTRL1.DIR=0 使計數器向上計數。
PWM 模式 1 的示例:
當 TIMx_CNT < TIMx_CCDATx 時, OCxREF 為高電平,否則為低電平。 如果 TIMx_CCDATx 中的比較值大于自動重載值,則 OCxREF 將保持為 1。相反,如果比較值為 0,則 OCxREF 將保持為 0。當 TIMx_AR=8 時, PWM 波形如下:
向下計數
用戶可以設置 TIMx_CTRL1.DIR=1 使計數器向下計數。
PWM 模式 1 的示例:
當 TIMx_CNT > TIMx_CCDATx 時, OCxREF 為低電平,否則為高電平。 如果 TIMx_CCDATx 中的比較值大于自動重載值,則 OCxREF 將保持為 1。
注:若第n 個PWM 周期CCDATx 影子寄存器>=AR 值,第n+1 個PWM 周期CCDATx 的影子寄存器值是0。在第n+1 個PWM周期的計數器為0 的時刻,雖然計數器 = CCDATx 影子寄存器的值 = 0, OCxREF =‘0’,但不會產生比較事件。
2.通過PWM輸出呼吸燈示例
1.根據N32G45帖子介紹可知LED硬件接口:https://bbs.elecfans.com/jishu_2320004_1_1.html
2.接下來我我們以D2、D3為例(D2、D3剛才處于TIM3的通道1和通道2上),實現PWM輸出控制LED。
根據參考手冊第7章可以看到,我們想要實現該功能,就需要開始TIM3的部分重映射功能。
TIM3通道的部分重映射配置如下:
RCC->APB2PCLKEN|=1<<0;//AFIO AFIO->RMP_CFG&=~(0x3<<10); AFIO->RMP_CFG|=2<<10;//開啟部分重映像 AFIO->RMP_CFG&=~(0x7<<24); AFIO->RMP_CFG|=1<<24;//將PB4設置為普通IO
寄存器相關介紹可查看N32用戶手冊第7.4章節AFIO寄存器配置。
3.配置定時器基本功能和PWM模式。
在完成PWM模式輸出時,我們需要先完成定時器的基本功能配置(開定時器時鐘、設置預分頻系數,設置周期時間)。
定時器相關寄存器可參考N32用戶手冊12.4章節。下面列舉幾個常用寄存器。
控制寄存器1(TIM_CTRL1)
本寄存器主要實現定時器的基本功能配置:設置計數模式、開始定時器等。
預分頻器(TIM_PSC)
本寄存器設置定時器的工作頻率,例如要實現計數器+1的時長為1us,則時鐘的PSC=72-1;
注意:定時器的時鐘線工作頻率為72MHZ,即CK_PSC=72MHZ
重裝載寄存器(TIM_AR)
重裝載寄存器為實現定時器計數周期。
捕獲比較寄存器(TIM_CCDAT1)
當為輸出模式時,CCDAT寄存器用于設置占空比;當為輸入模式時,CCDAT用于保存捕獲到的電平時間;
捕獲/比較寄存器(TIM_CCMOD)
捕獲比較寄存器用于設置輸入捕獲模式和輸出比較模式的通道參數信息。
捕獲/比較使能寄存器(TIM_CCEN)
捕獲比較使能寄存器用于啟動通道、設置有效電平極性。
2.1 定時配置示例
完成定時器基本功能配置,設置周期時間,設置分頻系數,配置通道參數,輸出PWM。
/*********************************** ** **函數功能:定時器器PWM輸出 **TIM3通道引腳: ** 沒有重映射 部分重映射 完全重映射 ** TIM3_CH1 PA6 PB4 PC6 ** TIM3_CH2 PA7 PB5 PC7 **形參: ** chx --要開啟的通道(1 --通道1,2--通道2, 3 --表示開啟通道1和通道2) ** psc --預分頻系數 ** ar --重裝載值(即周期時間) ** ccr --占空比 ** 注意:本示例采用部分重映射功能 **作者:IT_阿水 ************************************/ void TIM3_PWM_Out(u8 chx,u16 psc,u16 ar,u16 ccr) { /*1.開時鐘*/ RCC->APB2PCLKEN|=1<<3;//PB RCC->APB2PCLKEN|=1<<0;//AFIO AFIO->RMP_CFG&=~(0x3<<10); AFIO->RMP_CFG|=2<<10;//開啟部分重映像 AFIO->RMP_CFG&=~(0x7<<24); AFIO->RMP_CFG|=1<<24;//將PB4設置為普通IO /*2.配置GPIO*/ GPIOB->PL_CFG&=0xFF00FFFF; GPIOB->PL_CFG|=0x00BB0000;//通用復用推挽輸出模式 /*3.定時器配置*/ RCC->APB1PCLKEN|=1<<1;//TIM3 RCC->APB1PRST|=1<<1;//開啟復位時鐘 RCC->APB1PRST&=~(1<<1);//取消復位 TIM3->CTRL1|=1<<7; TIM3->PSC=psc-1;//預分頻 TIM3->AR=ar;//重裝載值 /*輸出PWM配置*/ if(chx&0x1) { TIM3->CCMOD1&=~(0x3<<0);//輸出 TIM3->CCMOD1|=1<<2;//快速使能 TIM3->CCMOD1|=1<<3;//預加載 TIM3->CCMOD1|=0x6<<4;//PWM0 TIM3->CCDAT1=ccr;//占空比,有效電平時間 TIM3->CCEN|=1<<0;//開啟CH1 } if(chx&1<<1)//CH2 { TIM3->CCMOD1&=~(0x3<<8);//輸出 TIM3->CCMOD1|=1<<10;//快速使能 TIM3->CCMOD1|=1<<11;//預加載 TIM3->CCMOD1|=0x6<<12;//PWM0 TIM3->CCDAT2=ccr;//占空比,有效電平時間 TIM3->CCEN|=1<<4;//開啟CH2 } TIM3->CTRL1|=1<<0;//開啟定時器 }
2.2 呼吸燈效果實現
通過調節PWM輸出的占空比,實現LED呼吸燈效果。
#include "n32g45x.h" #include #include #include "led.h" #include "key.h" #include "usart.h" #include "delay.h" #include "timer.h" int main() { u8 key_val; int time=0; u8 flag=0; LED_Init(); KEY_Init(); USART_Init(115200); TIM3_PWM_Out(3,72,400,0); printf("串口初始化完成rn"); while(1) { key_val=Key_Scan(); if(key_val) { printf("串口+DMA數據發送測試示例!rn"); } if(usart1_flag) { usart1_rx_buff[usart1_cnt]='?'; printf("%s,%drn",usart1_rx_buff,usart1_cnt); if(strcmp((char *)usart1_rx_buff,"LED1_ON")==0)LED_D1=1; else if(strcmp((char *)usart1_rx_buff,"LED1_OFF")==0)LED_D1=0; else if(strcmp((char *)usart1_rx_buff,"LED2_ON")==0)LED_D2=1; else if(strcmp((char *)usart1_rx_buff,"LED2_OFF")==0)LED_D2=0; else if(strcmp((char *)usart1_rx_buff,"LED3_ON")==0)LED_D3=1; else if(strcmp((char *)usart1_rx_buff,"LED3_OFF")==0)LED_D3=0; usart1_flag=0; } if(time>=400)flag=1; else if(time<=0)flag=0; if(flag)time--; else time++; TIM3->CCDAT1=time; TIM3->CCDAT2=time; Delay_Ms(10); } }
審核編輯:湯梓紅
-
PWM
+關注
關注
114文章
5181瀏覽量
213796 -
定時器
+關注
關注
23文章
3246瀏覽量
114719 -
n32g455
+關注
關注
0文章
7瀏覽量
925
發布評論請先 登錄
相關推薦
評論