一、通用定時器簡介
STM32通用定時器由一個通過可編程預分頻器驅動的16位自動重裝載計數器組成,適用于多種應用場景,包括測量輸入信號的脈沖長度(利用輸入捕獲功能)和生成輸出波形(使用輸出比較及PWM功能)。借助于定時器預分頻器以及RCC時鐘控制器提供的預分頻能力,用戶可以靈活調整脈沖長度和波形周期,范圍可從幾微秒至幾毫秒不等。每個通用定時器都是完全獨立的,不共享任何資源,這保證了它們可以在互不影響的情況下單獨運行,同時也支持同步操作,以滿足復雜的實時控制需求。
通用TIMx (TIM2、TIM3、TIM4和TIM5)定時器功能包括:
- 16位向上、向下、向上/向下自動裝載計數器
- 16位可編程(可以實時修改)預分頻器,計數器時鐘頻率的分頻系數為1~65536之間的任意數值
- 4個獨立通道:
- 輸入捕獲
- 輸出比較
- PWM生成(邊緣或中間對齊模式)
- 單脈沖模式輸出
- 使用外部信號控制定時器和定時器互連的同步電路
- 如下事件發生時產生中斷/DMA:
- 更新:計數器向上溢出/向下溢出,計數器初始化(通過軟件或者內部/外部觸發)
- 觸發事件(計數器啟動、停止、初始化或者由內部/外部觸發計數)
- 輸入捕獲
- 輸出比較
- 支持針對定位的增量(正交)編碼器和霍爾傳感器電路
- 觸發輸入作為外部時鐘或者按周期的電流管理
二、通用定時器內部結構
通用定時器的內部結構相較于基本定時器而言復雜得多,主要由以下幾個關鍵部分組成:時基單元、時鐘發生器、輸入捕獲以及輸出比較等。
1. 時鐘源
通用定時器提供了四種不同的時鐘來源選項,具體選擇可通過配置TIMx_SMCR寄存器的相關位來實現:
(1)內部時鐘(CK_INT):這是最常見的時鐘源選擇,適用于大多數應用場景。
(2)外部時鐘模式1:使用外部輸入引腳TIx(x=1,2,3,4)作為時鐘源,允許定時器根據外部信號進行計數。
(3)外部時鐘模式2:通過外部觸發輸入ETR提供時鐘信號,進一步擴展了定時器的應用范圍。
(4)內部觸發輸入(ITRx,x=0,1,2,3):利用其他定時器或系統內部產生的觸發信號作為時鐘源。
在典型配置中,我們通常選擇內部時鐘(CK_INT)作為通用定時器的時鐘來源,并且由于APB1的時鐘分頻系數不為1,通用定時器的時鐘頻率是APB1時鐘的兩倍,即72MHz。
2. 控制器
通用定時器的控制器部分集成了觸發控制器、從模式控制器以及編碼器接口,以支持廣泛的應用需求。
觸發控制器負責生成觸發信號,可用于驅動片內外設的操作,如為其他定時器提供時鐘或觸發DAC和ADC轉換,從而增強系統內不同模塊間的同步與協調能力。
從模式控制器則管理計數器的各種操作狀態,包括復位、啟動、遞增或遞減計數,使得定時器能夠適應復雜的計數模式和同步操作要求,滿足多樣化的實時控制需求。此外,專門設計的編碼器接口用于處理來自旋轉編碼器的輸入信號,通過準確解碼位置信息調整計數器值,適用于需要精確位置反饋的應用場景。
3. 時基單元
通用定時器的時基單元由三個核心寄存器組成:計數器寄存器(TIMx_CNT)、預分頻器寄存器(TIMx_PSC)和自動重裝載寄存器(TIMx_ARR)。在高級定時器中,還額外包含一個重復計數寄存器(TIMx_RCR),這一特性在通用和基本定時器中并不存在。
在時基單元內,預分頻器寄存器(TIMx_PSC)用于對計數器時鐘頻率進行分頻調整。通過設置寄存器內的相應位,可以將分頻系數設定在1到65536之間,從而靈活控制計數器的工作頻率。由于從模式控制寄存器具備緩沖功能,預分頻器支持實時更改,新的分頻比將在下一個更新事件發生時生效。
此外,時基單元中的計數器寄存器(TIMx_CNT)支持多種計數方式:
(1)向上計數
在向上(遞增)計數模式下,計數器從0開始計數,每當接收到一個CK_CNT脈沖時,計數器的值增加1,直至達到自動重載寄存器(TIMx_ARR)中設定的值。此時,計數器會觸發一次上溢事件,并重新從0開始計數。
(2)向下計數
在向下(遞減)計數模式下,計數器從自動重載寄存器(TIMx_ARR)中設定的值開始遞減計數,每接收到一個CK_CNT脈沖時,計數器的值減少1,直至計數至0。此時,計數器觸發一次下溢事件,并重新從自動重載值開始新一輪計數。
(3)中央對齊計數
在中心對齊模式下,計數器的操作分為兩個階段:首先從0開始遞增計數至自動重載寄存器(TIMx_ARR)中設定的值減1,此時生成計數器上溢事件;然后從自動重載值開始遞減計數至1,并生成計數器下溢事件。
在時基單元中還有一個自動重載寄存器(TIMx_ARR),它用于存儲與計數器(TIMx_CNT)進行比較的目標值。
4. 輸入捕獲單元
輸入捕獲單元主要由以下幾部分組成:輸入通道、輸入濾波器和邊沿檢測器、輸入捕獲通道、預分頻器以及捕獲/比較寄存器。
在輸入捕獲模式下,當ICx輸入信號檢測到設定的跳變沿時,計數器的當前值會被鎖存到捕獲/比較寄存器(TIMx_CCRx)。每次捕獲事件發生時,相應的捕獲標志位CCxIF(位于TIMx_SR寄存器中)被置1,并可觸發中斷或DMA請求。
ICx輸入信號經過預分頻器處理,根據TIMx_CCMRx寄存器中的ICxPSC位設置預分頻系數,決定每多少個事件進行一次捕獲。若需捕獲每個邊沿,則預分頻系數應設為1。首次捕獲時,計數器CNT的值被鎖存到CCR寄存器并產生中斷,CCxIF標志被置位;若CCR已有值且CCxIF已置1,則發生第二次捕獲時,捕獲溢出標志位CCxOF會被置位,該標志只能通過軟件寫0清零。
5. 輸出比較通道
通用定時器通常配備有多個輸出通道(TIMx_CH1/2/3/4),這些通道對應于STM32微控制器上的物理引腳。每個輸出通道可以獨立配置為不同的功能,如輸出比較、PWM生成等。
輸出比較單元與輸入捕獲單元共享捕獲/比較寄存器(TIMx_CCRx)。然而,在輸出比較模式下,這些寄存器主要發揮其比較功能的作用。當計數器CNT的值與比較寄存器CCR的值相等時,輸出參考信號OCxREF的極性會發生改變,并且會產生一個比較中斷CCxI。此時,相應的標志位CCxIF(位于SR寄存器中)會被置位。
在發生比較匹配事件后,OCxREF信號經過一系列控制處理,最終轉換為實際的輸出信號OC1/2/3/4。這些輸出信號會通過對應的管腳TIMx_CH1/2/3/4輸出到外部設備。
三、PWM簡介
什么是PWM?
PWM是 Pulse Width Modulation 的縮寫,中文意思就是脈沖寬度調制,簡稱脈寬度調制,其核心思想是通過快速開關數字信號并改變其開啟時間(脈寬)的比例來控制輸送到負載的平均功率或電壓,即控制占空比。
它是利用微處理器的數字輸出來對模擬電路進行控制的一種非常有效的技術,其控制簡單、靈活和動態響應好等優點而成為電力電子技術最廣泛應用的控制方式,其應用領域包括測量,通信,功率控制與變換,電動機控制、伺服控制、調光、開關電源,甚至某些音頻放大器,因此學習PWM具有十分重要的現實意義。
- PWM 信號是一個周期性的方波(高電平-低電平交替)。
- 占空比 是一個周期內高電平(脈沖開啟)時間占整個周期時間的百分比。
- 公式:占空比 = (脈沖開啟時間 / 周期時間) × 100%
- 例如:一個周期為 10ms 的 PWM 信號,如果高電平持續 3ms,則占空比為 30%;如果高電平持續 7ms,則占空比為 70%。
與模擬控制的區別
- 傳統的模擬控制(如使用可變電阻)是通過連續地改變電壓或電流的大小來控制負載。
- PWM 控制是通過改變數字脈沖的寬度比例來達到類似的連續控制效果。它是數字式的開關控制,而非連續的模擬調節。
- PWM 控制本質上改變的是負載兩端的 平均電壓?和流經負載的 平均電流,而不是瞬時電壓或電流的峰值
通用定時器的PWM模式
PWM(脈沖寬度調制)模式是輸出比較模式的一種特例,專門用于生成具有特定頻率和占空比的PWM波形。它可以配置為PWM1模式或PWM2模式,適用于電機控制、LED亮度調節等多種應用。
PWM1模式:當計數器CNT的值小于比較寄存器CCR的值時,輸出高電平;反之,輸出低電平。這使得輸出信號的占空比由CCR值決定。
PWM2模式:與PWM1模式相反,當計數器CNT的值小于比較寄存器CCR的值時,輸出低電平;反之,輸出高電平。
通過調整計數器的自動重裝載值(TIMx_ARR)和比較寄存器(TIMx_CCRx)的值,可以精確控制PWM信號的周期和占空比。
四、代碼實現定時器輸出PWM脈沖
本實驗使用通用定時器TIM3的通道1來輸出PWM脈沖,TIM3的輸出通道1是映射在GPIO引腳PA6上,并在PA6引腳接一個LED燈。我們通過控制PWM占空比,實現呼吸燈的效果。(燈的亮度由亮到暗,再由暗到亮)
1.配置步驟
- 使能外設TIM3、GPIOA時鐘
- 初始GPIO
- 初始化定時器,配置定時器的時基單元和輸出通道部分
- 使能定時器
- 使能輸出比較預裝載寄存器
- 使能自動重裝載預裝載寄存器
- 設置比較寄存器的值
2.代碼實現
編寫tim_drv.c文件
#include "tim_drv.h"/*********************************************************************************** @brief : 定時器PWM輸出配置函數* * @param : arr 自動重裝載值* @param : psc 預分頻系數* @retval : 無
**********************************************************************************/
void PWM_Config(uint16_t arr, uint16_t psc)
{//開啟外設GPIO時鐘 復用時鐘AFIO 定時器TIM3時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//GPIO初始化GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6; //引腳6GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//復用推挽輸出GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//速率GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化定時器TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //時鐘分割TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //向上計數模式TIM_TimeBaseInitStruct.TIM_Period = arr; //自動重裝載值TIM_TimeBaseInitStruct.TIM_Prescaler = psc; //預分頻系數TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);//輸出比較通道參數初始化TIM_OCInitTypeDef TIM_OCInitStruct;TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; //PWM1模式TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_Low; //有效電平為低電平TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; //輸出使能TIM_OCInitStruct.TIM_Pulse = 0; //初始占空比為0(整個計數周期PWM波形為高電平)TIM_OC1Init(TIM3,&TIM_OCInitStruct);//使能輸出比較預裝載寄存器TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能自動重裝載預裝載寄存器TIM_ARRPreloadConfig(TIM3,ENABLE);//使能定時器TIM_Cmd(TIM3,ENABLE);
}
編寫tim_drv.h文件
#ifndef __TIM_DRV_H__
#define __TIM_DRV_H__//頭文件包含
#include "stm32f10x.h"//函數聲明
void PWM_Config(uint16_t arr, uint16_t psc);#endif
編寫main.c文件
#include "led_drv.h"
#include "systick.h"
#include "tim_drv.h"int main(void)
{uint8_t dir=0;uint16_t ccr = 0;SysTick_Init(72);//初始化systickPWM_Config(100-1,720-1);//初始化LEDwhile (1){if(!dir){ccr++;if(ccr >= 500)dir = 1;}else{ccr--;if(ccr <= 0)dir =0;}TIM_SetCompare1(TIM3,ccr);delay_ms(5);}
}