stm32之TIM-高级定时器应用实例一(详细)
- 硬件:stm32f103c8t6
- 開發(fā)工具:Keil uVision4
- 下載調試工具:ARM仿真器
??????? 如果第一次接觸定時器,可以先看基本定時器。本篇內容較多,如果想直接動手操作,可以跳到后面的實驗代碼。
??????? stm32標準庫對定時器外設建立了4個初始化結構體,定時器分為基本定時器、通用定時器、高級定時器,針對不用的定時器要使用不同初始化結構體。下面是4個初始化結構體的適用分類:
TIM_TimeBaseInitTypeDef? (基本定時器、通用定時器、高級定時器)
TIM_OCInitTypeDef???????????? (通用定時器、高級定時器)
TIM_ICInitTypeDef?????????????? (通用定時器、高級定時器)
TIM_BDTRInitTypeDef???????? (高級定時器)
???????? 使用哪一個定時器,就配置所有相應的初始化結構體,然后調用初始化函數。下面先理解每個結構體成員的含義和其取值范圍。
定時器基本初始化結構體 >> ?TIM_TimeBaseInitTypeDef
typedef struct {uint16_t TIM_Prescaler; /*定時器預分頻設置。 value:(0~0xFFFF)*/uint16_t TIM_CounterMode;/*選擇了計數器模式。Value: #define TIM_CounterMode_Up ((uint16_t)0x0000) //TIM 向上計數模式 #define TIM_CounterMode_Down ((uint16_t)0x0010) //TIM 向下計數模式 #define TIM_CounterMode_CenterAligned1 ((uint16_t)0x0020) //TIM 中央對齊模式 1 計數模式 #define TIM_CounterMode_CenterAligned2 ((uint16_t)0x0040) //TIM 中央對齊模式 2 計數模式*/uint16_t TIM_Period; /*設置了在下一個更新事件裝入活動的自動重裝載寄存器周期的值。value:0x0000~0xFFFF*/ uint16_t TIM_ClockDivision; /*設置定時器時鐘CK_INT頻率與死區(qū)發(fā)生器以及數字濾波器采樣時鐘頻率分頻化。Value: #define TIM_CKD_DIV1 ((uint16_t)0x0000) #define TIM_CKD_DIV2 ((uint16_t)0x0100) #define TIM_CKD_DIV4 ((uint16_t)0x0200)*/ uint8_t TIM_RepetitionCounter; /*是否使用重復定時器,當該值不為0的時候,計數器計數值達到周期數時,該值減1,計數器重新計數,當該值減到0的時候才會產生事件。*/ } TIM_TimeBaseInitTypeDef;備注: 若是主頻72MHz、TIM_Prescaler的值設置為(72-1),則定時器時鐘頻率=72MHz/72=1MHz。知道頻率就可以算周期了,用1/1MHz 乘以TIM_Period的值就是定時的時間(周期),如果加入了重復定時器,那么還要乘以TIM_RepetitionCounter的值才是定時的時間(周期)。
定時器比較輸出初始化結構體 >> TIM_OCInitTypeDef
typedef struct {uint16_t TIM_OCMode;/*比較輸出模式選擇,共8種。value: #define TIM_OCMode_Timing ((uint16_t)0x0000) // TIM 輸出比較時間模式 #define TIM_OCMode_Active ((uint16_t)0x0010) //TIM 輸出比較主動模式 #define TIM_OCMode_Inactive ((uint16_t)0x0020) //TIM 輸出比較非主動模式 #define TIM_OCMode_Toggle ((uint16_t)0x0030) //TIM 輸出比較觸發(fā)模式 #define TIM_OCMode_PWM1 ((uint16_t)0x0060) //TIM 脈沖寬度調制模式 1 #define TIM_OCMode_PWM2 ((uint16_t)0x0070) //TIM 脈沖寬度調制模式 2*/ uint16_t TIM_OutputState;/*比較輸出使能,決定信號是否通過外部引腳輸出。value:0(Disable)、1(Enable)。 */ uint16_t TIM_OutputNState; /*比較互補輸出使能,決定互補信號是否通過外部引腳輸出。value:0(Disable)、1(Enable)。*/uint16_t TIM_Pulse; /*比較輸出的脈沖寬度,設置占空比。Value:0x0000~0xFFFF*/ uint16_t TIM_OCPolarity; /*比較輸出極性,決定定時器通道有效電平的極性。Value: #define TIM_OCPolarity_High ((uint16_t)0x0000) #define TIM_OCPolarity_Low ((uint16_t)0x0002)*/uint16_t TIM_OCNPolarity; /*比較互補輸出極性,可選高電平有效、低電平有效。Value: #define TIM_OCNPolarity_High ((uint16_t)0x0000) #define TIM_OCNPolarity_Low ((uint16_t)0x0008)*/uint16_t TIM_OCIdleState; /*空閑狀態(tài)時通道輸出電平設置,可選高電平、低電平。Value: #define TIM_OCNPolarity_High ((uint16_t)0x0000) #define TIM_OCNPolarity_Low ((uint16_t)0x0008)*/uint16_t TIM_OCNIdleState; /*空閑狀態(tài)時互補通道輸出電平設置,可選高電平、低電平,設定值必須跟TIM_OCIdleState相反。Value: #define TIM_OCNIdleState_Set ((uint16_t)0x0200) #define TIM_OCNIdleState_Reset ((uint16_t)0x0000)*/} TIM_OCInitTypeDef;備注:設置TIM_Pulse的值就可以改變輸出波形的占空比了,如果不使用重復定時器,那么占空比=(TIM_Pulse+1)/(TIM_Period+1)x100%。
定時器輸入捕獲初始化結構體? >> TIM_ICInitTypeDef
typedef struct {uint16_t TIM_Channel; /*輸入通道選擇,共4個通道。Value: #define TIM_Channel_1 ((uint16_t)0x0000) //使用 TIM 通道 1 #define TIM_Channel_2 ((uint16_t)0x0004) //使用 TIM 通道 2 #define TIM_Channel_3 ((uint16_t)0x0008) //使用 TIM 通道 3 #define TIM_Channel_4 ((uint16_t)0x000C) //使用 TIM 通道 4*/ uint16_t TIM_ICPolarity; /*輸入捕獲邊沿觸發(fā)選擇,可選上升沿觸發(fā)、下降沿觸發(fā)。Value: #define TIM_ICPolarity_Rising ((uint16_t)0x0000) //TIM 輸入捕獲上升沿 #define TIM_ICPolarity_Falling ((uint16_t)0x0002) //TIM 輸入捕獲下降沿*/uint16_t TIM_ICSelection; /*輸入通道選擇,共3個通道。Value: #define TIM_ICSelection_DirectTI ((uint16_t)0x0001) //TIM 輸入 2,3 或 4 選擇對應地與 IC1 或 IC2 或IC3 或 IC4 相連 #define TIM_ICSelection_IndirectTI ((uint16_t)0x0002) //TIM 輸入 2,3 或 4 選擇對應地與 IC2 或 IC1 或IC4 或 IC3 相連 #define TIM_ICSelection_TRC ((uint16_t)0x0003) //TIM 輸入 2,3 或 4 選擇與 TRC 相連*/uint16_t TIM_ICPrescaler; /*輸入捕獲通道預分頻,共(1、2、4、8)種。Value: #define TIM_ICPSC_DIV1 ((uint16_t)0x0000) //TIM 捕獲在捕獲輸入上每探測到一個邊沿執(zhí)行一次 #define TIM_ICPSC_DIV2 ((uint16_t)0x0004) // TIM 捕獲每 2 個事件執(zhí)行一次 #define TIM_ICPSC_DIV4 ((uint16_t)0x0008) //TIM 捕獲每 4 個事件執(zhí)行一次 #define TIM_ICPSC_DIV8 ((uint16_t)0x000C) //TIM 捕獲每 8 個事件執(zhí)行一次*/uint16_t TIM_ICFilter; /*輸入捕獲濾波器設置,value:0x0~0x0F。一般不用,設置為0*/ } TIM_ICInitTypeDef;備注:定時器捕獲信號,可以測量輸入信號的脈寬和測量PWM輸入信號的頻率和占空比;信號的來源可以來自其他的定時器或者外部引腳;濾波器的作用是排除高頻的干擾,采樣的頻率必須大于等于兩倍的輸入信號。
斷路和死區(qū)初始化結構體? >>TIM_BDTRInitTypeDef
typedef struct {uint16_t TIM_OSSRState;/*運行模式下關閉狀態(tài)選擇。Value: #define TIM_OSSRState_Enable ((uint16_t)0x0800) #define TIM_OSSRState_Disable ((uint16_t)0x0000)*/ uint16_t TIM_OSSIState;/*空閑模式下關閉狀態(tài)選擇。Value: #define TIM_OSSIState_Enable ((uint16_t)0x0400) #define TIM_OSSIState_Disable ((uint16_t)0x0000)*/ uint16_t TIM_LOCKLevel;/*鎖定配置。Value: #define TIM_LOCKLevel_OFF ((uint16_t)0x0000) #define TIM_LOCKLevel_1 ((uint16_t)0x0100) #define TIM_LOCKLevel_2 ((uint16_t)0x0200) #define TIM_LOCKLevel_3 ((uint16_t)0x0300)*/ uint16_t TIM_DeadTime;/*死區(qū)時間。Vlaue:0x0~0xFF*/uint16_t TIM_Break;/*短路輸入使能控制。Value: #define TIM_Break_Enable ((uint16_t)0x1000) #define TIM_Break_Disable ((uint16_t)0x0000)*/ uint16_t TIM_BreakPolarity;/*斷路輸出極性。Value: #define TIM_BreakPolarity_Low ((uint16_t)0x0000) #define TIM_BreakPolarity_High ((uint16_t)0x2000)*/ uint16_t TIM_AutomaticOutput;/*自動輸出使能。Value: #define TIM_AutomaticOutput_Enable ((uint16_t)0x4000) #define TIM_AutomaticOutput_Disable ((uint16_t)0x0000)*/} TIM_BDTRInitTypeDef;備注:
??????? 上圖的黑影部分是死區(qū)時間,死區(qū)時間是根據與輸出信號相連接的器件及其特性來調整的,為了避免OCx和OCxN同時改變時,造成外部器來不及反應所造成的短路問題。
下面通過幾個實例,進一步理解初始化結構體成員的含義,熟悉定時器的使用的流程。
實驗一.PWM互補輸出實驗(帶死區(qū)和斷路功能)
一. 設計要求:
雙通道互補PWM,帶死區(qū)和剎車功能。
周期:100ms
占空比:通道一為25%,通道二為60%
死區(qū)持續(xù)時間:12.8ms??
二. 硬件設計:
?采用TIM1的通道一和通道二。
??????? PA8、PB13引腳是TIM1通道一的互補輸出。PA9、PB14引腳是TIM1通道二的互補輸出。為增加斷路功能,需要用到TIM1_BKIN引腳,PB12。
三. 設計步驟:
>>死區(qū)持續(xù)時間的計算:
??????? TIM_DeadTime的就是配置寄存器DTG[7:0]的值,是定時器時鐘,是死區(qū)發(fā)生器的時鐘,DT是死區(qū)持續(xù)時間。
本實驗定時器時鐘配置為10kHz,死區(qū)持續(xù)時間需要配置成12.8ms,我這里選用第二條公式,具體選用那一條公式,由DTG[7:5]這幾個bit位決定,如上圖。
根據公式? DTG[7:5]=10x => DT=(64+DTG[5:0]) × Tdtg,Tdtg = 2 × TDTS
那么先計算 =2=2*(1/10kHz)=0.2ms
把參數代入公式 DT=(64+DTG[5:0]) × Tdtg,可算出DTG[5:0]=0,即DTG[7:0]=0x80.
創(chuàng)建TIM_test.h
#ifndef __TIM_TEST_H #define __TIM_TEST_H #include "stm32f10x.h"void GPIO_Configuration(void); void TIME_Configuration(void);#endif創(chuàng)建TIM_test.c
void GPIO_Configuration(void) {/*定義一個GPIO_InitTypeDef類型的結構體*/GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA| \ RCC_APB2Periph_GPIOC, ENABLE);//開啟GPIOC的外設時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //設置引腳模式為通用推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;GPIO_Init(GPIOB, &GPIO_InitStructure); //調用庫函數,初始化GPIOCGPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;GPIO_Init(GPIOA, &GPIO_InitStructure); //調用庫函數,初始化GPIOCGPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_Init(GPIOB, &GPIO_InitStructure); //調用庫函數,初始化GPIOCGPIO_SetBits(GPIOB,GPIO_Pin_12); }#define ADVANCE_TIM TIM1void TIME_Configuration(void) {TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;TIM_BDTRInitTypeDef TIM_BDTRInitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //開啟TIM1時鐘//時基結構體配置TIM_TimeBaseStructure.TIM_Period = 1000-1; //從0開始計數 一個周期1000次TIM_TimeBaseStructure.TIM_Prescaler =(7200-1); //計數器頻率為10kHz 定時器時鐘:72MHz/7200=10kHz 周期:(1/10kHz)*1000=100msTIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //不需要分頻TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //計數方式 向上計數TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //重復計數器TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure); //調用庫函數,初始化TIM1//輸出比較結構體配置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;//初始化TIM1的通道一TIM_OCInitStructure.TIM_Pulse = 250-1; //占空比=250/1000=25%TIM_OC1Init(ADVANCE_TIM,&TIM_OCInitStructure);TIM_OC1PreloadConfig(ADVANCE_TIM,TIM_OCPreload_Enable);//初始化TIM1通道二TIM_OCInitStructure.TIM_Pulse = 600-1; //占空比=600/1000=60%TIM_OC2Init(ADVANCE_TIM,&TIM_OCInitStructure);TIM_OC2PreloadConfig(ADVANCE_TIM,TIM_OCPreload_Enable);//死區(qū)和短路結構體配置TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;TIM_BDTRInitStructure.TIM_DeadTime = 0x80;TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;//低電平有效,如果引腳檢測到高電平則會停止PWM的輸出,不會產生任何波形TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;TIM_BDTRConfig(ADVANCE_TIM,&TIM_BDTRInitStructure);//使能定時器,計數器開始計數TIM_Cmd(ADVANCE_TIM, ENABLE); //主動輸出使能TIM_CtrlPWMOutputs(ADVANCE_TIM,ENABLE); }創(chuàng)建main.c
#include "stm32f10x.h" #include “TIM_test.h”int main(void) { GPIO_Configuration(); //IO口配置TIME_Configuration(); //定時器配置while(1){} }四. 實驗結果:
?????? 把程序編譯燒錄到開發(fā)板里面出,再將PA8,PB13引腳和PA9,PB14引腳接到示波器,并把短路輸入引腳PB12拉低,示波器和開發(fā)板共地。也可以先在keil里面進行軟件仿真。用keil4 模擬仿真顯示引腳波形輸出分析的步驟
軟件仿真:
周期:100ms
死區(qū)持續(xù)時間:12.8ms
占空比(通道一):25%
占空比(通道二):60%
硬件調試:
信號1接的是PB13引腳,信號2接的是PA8引腳,調整示波器到合適的參數。
?????? 調試短路功能可以將PB12引腳處接高電平,那么定時器就會停止產生波形,以達到剎車的功能。高級定時器的PWM輸出的功能特性天生就是用來控制電機的。
?????? 一個高級定時器可以輸出多路PWM,但是他們的周期是一樣的,占空比可以不一樣,在運行過程中每個通道的占空比是可以通過調用函數來改變。通用定時器跟高級定時器的區(qū)別是前者沒有死區(qū)和斷路功能,其他都是一樣。
水平有限,僅供參考,錯誤之處以及不足之處還望多多指教。
?
?
總結
以上是生活随笔為你收集整理的stm32之TIM-高级定时器应用实例一(详细)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt小游戏《2048》源码(含大量注释)
- 下一篇: 用keil4 模拟仿真显示引脚波形输出分