STM32的TIM1之PWM互補輸出_死區時間和剎車配置
1、定時器1的PWM輸出通道
STM32高級定時器TIM1在用作PWM互補輸出時,共有4個輸出通道,其中有3個是互補輸出通道,如下:
通道1:TIM1_CH1對應PA8引腳,TIM1_CH1N對應PB13引腳;
通道2:TIM1_CH2對應PA9引腳,TIM1_CH2N對應PB14引腳;
通道3:TIM1_CH3對應PA10引腳,TIM1_CH3N對應PB15引腳;
通道4:TIM1_CH4對應PA11引腳;
STM32高級定時器TIM1的PWM剎車引腳TIM1_BKIN對應PB12引腳;
2、PWM互補輸出的意義
在使用互補輸出時,通常需要考慮死區時間,防止互補引腳控制的功率管同時而導通引起燒壞。見下圖:
如果死區Deadtime>0,則在TIM1_CH1和TIM1_CH1N輸出波形中插入“死區時間”,可防止TIM1_CH1和TIM1_CH1N控制的功率管同時導通。
3、互補輸出
如果死區Deadtime=0,則TIM1_CH1N的輸出波形是TIM1_CH1的反相;當死區時間為0,且沒有收到剎車信號時,如果TIM1_CH1輸出高電平,則TIM1_CH1N一定會輸出低電平,我們稱之為互補輸出。
4、PWM剎車
PWM剎車,就是停止PWM輸出波形。
5、PWM的“有效電平”和“無效電平”定義:
在PWM模式1中
1)、在向上計數時,一旦TIMx_CNT<TIMx_CCR1時,通道1引腳輸出“有效電平”,否則輸出“無效電平”;
2)、在向下計數時,一旦TIMx_CNT>TIMx_CCR1時,通道1引腳輸出“無效電平”(OC1REF=0),否則輸出“有效電平”(OC1REF=1)。
在PWM模式2中
1)、在向上計數時,一旦TIMx_CNT<TIMx_CCR1時,通道1引腳輸出“無效電平”,否則輸出“有效電平”;
2)、在向下計數時,一旦TIMx_CNT>TIMx_CCR1時,通道1引腳輸出“有效電平”,否則輸出“無效電平”。
6、PWM在死區期間輸出的電平
1)、若配置了死區時間,則在死區期間,通道1引腳輸出的電平和其“無效電平”保持一致。
2)、將“死區期間和無效電平期間”的TIM1_CH1和TIM1_CH1N配置輸出為低電平:
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
//TIM1_CH1引腳輸出有效電平為高電平,則在死區期間和無效電平期間均為低電平
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
// TIM1_CH1N引腳輸出有效電平為高電平,則在死區期間和無效電平期間均為低電平
3)、死區時間
? TIM_BDTRInitStructure.TIM_DeadTime = 11;
? //輸出比較信號死區時間配置,具體如何計算可參考 BDTR:DTG[7:0]的描述
? //DTG[7:5]=0xx => DT=DTG[7:0]*tdtg,這里的tdtg=tDTS.
? //DTG[7:5]=10x => DT=(64+DTG[5:0])*tdtg,這里的Tdtg=2*tDTS.
? //DTG[7:5]=110 => DT=(32+DTG[4:0])*tdtg,這里的Tdtg=8*tDTS.
? //DTG[7:5]=111 => DT=(32+DTG[4:0])*tdtg,這里的Tdtg=16*tDTS.
? //tDTS=tCKINT=1/72000000=13.8ns,11*13.8=152.7ns
? //這里配置的死區時間為152ns
7、PWM空閑電平極性配置和PWM剎車的關系
TIM1_CH1和TIM1_CH1N引腳的“空閑電平極性”指的是在“剎車”時TIM1_CH1和TIM1_CH1N引腳輸出的極性。
剎車輸出配置:
1)、TIM1_CH1和TIM1_CH1N輸出配置為互異電平,可能會導致無法剎車;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
2)、TIM1_CH1和TIM1_CH1N輸出同時配置為低電平,當剎車信號到來時,會執行有效剎車;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
3)、TIM1_CH1和TIM1_CH1N輸出同時配置為高電平,當剎車信號到來時,會執行有效剎車;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
8、TIM1之PWM程序舉例:
void TIM1_GPIO_Config(void)
{
??? GPIO_InitTypeDef GPIO_InitStructure;
/// TIM1_CH1引腳初始化///
??? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
??? //使能PA口時鐘
? GPIO_InitStructure.GPIO_Pin =? GPIO_Pin_8;
? //PA8為TIM1_CH1通道,TIM1輸出比較通道
? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
? //設置引腳為復用推挽輸出
? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
? //設置引腳的最高輸出速率為50MHz
? GPIO_Init(GPIOA, &GPIO_InitStructure);
?/// TIM1_CH1N引腳初始化///
??? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
? GPIO_InitStructure.GPIO_Pin =? GPIO_Pin_13;
? //PB13為TIM1_CH1N通道,TIM1輸出比較通道的互補通道
? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
? //設置引腳為復用推挽輸出
? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
? //設置引腳的最高輸出速率為50MHz
? GPIO_Init(GPIOB, &GPIO_InitStructure);
? //TIM1_BKIN剎車引腳初始化/
??? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
? GPIO_InitStructure.GPIO_Pin =? GPIO_Pin_12;
?? //PB12對應TIM1_BKIN,為PWM剎車引腳
? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
?? //設置引腳為浮空輸入?
? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
? //設置引腳的最高輸出速率為50MHz
? GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void TIM1_Mode_Config(void)
{
??? TIM_TimeBaseInitTypeDef? TIM_TimeBaseStructure; //時基結構體
??? TIM_OCInitTypeDef? TIM_OCInitStructure;???????? //輸出比較結構體
??? TIM_BDTRInitTypeDef TIM_BDTRInitStructure;????? //剎車結構體
??? RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
??? //使能TIM1時鐘,即內部時鐘CK_INT=72M
/*--------------------時基結構體初始化-------------------------*/
??? TIM_TimeBaseStructure.TIM_Period=(8-1);//周期ARR
//自動重裝載寄存器的值,累計(TIM_Period+1)個"分頻時鐘"后產生一個更新或者中斷
??? TIM_TimeBaseStructure.TIM_Prescaler= (9-1);
??? //TIM1時鐘分頻因子PSC
??? TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
?? ?//時鐘分頻因子 = 1,tDTS=tCKINT
??? //PWM 信號的頻率 F = TIM_CLK/{(ARR+1)*(PSC+1)}
??? //72000000/(8*9)=1000000Hz=1MHz
??? TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
??? //計數器計數模式,設置為向上計數
??? TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
??? //重復計數器的值,沒用到不用管
??? TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);//初始化定時器
??? /*--------------------輸出比較結構體初始化-------------------*/
??? TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
??? //配置為PWM模式1
??? TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
??? //PWM輸出使能
??? TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
??? //互補輸出使能
? TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
? //TIM1_CH1引腳輸出有效電平為高電平,則在死區期間和無效期間均為低電平
? TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
? //TIM1_CH1N引腳輸出有效電平為高電平,則在死區期間和無效空閑期間均為低電平
//TIM1_CH1和TIM1_CH1N輸出配置為互異電平,導致會無法剎車,死區期間的輸出電平這個設置無關/
//? TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
//剎車時,TIM1_CH1引腳為高電平
//? TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
//剎車時,互補輸出TIM1_CH1N引腳為低電平
//TIM1_CH1和TIM1_CH1N輸出同時配置為低電平,當剎車信號到來時,會執行有效剎車/
??? TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
?? ?//剎車時,TIM1_CH1引腳為低電平
??? TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
??? //剎車時,互補輸出TIM1_CH1N引腳為低電平
//TIM1_CH1和TIM1_CH1N輸出同時配置為高電平,當剎車信號到來時,會執行有效剎車/
//? TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
//剎車時,TIM1_CH1引腳為高電平
//? TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
//剎車時,TIM1_CH1N引腳為高電平
??? TIM_OCInitStructure.TIM_Pulse = (5-1); //占空比 = 4 / 8 = 50%
??? TIM_OC1Init(TIM1, &TIM_OCInitStructure);//初始化PWM輸出通道1
??? TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
??? //開啟通道1預裝載,在更新時間后才會重新裝載數值
??? /*-------------------剎車和死區結構體初始化-------------------*/
??? // 有關剎車和死區結構體的成員具體可參考BDTR寄存器的描述
? TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
? //運行模式下“關閉模式”選擇 = 1
? TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
? //空閑模式下“關閉模式”選擇 = 1
? TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
? //鎖定級別1,見參考手冊
? TIM_BDTRInitStructure.TIM_DeadTime = 11;
??? //輸出比較信號死區時間配置,具體如何計算可參考 BDTR:DTG[7:0]的描述
? //DTG[7:5]=0xx => DT=DTG[7:0]*tdtg,這里的tdtg=tDTS.
? //DTG[7:5]=10x => DT=(64+DTG[5:0])*tdtg,這里的Tdtg=2*tDTS.
? //DTG[7:5]=110 => DT=(32+DTG[4:0])*tdtg,這里的Tdtg=8*tDTS.
? //DTG[7:5]=111 => DT=(32+DTG[4:0])*tdtg,這里的Tdtg=16*tDTS.
??? //tDTS=tCKINT=1/72000000=13.8ns,11*13.8=152.7ns
??? //這里配置的死區時間為152ns
? TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;//開啟剎車功能
? TIM_BDTRInitStructure.TIM_BreakPolarity =TIM_BreakPolarity_Low;
? //PWM剎車時,輸入低電平有效,則不會產生任何PWM輸出波形
? TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
? //開啟自動輸出
? TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
??? TIM_Cmd(TIM1, ENABLE);//使能定時器,計數器開始計數??
??? TIM_CtrlPWMOutputs(TIM1, ENABLE);
??? //主輸出使能,當使用的是通用定時器時,這句不需要
}
void TIM1_PWM_Init(void)
{
??? TIM1_GPIO_Config();
??? TIM1_Mode_Config();
}
9、測試結果
PWM剎車實驗