stm32 PWM互补输出
stm32高級定時器例子—stm32 PWM互補輸出
定時器初始化結構體
TIM_TimeBaseInitTypeDef
時基結構體,用于定時器基礎參數設置,與TIM_TimeBaseInit函數配合使用,完成配置。
typedef struct { TIM_Prescaler /*定時器預分頻器設置,時鐘源經該預分頻器才是定時器計 數時鐘CK_CNT,它設定PSC寄存器的值。計數器時鐘頻率 (fCK_CNT) 等于fCK_PSC/(PSC[15:0]+1),可實現1至65536分頻。*/ TIM_CounterMode /*定時器計數方式,可設置為向上計數、向下計數、中心對齊*/ TIM_Period /*定時器周期,設定自動重載寄存器ARR的值可設置范圍為0至65535*/ TIM_ClockDivision /*時鐘分頻,設置定時器時鐘CK_INT頻率與死區發生器以及數字濾波器采樣時鐘頻率分頻比。可以選擇 1、2、4 分頻。*/ TIM_RepetitionCounter /*重復計數器,只有 8 位,只存在于高級定時器*/ }TIM_TimeBaseInitTypeDef;TIM_OCInitTypeDef
輸出比較結構體,用于輸出比較模式。與TIM_OCxInit函數配合使用,完成指定定時器輸出通道初始化配置。
typedef struct {uint16_t TIM_OCMode; /*比較輸出模式選擇,共有八種。常用的為 PWM1/PWM2。設定CCMRx寄存器OCxM[2:0]位的值*/uint16_t TIM_OutputState; /*比較輸出使能,決定最終的輸出比較信號OCx是否通過外部引腳輸出。設定TIMx_CCER寄存器CCxE/CCxNE位的值。*/uint16_t TIM_OutputNState; /*比較互補輸出使能,決定OCx的互補信號OCxN是否通過外部引腳輸出。設定CCER寄存器CCxNE位的值*/uint16_t TIM_Pulse; /*比較輸出脈沖寬度,設定比較寄存器CCR的值,決定脈沖寬度。可設置范圍為0至65535。*/uint16_t TIM_OCPolarity; /*比較輸出極性,可選OCx為高電平有效或低電平有效。決定定時器通道有效電平。設定CCER寄存器的CCxP位的值*/uint16_t TIM_OCNPolarity; /*比較互補輸出極性,可選OCxN為高電平有效或低電平有效。設定TIMx_CCER寄存器的CCxNP位的值。*/uint16_t TIM_OCIdleState; /*空閑狀態時,通道輸出電平設置,可選輸出1或輸出0,即在空閑狀態(BDTR_MOE位為0)時,經過死區時間后定時器通道輸出高電平或低電平。設定CR2寄存器的OISx位的值*/uint16_t TIM_OCNIdleState; /*空閑狀態時互補通道輸出電平設置,可選輸出1或輸出0,即在空閑狀態(BDTR_MOE位為0)時,經過死區時間后定時器互補通道輸出高電平或低電平,設定值必須與TIM_OCIdleState相反。設定CR2寄存器的OISxN位的值。*/ } TIM_OCInitTypeDef;TIM_ICInitTypeDef
輸入捕獲結構體,用于輸入捕獲模式。
與TIM_ICInit函數配合使用,完成定時器輸入通道初始化配置。
如果使用PWM輸入模式,與TIM_PWMIConfig函數配合使用,完成定時器輸入通道初始化配置。
typedef struct {uint16_t TIM_Channel; /*捕獲通道ICx選擇,可選TIM_Channel_1、2、3、4四個通道。設定CCMRx寄存器CCxS位的值*/uint16_t TIM_ICPolarity; /*輸入捕獲邊沿觸發選擇,可選上升沿觸發、下降沿觸發、邊沿跳變觸發。設定CCER寄存器CCxP位和CCxNP位的值。*/ uint16_t TIM_ICSelection; /*輸入通道選擇,捕獲通道ICx的信號可來自三個輸入通道,分別為TIM_ICSelection_DirectTI、TIM_ICSelection_IndirectTITIM_ICSelection_TRC普通的輸入捕獲,4個通道都可以使用,PWM輸入,只能使用通道1和通道2。設定CCRMx寄存器的CCxS[1:0]位的值*/uint16_t TIM_ICPrescaler; /*輸入捕獲通道預分頻器,可設置1、2、4、8分頻,設定CCMRx寄存器的ICxPSC[1:0]位的值。如果需捕獲輸入信號的每個有效邊沿,則設置1分頻。*/uint16_t TIM_ICFilter; /*輸入捕獲濾波器設置,可設置0x0至0x0F。設定CCMRx寄存器ICxF[3:0]位的值。一般不使用濾波器,設置為0*/ } TIM_ICInitTypeDef;關于捕獲通道ICx的信號可來自三個輸入通道:
TIM_BDTRInitTypeDef
斷路和死區結構體,用于斷路和死區參數的設置,高級定時器專用。
用于配置斷路時,通道輸出狀態、死區時間。
與TIM_BDTRConfig函數配置使用,完成參數配置。
這個結構體的成員只對應BDTR寄存器。
typedef struct {uint16_t TIM_OSSRState; /*運行模式下的關閉狀態選擇,設定BDTR寄存器OSSR位的值*/uint16_t TIM_OSSIState; /*空閑模式下的關閉狀態選擇,設定BDTR寄存器OSSI位的值。*/ uint16_t TIM_LOCKLevel; /*鎖定級別配置, 設定BDTR寄存器LOCK[1:0]位的值*/ uint16_t TIM_DeadTime; /*配置死區發生器,定義死區持續時間,可選設置范圍為0x0至0xFF。設定BDTR寄存器DTG[7:0]位的值*/ uint16_t TIM_Break; /*斷路輸入功能選擇,可選使能或禁止。設定BDTR寄存器BKE位的值*/ uint16_t TIM_BreakPolarity; /*斷路輸入通道BRK極性選擇,可選高電平有效或低電平有效。設定BDTR寄存器BKP位的值。*/ uint16_t TIM_AutomaticOutput; /*自動輸出使能,可選使能或禁止,設定BDTR寄存器AOE位的值。*/ } TIM_BDTRInitTypeDef;PWM 互補輸出
在主輸出通道輸出波形,在互補通道輸出與主通道互補的的波形,添加斷路和死區功能。
使用高級定時器TIM1的通道1及其互補通道作為本實驗的波形輸出通道。對應PA8和PB13。
將示波器的兩個輸入通道分別與PA8和PB13引腳連接,共地,觀察波形。
增加斷路功能,用到TIM1_BKIN引腳。對應PB12引腳。
設置該引腳為高電平有效,BKIN引腳置高電平時,兩路互補的PWM輸出就被停止,像是剎車一樣。
Main函數,調用ADVANCE_TIM_Init()函數。
該函數調用ADVANCE_TIM_GPIO_Config()和ADVANCE_TIM_Mode_Config()進行定時器GPIO引腳和工作模式的初始化。
相應的GPIO引腳上可以檢測到互補輸出的PWM信號,而且帶死區時間。
程序運行的過程中,如果BKIN引腳被拉高,PWM輸出會被禁止,像是斷路或者剎車。
#include "stm32f10x.h" #include "bsp_led.h" #include "bsp_AdvanceTim.h" /*** @brief 主函數* @param 無 * @retval 無*/ int main(void) { /* 高級定時器初始化 */ADVANCE_TIM_Init();while(1){ } }修改PWM的周期和占空比,只需修改下面的ADVANCE_TIM_PERIOD、ADVANCE_TIM_PSC和ADVANCE_TIM_PULSE這三個宏即可。具體原因,看之前寫的文章—高級定時器里面的PWM輸出模式。
TIM_CLK等于72MHZ,ARR是自動重裝載寄存器的值,對應ADVANCE_TIM_PERIOD;PSC是計數器時鐘的分頻因子,對應ADVANCE_TIM_PSC。
PWM信號的頻率:F = TIM_CLK/{(ARR+1)*(PSC+1)}
計數器時鐘CK_CNT:
定時器時鐘經過PSC預分頻器后,即CK_CNT,用來驅動計數器計數。
PSC是16位的預分頻器,可以對定時器時鐘TIMxCLK進行1~65536之間的任何一個數進行分頻。CK_CNT=TIMxCLK/(PSC+1)。
ARR=8,CCR=4,CNT從0開始計數。
當CNT<CCR,OCxREF為有效的高電平,同時,比較中斷寄存器CCxIF置位。
CCR<=CNT<=ARR,OCxREF為無效的低電平。
計數器在CK_CNT的驅動下,計一個數的時間,1/(TIMxCLK/(PSC+1))=1/(CK_CNT)=(PSC+1)/TIMxCLK
計一個數的時間乘上一個波形的計數次數(ARR+1),就是整個波形的所需時間。
時間取倒數就是PWM信號的頻率。
由此可知F = TIM_CLK/{(ARR+1)*(PSC+1)}的含義。
ARR :自動重裝載寄存器的值 CLK_cnt:計數器的時鐘,等于 Fck_int / (psc+1) = 72M/(psc+1) PWM 信號的周期 T = (ARR+1) * (1/CLK_cnt) = (ARR+1)*(PSC+1) / 72M 占空比P=CCR/(ARR+1) #ifndef __BSP_ADVANCETIME_H #define __BSP_ADVANCETIME_H#include "stm32f10x.h"/************高級定時器TIM參數定義,只限TIM1和TIM8************/ // 當使用不同的定時器的時候,對應的GPIO是不一樣的,這點要注意 // 這里我們使用高級控制定時器TIM1#define ADVANCE_TIM TIM1 #define ADVANCE_TIM_APBxClock_FUN RCC_APB2PeriphClockCmd #define ADVANCE_TIM_CLK RCC_APB2Periph_TIM1 // PWM 信號的頻率 F = TIM_CLK/{(ARR+1)*(PSC+1)} #define ADVANCE_TIM_PERIOD (8-1) #define ADVANCE_TIM_PSC (9-1) #define ADVANCE_TIM_PULSE 4#define ADVANCE_TIM_IRQ TIM1_UP_IRQn #define ADVANCE_TIM_IRQHandler TIM1_UP_IRQHandler// TIM1 輸出比較通道 #define ADVANCE_TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOA #define ADVANCE_TIM_CH1_PORT GPIOA #define ADVANCE_TIM_CH1_PIN GPIO_Pin_8// TIM1 輸出比較通道的互補通道 #define ADVANCE_TIM_CH1N_GPIO_CLK RCC_APB2Periph_GPIOB #define ADVANCE_TIM_CH1N_PORT GPIOB #define ADVANCE_TIM_CH1N_PIN GPIO_Pin_13// TIM1 輸出比較通道的剎車通道 #define ADVANCE_TIM_BKIN_GPIO_CLK RCC_APB2Periph_GPIOB #define ADVANCE_TIM_BKIN_PORT GPIOB #define ADVANCE_TIM_BKIN_PIN GPIO_Pin_12/**************************函數聲明********************************/void ADVANCE_TIM_Init(void);#endif /* __BSP_ADVANCETIME_H */ #include "bsp_AdvanceTim.h" static void ADVANCE_TIM_GPIO_Config(void) {GPIO_InitTypeDef GPIO_InitStructure;// 輸出比較通道 GPIO 初始化RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure);// 輸出比較通道互補通道 GPIO 初始化RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1N_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1N_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(ADVANCE_TIM_CH1N_PORT, &GPIO_InitStructure);// 輸出比較通道剎車通道 GPIO 初始化RCC_APB2PeriphClockCmd(ADVANCE_TIM_BKIN_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_BKIN_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(ADVANCE_TIM_BKIN_PORT, &GPIO_InitStructure);// BKIN引腳默認先輸出低電平GPIO_ResetBits(ADVANCE_TIM_BKIN_PORT,ADVANCE_TIM_BKIN_PIN); }///* // * 注意:TIM_TimeBaseInitTypeDef結構體里面有5個成員,TIM6和TIM7的寄存器里面只有 // * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的時候只需初始化這兩個成員即可, // * 另外三個成員是通用定時器和高級定時器才有. // *----------------------------------------------------------------------------- // *typedef struct // *{ TIM_Prescaler 都有 // * TIM_CounterMode TIMx,x[6,7]沒有,其他都有 // * TIM_Period 都有 // * TIM_ClockDivision TIMx,x[6,7]沒有,其他都有 // * TIM_RepetitionCounter TIMx,x[1,8,15,16,17]才有 // *}TIM_TimeBaseInitTypeDef; // *----------------------------------------------------------------------------- // *//* ---------------- PWM信號 周期和占空比的計算--------------- */ // ARR :自動重裝載寄存器的值 // CLK_cnt:計數器的時鐘,等于 Fck_int / (psc+1) = 72M/(psc+1) // PWM 信號的周期 T = (ARR+1) * (1/CLK_cnt) = (ARR+1)*(PSC+1) / 72M // 占空比P=CCR/(ARR+1)static void ADVANCE_TIM_Mode_Config(void) {// 開啟定時器時鐘,即內部時鐘CK_INT=72MADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK,ENABLE);/*--------------------時基結構體初始化-------------------------*/TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;// 自動重裝載寄存器的值,累計TIM_Period+1個頻率后產生一個更新或者中斷TIM_TimeBaseStructure.TIM_Period=ADVANCE_TIM_PERIOD; // 驅動CNT計數器的時鐘 = Fck_int/(psc+1)TIM_TimeBaseStructure.TIM_Prescaler= ADVANCE_TIM_PSC; // 時鐘分頻因子 ,配置死區時間時需要用到TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; // 計數器計數模式,設置為向上計數TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // 重復計數器的值,沒用到不用管TIM_TimeBaseStructure.TIM_RepetitionCounter=0; // 初始化定時器TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);/*--------------------輸出比較結構體初始化-------------------*/ TIM_OCInitTypeDef TIM_OCInitStructure;// 配置為PWM模式1TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;// 輸出使能TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;// 互補輸出使能TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 設置占空比大小TIM_OCInitStructure.TIM_Pulse = ADVANCE_TIM_PULSE;// 輸出通道電平極性配置TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;// 互補輸出通道電平極性配置TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;// 輸出通道空閑電平極性配置TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;// 互補輸出通道空閑電平極性配置TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;TIM_OC1Init(ADVANCE_TIM, &TIM_OCInitStructure);TIM_OC1PreloadConfig(ADVANCE_TIM, TIM_OCPreload_Enable);/*-------------------剎車和死區結構體初始化-------------------*/// 有關剎車和死區結構體的成員具體可參考BDTR寄存器的描述TIM_BDTRInitTypeDef TIM_BDTRInitStructure;TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;// 輸出比較信號死區時間配置,具體如何計算可參考 BDTR:UTG[7:0]的描述// 這里配置的死區時間為152nsTIM_BDTRInitStructure.TIM_DeadTime = 11;TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;// 當BKIN引腳檢測到高電平的時候,輸出比較信號被禁止,就好像是剎車一樣TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure);// 使能計數器TIM_Cmd(ADVANCE_TIM, ENABLE); // 主輸出使能,當使用的是通用定時器時,這句不需要TIM_CtrlPWMOutputs(ADVANCE_TIM, ENABLE); }void ADVANCE_TIM_Init(void) {ADVANCE_TIM_GPIO_Config();ADVANCE_TIM_Mode_Config(); }
目前這里沒有示波器,于是就用仿真模擬。應該是出現一路互補的帶死區時間的PWM波形。
當BKIN引腳接高電平時,PWM輸出被禁止,好像是剎車一樣。
總結
以上是生活随笔為你收集整理的stm32 PWM互补输出的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: stm32基本定时器
- 下一篇: 华润置地php面试题_长春华润置地崑崙御