硬件:Stm32f103c8t6最小系統。
開發平臺:MDK-Arm。
目的:使用Stm32高級定時器TIM1。配置中心對齊模式輸出三路互補PWM。
(1)Stm32的高級定時器:
Stm32f103c8t6有一個高級定時器TIM1。STM32的高級定時器比通用定時器增加了可編程死區互補輸出,重復計數器,帶剎車(短路)功能。這些功能為電機控制提供了便利。其中重復計數器下篇文章單獨講。
TIM1的IO分配:
(2)高級定時器框圖分析:
圖1
圖1高級定時器框圖,可分為6部分,①時鐘源選擇,②控制器,③時基單元,④輸入捕獲,⑤輸出比較,⑥剎車斷路。
①時鐘選擇:
時鐘源有:內部時鐘(CK_INT),外部時鐘模式1,外部時鐘模式2,內部觸發輸入(ITRx)。具體可以看TIMx_SMCR寄存器SMS位和ECE位這里我們使用內部時鐘64MHz(沒使用外部晶振,系統時鐘是64MHz)。
②控制器
控制器部分包含觸發控制器,從模式控制器,編碼器接口。觸發控制器可以為片內外設提供觸發信號。
③⑤時基單元和輸出比較
時基單元的計數模式選中心對齊模式和比較輸出的比較模式選PWM模式來講解。
首先時鐘源通過預分頻寄存器PSC分頻得到CK_CNT,得到計數器CNT計數頻率,計數器開始從0向上計數,每計一次,和CCR比較一次,當CRR>CNT, 輸出高電平,反之輸出低電平,計數器CNT繼續計數,當計數器等于ARR值時,計數器向下計數,當計數器CNT>CCR時,輸出低電平,反之輸出高電平。計數器周而復始向上向下計數并不斷的和CRR值比較,參考圖2。
圖2
實際此過程我們可以看成一個比較器,CRR作為參考電壓,接到比較器同相輸入端,CNT作為信號電壓,接到比較器反相輸入端,這樣根據比較輸出PWM。反之把CNT和CRR調換位置,會輸出相反極性的PWM,參考圖2.
計數器計數模式有:向上計數,向下計數,中心對齊計數。
比較輸出比較模式:凍結,匹配時設置通道x為有效電平,匹配時設置通道x為無效電平,翻轉,強制為無效電平,強制為有效電平,PWM1,PWM2。
死區發生器:
通過寄存器BDTR的位UTG[7:0]來配置死區時間,關于死區時間設置可以這篇文章:
⑥短路功能
斷路功能用于電控的剎車功能,可以通過寄存器BDTR的BKE位使能斷路功能,BKP位設置斷路輸入引腳的有效電平
④輸入捕獲
輸入捕獲可以對輸入的信號的上升沿,下降沿或者雙邊沿進行捕獲,常用的有測量輸 入信號的脈寬和測量 PWM 輸入信號的頻率和占空比這兩種。
輸入捕獲的大概的原理就是,當捕獲到信號的跳變沿的時候,把計數器 CNT 的值鎖存 到捕獲寄存器 CCR 中,把前后兩次捕獲到的 CCR 寄存器中的值相減,就可以算出脈寬或者頻率。如果捕獲的脈寬的時間長度超過你的捕獲定時器的周期,就會發生溢出,這個我 們需要做額外的處理。
(3)程序設計
程序使用ST官方固件庫,編程步驟:
①GPIO初始化;
②時基結構體TIM_TimeBaseInitTypeDef 初始化;
③比較結構體 TIM_OCInitTypeDef 初始化;
④剎車和死區結構體 TIM_BDTRInitTypeDef 初始化。
程序分析:
①宏定義:
#define RCC_TIMGPIO_CLK RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB
#define TIM_CHxGPIO_Pinx GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11
#define TIM_CHxGPIOx GPIOA
#define TIM_CHxNGPIO_Pinx GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15
#define TIM_CHxNGPIOx GPIOB
#define TIM_BKINGPIO_Pinx GPIO_Pin_2
#define TIM_BKINGPIOx GPIOB
//TIM1 macro definition
/ PWM頻率和死區時間計算 */
//電機控制載波頻率一般配置在15-20KHz,頻率配置低了電機噪聲大,配置高了,對MOS
//管開關頻率要求高,且開關損耗大,這里載波配置為20KHz。
//計數器頻率計算CK_CNT = 64MHz/(PSC+1) = 64MHz/1=64MHz
//中心對齊PWM頻率=CK_INT/2(ARR+1)=64M/2(1599+1)=20KHz。
//死區時間配置為2us
//64M/(CKD+1)/ UTG = 500KHz,換算成時間位2us
// TIMx_CR1寄存器CKD 位,TIMx_BDTR寄存器UTG位。
#define TIMx TIM1
#define RCC_TIM_CLK RCC_APB2Periph_TIM1
#define TIM_ARR 1599
#define TIM_CK_PSC 0
#define TIM_RCR 0
#define TIM_CCRx 799
#define PWM_DeadTime 128
②GPIO初始化:
static void GPIO_TIM_Config(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_TIMGPIO_CLK, ENABLE);
//TIM1_PA8CH1 PA9CH2 PA10CH3 PA11CH4
GPIO_InitStructure.GPIO_Pin = TIM_CHxGPIO_Pinx;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PB13CH1N PB14CH2N PB15CH3N PB12BKIN
GPIO_InitStructure.GPIO_Pin = TIM_CHxNGPIO_Pinx;
GPIO_Init(TIM_CHxNGPIOx, &GPIO_InitStructure);
//PB12BKIN
GPIO_InitStructure.GPIO_Pin = TIM_BKINGPIO_Pinx;
GPIO_Init(TIM_BKINGPIOx, &GPIO_InitStructure);
GPIO_ResetBits(TIM_BKINGPIOx,TIM_BKINGPIO_Pinx);//剎車
}
③定時器時基單元,輸出比較,剎車死區初始化:
static void AdvanceTIM1_Config(void){
//開啟定時器時鐘,即內部時鐘CK_INT=64MHz
RCC_APB2PeriphClockCmd(RCC_TIM_CLK,ENABLE);
/*--------------------時基結構體初始化-------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = TIM_ARR; //自動重裝載寄存器的值,累計TIM_Period+1個頻率后產生一個更新或者中斷
TIM_TimeBaseStructure.TIM_Prescaler = TIM_CK_PSC; //驅動CNT計數器的時鐘 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //時鐘分頻因子 ,配置死區時間時需要用到
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1; //中心對齊1
TIM_TimeBaseStructure.TIM_RepetitionCounter = TIM_RCR; //重復計數器的值,沒用到不用管
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure); //初始化定時器
/*--------------------輸出比較結構體初始化-------------------*/
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM1模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //輸出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //互補輸出使能
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_OCInitStructure.TIM_Pulse = TIM_CCRx; //設置占空比大小
TIM_OC1Init(TIMx, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);
TIM_OC2Init(TIMx, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIMx, TIM_OCPreload_Enable);
TIM_OC3Init(TIMx, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIMx, 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]的描述
//這里配置的死區時間為2uS
TIM_BDTRInitStructure.TIM_DeadTime = 128;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
//當BKIN引腳檢測到高電平的時候,輸出比較信號被禁止,就好像是剎車一樣
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIMx, &TIM_BDTRInitStructure);
TIM_Cmd(TIMx, ENABLE);
//主輸出使能,當使用的是通用定時器時,這句不需要
TIM_CtrlPWMOutputs(TIMx, ENABLE);
}
(4)程序燒錄驗證:圖3是一對PWM互補輸出波形。
圖3
-
電機控制
+關注
關注
3539文章
1895瀏覽量
269125 -
PWM波
+關注
關注
0文章
99瀏覽量
16921 -
預分頻器
+關注
關注
0文章
18瀏覽量
8179 -
STM32F103C8T6
+關注
關注
109文章
162瀏覽量
83830 -
stm32定時器
+關注
關注
0文章
13瀏覽量
2301
發布評論請先 登錄
相關推薦
評論