STM32F103單片機定時器自帶互補PWM波形輸出功能,利用定時器輸出比較模式,不僅可以輸出互補的 PWM波,還可以設置輸出方波的起始相位和死區時間。
下面就總結一下如何實現PWM互補輸出。
void TIM1_PWM_DeadtimeInit( u16 arr, u16 psc, u16 ccr1, u16 ccr2, u16 deadtime )
{
GPIO_InitTypeDef GPIO_InitSturcture;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE );
RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
//TIM1 互補PWM CH1->PA8 CH2->PA9 CH1N->PB13 CH2N->PB14
GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitSturcture );
GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitSturcture );
//定時器設置
TIM_TimeBaseInitStructure.TIM_Period = arr;
TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x00;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0x00;
TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure );
//通道1 捕獲比較模式設置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; //翻轉,當 TIMx_CCR1=TIMx_CNT時,翻轉OC1REF的電平
TIM_OCInitStructure.TIM_Pulse = ccr1; //100
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //CCER的CC1P,輸入/捕獲輸出極性
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //CER的CC1N,輸入/捕獲輸出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; //OIS1位
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; //CR2的OIS1N位,當MOE位0時,輸出空閒狀態位OIS1N.
TIM_OC1Init( TIM1, &TIM_OCInitStructure );
//通道2 設置
TIM_OCInitStructure.TIM_Pulse = ccr2; //316
TIM_OC2Init( TIM1, &TIM_OCInitStructure );
//剎車和死區設置
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; //OSSR:運行模式下“關閉狀態”選擇
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; //OSSI:空閒模式下“關閉狀態”選擇
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; //鎖定設 置,級別爲1
TIM_BDTRInitStructure.TIM_DeadTime = deadtime; //死區延時時間
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable; //禁止剎車輸 入
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low; //剎車輸入極性
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; //自動輸出使能
TIM_BDTRConfig( TIM1, &TIM_BDTRInitStructure );
TIM_CtrlPWMOutputs( TIM1, ENABLE );
TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Enable );
TIM_OC2PreloadConfig( TIM1, TIM_OCPreload_Enable );
TIM_ARRPreloadConfig( TIM1, ENABLE );
TIM_Cmd( TIM1, ENABLE );
}
首先初始化IO口,這裏使用的是定時器1的通道1和通道2。
PA8爲定時器1通道1輸出口,PB13爲定時器1通道1互補輸出口。
PA9爲定時器1通道2輸出口, PB14爲定時器1通道2互補輸出口。
下來初始化定時器,參數arr設置輸出PWM波頻率,psc設置定時器時鐘分頻係數。定時器初始化之後,設置定時器工作模式爲輸出比較模式,其中參數 ccr1 設置通道1的輸出方波起始相位,參數cc2設置通道2輸出方波起始相位。參數 deadtime 設置互補PWM波形的死區時間。初始化結束後啓動定時器。
關於輸出比較模式的詳細說明參考STM32輸出比較模式和PWM模式 比較這篇文章。
下面看主函數設置
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "pwm_ch_chn.h"
// LED0 PA8 LED1 PD2
int main(void)
{
delay_init(); //延時函數初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
LED_Init();
LED0 = 1;
LED1 = 1;
delay_ms(500);
LED0 = 0;
LED1 = 0;
// Tout=(719+1)*(0+1)/72M=10us 72M/720=0.1M=100K
TIM1_PWM_DeadtimeInit(719,0,0,0,72);//50KHz
while(1)
{
}
}
主函數中設置自動裝載值爲 720,分頻係數爲0,那麼輸出方波頻率爲 72MHz / 720 = 0.1MHz,也就是輸出波形頻率爲100K,由於此處用的是定時器的輸出比較模式,所以輸出頻率爲計算值的一半,所以實際輸出方波頻率爲50KHz。ccr1值設置爲0,也就是定時器1通道1的輸出波形起始相位爲0,ccr2的值爲0,所以起始相位也爲0。死區時間設置爲72,爲週期數的1/10,也就是2us。
下面看一下輸出波形
黃色爲 TIM1_CH1波形,綠色爲TIM1_CH1N波形,這兩個波形是通道1互補波形。
藍色爲 TIM1_CH2波形,粉色爲TIM1_CH2N波形,這兩個波形是通道2互補波形。
黃色和藍色波形起始相位相同。
原波形和互補波形死區時間爲1us,剛纔計算的死區時間是2us,這裏爲什麼是1us?因爲死區時間是上升沿時間差+下降沿時間差,是兩個對稱的區間。這裏只測了一個區間,所以爲總時間的一半。
下來同時改變ccr1和ccr2的初始值,看看輸出波形相位有沒有發生變化。
TIM1_PWM_DeadtimeInit(719,0,72,144,72);//50KHz
輸出波形爲
藍色波形下降沿比黃色波形下降沿滯後了一點,說明起始相位已經發生了改變。
放大波形後可以看到,下降沿滯後的時間爲1us,和死區時間相同。