STM32之TIM 舵機控制PWM
頻率的計算為: F = TIM_CLK/{(ARR+1)*(PSC+1)}
如果有中斷函式就要配置中斷通道中之類的
配置相應TIM通道的GPIO複用引腳
時基結構體配置
輸出比較結構體配置(pwm輸出時使用)
輸出使能
/************高階定時器 TIM 引數定義,只限 TIM1 和 TIM8************/ /************************************************************************************* PWM 訊號的頻率的計算為: F = TIM_CLK/{(ARR+1)*(PSC+1)}, 其中 TIM_CLK 等於 72MHZ TIM1 ch1輸出比較通道 TIM1 chn1輸出比較通道的互補通道 TIM1 輸出比較通道的剎車通道 當使用不同的定時器的時候,對應的 GPIO 是不一樣的,這點要注意 這裡我們使用高階控制定時器 TIM1 ************************************************************************************/ //定時器複用功能引腳初始化 /* 使用TIM1 通道 ch1 PA8 ch1n PB13 */ static void TIM1_GPIO_CH12_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; // 輸出比較通道 GPIO 初始化 // TIM1 輸出比較通道 // 輸出比較通道 GPIO 初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 輸出比較通道互補通道 GPIO 初始化 // TIM1 輸出比較通道的互補通道 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // 輸出比較通道剎車通道 GPIO 初始化 // TIM1 輸出比較通道的剎車通道 /* RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // BKIN 引腳預設先輸出低電平 GPIO_ResetBits(GPIOB,GPIO_Pin_12); */ } #define ADVANCE_TIM_PSC (720-1) //週期 分頻數PSC #define ADVANCE_TIM_PERIOD (2000-1) //計數個數ARR #define ADVANCE_TIM_PULSE 150 //佔空比 與ARR相比較 // PWM 訊號的頻率 F = TIM_CLK/{(ARR+1)*(PSC+1)} //定時器模式配置 static void TIM1_Mode_Config(void) { // 開啟定時器時鐘,即內部時鐘 CK_INT=72M RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,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(TIM1, &TIM_TimeBaseStructure); /*--------------------輸出比較結構體初始化-------------------*/ TIM_OCInitTypeDef TIM_OCInitStructure; // 配置為 PWM 模式 1 TIM_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( TIM1, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM1, 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]的描述 // 這裡配置的死區時間為 152ns TIM_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(TIM1, &TIM_BDTRInitStructure); */ // 使能計數器 TIM_Cmd(TIM1, ENABLE); // 主輸出使能,當使用的是通用定時器時,這句不需要 TIM_CtrlPWMOutputs(TIM1, ENABLE); } void Advance_TIM1_Init(void) { TIM1_GPIO_CH12_Config(); TIM1_Mode_Config(); //外面使用這個控制函式控制佔空比 //TIM_SetCompare1(TIM1 , 70); }
基本定時器 TIM6 和 TIM7 是一個 16 位的只能向上計數的定時器,只能定時,沒有外部 IO。TIM_TimeBaseInitTypeDef 結構體裡面有 5 個成員, TIM6 和 TIM7 的暫存器裡面只有TIM_Prescaler 和 TIM_Period,另外三個成員基本定時器是沒有的,所以使用 TIM6 和TIM7 的時候只需初始化這兩個成員即可
通用定時器 TIM2/3/4/5 是一個 16 位的可以向上/下計數的定時器,可以定時,可以輸出比較,可以輸入捕捉,每個定時器有四個外部 IO。
高階定時器 TIM1/8是一個 16 位的可以向上/下計數的定時器,可以定時,可以輸出比較,可以輸入捕捉,還
可以有三相電機互補輸出訊號,每個定時器有 8 個外部 IO。
STM32F103ZET6高階控制和通用定時器通道引腳分佈
高階定時器 | 通用定時器 | |||||
TIM1 | TIM8 | TIM2 | TIM5 | TIM3 | TIM4 | |
CH1 | PA8/PE9 | PC6 | PA0/PA15 | PA0 | PA6/PC6/PB4 | PB6/PD12 |
CH1N | PB13/PA7/PE8 | PA7 | ||||
CH2 | PA9/PE11 | PC7 | PA1/PB3 | PA1 | PA7/PC7/PB5 | PB7/PD13 |
CH2N | PB14/PB0/PE10 | PB0 | ||||
CH3 | PA10/PE13 |
PC8 | PA2/PB10 | PA2 | PB0/PC8 | PB8/PD14 |
CH3N | PB15/PB1/PE12 | PB1 | ||||
CH4 | PA11/PE14 | PC9 | PA3/PB11 | PA3 | PB1/PC9 | PB9/PD15 |
ETR | PA12/PE7 | PA0 | PA0/PA15 | PD2 | PE0 | |
BKIN | PB12/PA6/PE15 | PA6 |
其中高階定時器 TIM1 和 TIM8 可以同時產生多達 7 路的 PWM 輸出。而通用定時器也能同時產生多達 4路的 PWM 輸出
高階控制定時器(TIM1 和 TIM8)和通用定時器在基本定時器的基礎上引入了外部引腳,可以實現輸入捕獲和輸出比較功能。高階控制定時器比通用定時器增加了可程式設計死區互補輸出、重複計數器、帶剎車(斷路)功能,這些功能都是針對工業電機控制方面。
輸入捕獲可以對輸入的訊號的上升沿,下降沿或者雙邊沿進行捕獲,常用的有測量輸入訊號的脈寬和測量 PWM 輸入訊號的頻率和佔空比這兩種。
輸入捕獲的大概的原理就是,當捕獲到訊號的跳變沿的時候,把計數器 CNT 的值鎖存到捕獲暫存器 CCR 中,把前後兩次捕獲到的 CCR 暫存器中的值相減,就可以算出脈寬或者頻率。如果捕獲的脈寬的時間長度超過你的捕獲定時器的週期,就會發生溢位,這個我們需要做額外的處理。
輸入通道
需要被測量的訊號從定時器的外部引腳 TIMx_CH1/2/3/4 進入,通常叫 TI1/2/3/4,在後面的捕獲講解中對於要被測量的訊號我們都以 TIx 為標準叫法。
輸入濾波器和邊沿檢測器
當輸入的訊號存在高頻干擾的時候,我們需要對輸入訊號進行濾波,即進行重新取樣,根據取樣定律,取樣的頻率必須大於等於兩倍的輸入訊號。比如輸入的訊號為 1M,又存在高頻的訊號干擾,那麼此時就很有必要進行濾波,我們可以設定取樣頻率為 2M,這樣可以在保證取樣到有效訊號的基礎上把高於 2M 的高頻干擾訊號過濾掉。
捕獲通道
捕獲通道就是圖中的 IC1/2/3/4,每個捕獲通道都有相對應的捕獲暫存器 CCR1/2/3/4,
當發生捕獲的時候,計數器 CNT 的值就會被鎖存到捕獲暫存器中。
這裡我們要搞清楚輸入通道和捕獲通道的區別,輸入通道是用來輸入訊號的,捕獲通
道是用來捕獲輸入訊號的通道,一個輸入通道的訊號可以同時輸入給兩個捕獲通道。比如
輸入通道 TI1 的訊號經過濾波邊沿檢測器之後的 TI1FP1 和 TI1FP2 可以進入到捕獲通道
IC1 和 IC2,其實這就是我們後面要講的 PWM 輸入捕獲,只有一路輸入訊號(TI1)卻佔
用了兩個捕獲通道(IC1 和 IC2)。當只需要測量輸入訊號的脈寬時候,用一個捕獲通道即
可。輸入通道和捕獲通道的對映關係具體由暫存器 CCMRx 的位 CCxS[1:0]配置。
定時器初始化結構體詳解
在標準庫函式標頭檔案 stm32f4xx_tim.h 中對定時器外設建立了四個初始化結構體,分別為 時 基 初 始 化 結 構 體 TIM_TimeBaseInitTypeDef 、 輸 出 比 較 初 始 化 結 構 體TIM_OCInitTypeDef、輸入捕獲初始化結構體 TIM_ICInitTypeDef 和斷路和死區初始化結構體 TIM_BDTRInitTypeDef,高階控制定時器可以用到所有初始化結構體,通用定時器不能使用 TIM_BDTRInitTypeDef 結構體,基本定時器只能使用時基結構體。接下來我們具體講解下這四個結構體
1. TIM_TimeBaseInitTypeDef
時 基 結 構 體 TIM_TimeBaseInitTypeDef 用 於 定 時 器 基 礎 參 數 設 置 , 與TIM_TimeBaseInit 函式配合使用完成配置。
定時器基本初始化結構體
typedef struct {
uint16_t TIM_Prescaler; // 預分頻器
uint16_t TIM_CounterMode; // 計數模式
uint32_t TIM_Period; // 定時器週期
uint16_t TIM_ClockDivision; // 時鐘分頻
uint8_t TIM_RepetitionCounter; // 重複計算器
} TIM_TimeBaseInitTypeDef;
TIM_Prescaler:驅動 CNT 計數器的時鐘 = Fck_int/(psc+1)
定時器預分頻器設定,時鐘源經該預分頻器才是定時器計數時鐘CK_CNT,它設定 PSC 暫存器的值。計算公式為: 計數器時鐘頻率 (fCK_CNT) 等於fCK_PSC / (PSC[15:0] + 1),可實現 1 至 65536 分頻。
TIM_CounterMode:設定計數模式
定時器計數方式,可設定為向上計數、向下計數以及中心對齊。高階控制定時器允許選擇任意一種。
TIM_Period:定時器週期,自動重灌載暫存器的值,累計 TIM_Period+1 個頻率後產生一個更新或者中斷
實際就是設定自動過載暫存器 ARR 的值, ARR 為要裝載到實際自動過載暫存器(即影子暫存器) 的值, 可設定範圍為 0 至 65535。
TIM_ClockDivision:時鐘分頻
設定定時器時鐘 CK_INT 頻率與死區發生器以及數字濾波器取樣時鐘頻率分頻比。可以選擇 1、 2、 4 分頻。
TIM_RepetitionCounter:重複計數器的值
重複計數器,只有 8 位,只存在於高階定時器。在開啟了 TIM1 的時鐘之後,我們要設定 ARR (TIM_Period)和 PSC (TIM_Prescaler)兩個暫存器的值來控制輸出 PWM 的週期。
TIM_OCInitTypeDef
輸出比較結構體 TIM_OCInitTypeDef 用於輸出比較模式,與 TIM_OCxInit 函式配合使用完成指定定時器輸出通道初始化配置。高階控制定時器有四個定時器通道,使用時都必須單獨設定。 PWM 通道設定是通過函式 TIM_OC1Init()~TIM_OC4Init()來設定的,不同的通道的設定函式不一樣,使用的是通道 1,就使用的函式是 TIM_OC1Init()。 TIM_OutputNState, TIM_OCNPolarity,TIM_OCIdleState 和 TIM_OCNIdleState 是高階定時器 TIM1 和 TIM8 才用到的。
定時器比較輸出初始化結構體
typedef struct {
uint16_t TIM_OCMode; // 比較輸出模式
uint16_t TIM_OutputState; // 比較輸出使能
uint16_t TIM_OutputNState; // 比較互補輸出使能
uint32_t TIM_Pulse; // 脈衝寬度
uint16_t TIM_OCPolarity; // 輸出極性--高階定時器 TIM1 和 TIM8 才用到的。
uint16_t TIM_OCNPolarity; // 互補輸出極性--高階定時器 TIM1 和 TIM8 才用到的
uint16_t TIM_OCIdleState; // 空閒狀態下比較輸出狀態--高階定時器 TIM1 和 TIM8 才用到的
uint16_t TIM_OCNIdleState; // 空閒狀態下比較互補輸出狀態--高階定時器 TIM1 和 TIM8 才用到的
} TIM_OCInitTypeDef;
(1) TIM_OCMode:比較輸出模式選擇
總共有八種,常用的為 PWM1/PWM2。它設定CCMRx 暫存器 OCxM[2:0]位的值。
(2) TIM_OutputState:比較輸出使能
決定最終的輸出比較訊號 OCx 是否通過外部引腳輸出。它設定 TIMx_CCER 暫存器 CCxE/CCxNE 位的值。
(3) TIM_OutputNState:比較互補輸出使能
,決定 OCx 的互補訊號 OCxN 是否通過外部引腳輸出。它設定 CCER 暫存器 CCxNE 位的值。
(4) TIM_Pulse:比較輸出脈衝寬度,???佔空比吧??
實際設定比較暫存器 CCR 的值,決定脈衝寬度。可設定範圍為 0 至 65535。
(5) TIM_OCPolarity:比較輸出極性,
可選 OCx 為高電平有效或低電平有效。它決定著定時器通道有效電平。它設定 CCER 暫存器的 CCxP 位的值。
(6) TIM_OCNPolarity:比較互補輸出極性,
可選 OCxN 為高電平有效或低電平有效。它設定 TIMx_CCER 暫存器的 CCxNP 位的值。
(7) TIM_OCIdleState:空閒狀態時通道輸出電平設定,可選輸出 1 或輸出 0,
即在空閒狀態(BDTR_MOE 位為 0)時,經過死區時間後定時器通道輸出高電平或低電平。它設定
CR2 暫存器的 OISx 位的值。
(8) TIM_OCNIdleState:空閒狀態時互補通道輸出電平設定,可選輸出 1 或輸出 0,
即在空閒狀態(BDTR_MOE 位為 0)時,經過死區時間後定時器互補通道輸出高電平或低電平,設定值必須與 TIM_OCIdleState 相反。它設定是 CR2 暫存器的 OISxN 位的值。
3. TIM_ICInitTypeDef
輸入捕獲結構體 TIM_ICInitTypeDef 用於輸入捕獲模式,與 TIM_ICInit 函式配合使用完成定時器輸入通道初始化配置。如果使用 PWM 輸入模式需要與 TIM_PWMIConfig 函式配合使用完成定時器輸入通道初始化配置。
定時器輸入捕獲初始化結構體
typedef struct {
uint16_t TIM_Channel; // 輸入通道選擇
uint16_t TIM_ICPolarity; // 輸入捕獲觸發選擇
uint16_t TIM_ICSelection; // 輸入捕獲選擇
uint16_t TIM_ICPrescaler; // 輸入捕獲預分頻器
uint16_t TIM_ICFilter; // 輸入捕獲濾波器
} TIM_ICInitTypeDef;
(1) TIM_Channel:
捕獲通道 ICx 選擇,可選 TIM_Channel_1、 TIM_Channel_2、TIM_Channel_3 或 TIM_Channel_4 四個通道。它設定 CCMRx 暫存器 CCxS 位 的值。
(2) TIM_ICPolarity:
輸入捕獲邊沿觸發選擇,可選上升沿觸發、下降沿觸發或邊沿跳變觸發。它設定 CCER 暫存器 CCxP 位和 CCxNP 位的值。
(3) TIM_ICSelection:
輸入通道選擇,捕獲通道 ICx 的訊號可來自三個輸入通道,分別為TIM_ICSelection_DirectTI、 TIM_ICSelection_IndirectTI 或 TIM_ICSelection_TRC,具體的區別見圖 32-15。如果是普通的輸入捕獲, 4 個通道都可以使用,如果是 PWM 輸入則只能使用通道 1 和通道 2。 它設定 CCRMx 暫存器的 CCxS[1:0]位的值
(4) TIM_ICPrescaler:輸入捕獲通道預分頻器,
可設定 1、 2、 4、 8 分頻,它設定 CCMRx暫存器的 ICxPSC[1:0]位的值。如果需要捕獲輸入訊號的每個有效邊沿,則設定 1 分頻即可。
(5) TIM_ICFilter:輸入捕獲濾波器設定,
可選設定 0x0 至 0x0F。它設定 CCMRx 暫存器ICxF[3:0]位的值。一般我們不使用濾波器,即設定為 0。
4. TIM_BDTRInitTypeDef
斷路和死區結構體 TIM_BDTRInitTypeDef 用於斷路和死區引數的設定,屬於高階定時器專用,用於配置斷路時通道輸出狀態,以及死區時間。它與 TIM_BDTRConfig 函式配置使用完成引數配置。 這個結構體的成員只對應 BDTR 這個暫存器,有關成員的具體使用配置請參考手冊 BDTR 暫存器的詳細描述。
斷路和死區初始化結構體
typedef struct {
uint16_t TIM_OSSRState; // 執行模式下的關閉狀態選擇
uint16_t TIM_OSSIState; // 空閒模式下的關閉狀態選擇
uint16_t TIM_LOCKLevel; // 鎖定配置
uint16_t TIM_DeadTime; // 死區時間
uint16_t TIM_Break; // 斷路輸入使能控制
uint16_t TIM_BreakPolarity; // 斷路輸入極性
uint16_t TIM_AutomaticOutput; // 自動輸出使能
} TIM_BDTRInitTypeDef;
(1) TIM_OSSRState:
執行模式下的關閉狀態選擇,它設定 BDTR 暫存器 OSSR 位的值。
(2) TIM_OSSIState:
空閒模式下的關閉狀態選擇,它設定 BDTR 暫存器 OSSI 位的值。
(3) TIM_LOCKLevel:
鎖定級別配置, BDTR 暫存器 LOCK[1:0]位的值。
(4) TIM_DeadTime:
配置死區發生器,定義死區持續時間,可選設定範圍為 0x0 至 0xFF。它設定 BDTR 暫存器 DTG[7:0]位的值。
(5) TIM_Break:
斷路輸入功能選擇,可選使能或禁止。它設定 BDTR 暫存器 BKE 位的值。
(6) TIM_BreakPolarity:
斷路輸入通道 BRK 極性選擇,可選高電平有效或低電平有效。它設定 BDTR 暫存器 BKP 位的值。
(7) TIM_AutomaticOutput:
自動輸出使能,可選使能或禁止,它設定 BDTR 暫存器 AOE位的值。
PWM 互補輸出實驗
舵機是一種電機,它使用一個反饋系統來控制電機的位置。大多數舵機是可以最大旋轉180°的。也有一些能轉更大角度,甚至360°。舵機比較多的用於對角度有要求的場合,比如攝像頭,智慧小車前置探測器,需要在某個範圍內進行監測的移動平臺。又或者把舵機放到玩具,讓玩具動起來。還可以用多個舵機,做個小型機器人,舵機就可以作為機器人的關節部分。其實舵機就是一種伺服電機
舵機三根線:
一根是紅色,連到+5V上。一根棕色(有些是黑的),連到GND。還有一根是黃色或者橘色,連到控制引腳。
怎麼控制?
PWM波,這是什麼東西呢?其實就是一種方波,其頻率為50Hz,週期就是20ms,在每個週期裡面,高電平的佔空比在0.5ms到2.5ms之間。而0.5ms代表的是0度,2.5ms代表的是180度。其他的度數可以直接按照比例換算過去
通過訊號線給舵機發送一系列的週期訊號(一般的舵機的能接收的訊號週期為20ms),然後通過控制週期訊號的高電平的持續時間來達到控制舵機轉動的目的。我手上的舵機就是根據高電平持續時間(0.5ms~2.5ms)來實現0~180的轉動的。
週期訊號的產生可以使用很多方式,但是使用PWM來控制高電平的佔空比不失為一種最好的應用方式。在STM32中,STM32的定時器也都提供有PWM的功能。下面就說明一下STM32輸出PWM的具體實現方式。
使用STM32控制單個舵機
在STM32中控制舵機,實際上就是開發STM32上的PWM功能,這部分功能需要配置STM32的定時器和GPIO複用共功能,然後就是通過修改定時器計數器的比較暫存器的數值來達到控制PWM的高電平佔空比的目的。
(1) 定時器 IO 配置
(2) 定時器時基結構體 TIM_TimeBaseInitTypeDef 配置
(3) 定時器輸出比較結構體 TIM_OCInitTypeDef 配置
(4) 定時器斷路和死區結構體 TIM_BDTRInitTypeDef 配置
PWM 輸出配置步驟(通過 TIM1_CH1 輸出PWM 來控制 舵機?)
1) 開啟 TIM1 時鐘,配置 PA8 為複用輸出。
要使用 TIM1,我們必須先開啟 TIM1 的時鐘,這裡我們還要配置 PA8 為複用輸出(當然還要時能 PORTA 的時鐘),這是因為 TIM1_CH1 通
道將使用 PA8 的複用功能作為輸出。
庫函式使能 TIM3 時鐘的方法是:RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定時器 3 時鐘
然後設定 PA8 為複用功能輸出的。
2)設定 TIM1 的 ARR 和 PSC。
配置TIM_TimeBaseInitTypeDef結構體
TIM_TimeBaseStructure.TIM_Period = arr; //設定自動重灌載值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設定預分頻值
3) 設定 TIM1_CH1 的 PWM 模式及通道方向, 使能 TIM1 的 CH1 輸出。
配置TIM_OCInitTypeDef結構體
4) 使能 TIM1
需要使能 TIM1。使能 TIM1 的方法:TIM_Cmd(TIM1, ENABLE); //使能 TIM1
5) 設定 MOE 輸出,使能 PWM 輸出。(高階定時器才需要)
普通定時器在完成以上設定了之後, 就可以輸出 PWM 了,但是高階定時器,我們還需要使能剎車和死區暫存器( TIM1_BDTR)的 MOE 位,以使能整個 OCx(即 PWM)輸出。 庫數的設定函式為:TIM_CtrlPWMOutputs(TIM1,ENABLE);// MOE 主輸出使能
6) 修改 TIM1_CCR1 來控制佔空比
最後,在經過以上設定之後, PWM 其實已經開始輸出了,只是其佔空比和頻率都是固定的,而我們通過修改 TIM1_CCR1 則可以控制 CH1 的輸出佔空比。
在庫函式中,修改 TIM1_CCR1 佔空比的函式是:
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
理所當然,對於其他通道,分別有一個函式名字,函式格式為 TIM_SetComparex(x=1,2,3,4)。
TIM2的通道一二,可惜被佔用換成3
void RCC_config_TIM2_CH1(void )
{
//使能複用以及GPIOB時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA,ENABLE);
//使能TIM2時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
}
void TIM2_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//PA0---TIM2通道1複用引腳
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure);
//PA1--TIM2通道2複用引腳
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure);
}
void TIM2_CH1_PWM_OUT(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
uint16_t Prescaler =0,Period,Pulse;
Prescaler = /*72M/36M - 1=*/ 1;
Period = 36000-1;
Pulse = 36000 *0.2;
/*
TIM2時基單元配置
重要配置:TIM_Prescaler(預分頻值)TIM_Period(定是週期)
將TIM_Period設定成999,則計數器會數1000個(TIM_Period+1)
節拍為一個定時器的週期。這個和後面需要配置的TIM_Pulse共同
控制著定時器輸出波形的佔空比。
TIM_Prescaler用來指定TIM時鐘的分頻值。也就是說它是進一步來
分頻TIM clock的。 簡單來說也就是定時器每一次數數的時間間隔是多少。
*/
TIM_TimeBaseStructure.TIM_Prescaler = Prescaler;//預分頻值
TIM_TimeBaseStructure.TIM_CounterMode = TIM_OutputState_Enable;
TIM_TimeBaseStructure.TIM_Period = Period;//定是週期 決定輸出頻率
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//時鐘分頻因子
TIM_TimeBaseInit( TIM2, &TIM_TimeBaseStructure);
/*
TIM2通道1:pwm模式配置
重要配置:TIM_Pulse(脈衝寬度)
*/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = Pulse;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
TIM_OC1Init( TIM2, &TIM_OCInitStructure);
TIM_OC2Init( TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);//使能或者失能 TIMx 在 CCR1 上的預裝載暫存器
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);//使能或者失能 TIMx 在 CCR1 上的預裝載暫存器
TIM_ARRPreloadConfig(TIM2, ENABLE);//使能或者失能 TIMx 在 ARR 上的預裝載暫存器
TIM_Cmd(TIM2, ENABLE);
}
void ADVANCE_TIM2_Init(void)
{
RCC_config_TIM2_CH1();
TIM2_GPIO_Config();
TIM2_CH1_PWM_OUT();
TIM_SetCompare1(TIM2 , 100); // 修改 TIM1_CCR1 來控制佔空比
TIM_SetCompare2(TIM2 , 100); // 修改 TIM1_CCR1 來控制佔空比
}
//設定 TIMx 捕獲比較 1 暫存器值
//每個捕獲通道都有相對應的捕獲暫存器 CCR1/2/3/4,
//原型 TIMx->CCR1 = Compare1;
//TIM_SetCompare1(TIM2 , 100); // 修改 TIM1_CCR1 來控制佔空比
相關推薦
STM32之TIM 舵機控制PWM
頻率的計算為: F = TIM_CLK/{(ARR+1)*(PSC+1)} 如果有中斷函式就要配置中斷通道中之類的 配置相應TIM通道的GPIO複用引腳 時基結構體配置 輸出比較結構體配置(pwm輸出時使用) 輸出使能 /************高階定時器 TI
STM32學習筆記-pwm生成-舵機控制
首先感謝河北科技大學航模協會-能給我這樣的學習機會-感謝那些帶我們教我們的學長學姐們.pwm是由定時器產生的這是一個定時器3控制舵機的例子不同舵機pwm的頻率和佔空比不同,用改變定時器初值和預分頻值即可.宣告:轉載請註明出處,本人入門級菜鳥,內容大多學習於網路,存在問題太多不
atmega16應用之舵機控制
atmega16應用之舵機控制 舵機工作的原理 (不會看版)控制電路板接受來自訊號線的控制訊號,控制電機轉動,電機帶動一系列齒輪組,減速後傳動至輸出舵盤。舵機的輸出軸和位置反饋電位計是相連的,舵盤轉動的同時,帶動位置反饋電位計,電位計將輸出一個電壓訊號到控制電路板,進行反饋,然後控制
Arduino之舵機控制
// 宣告呼叫Servo.h庫 #include <Servo.h> Servo myservo; // 建立一個舵機物件 int pos = 0; // 變數pos用來儲存舵機位置 void setup() { myservo.attach(9)
stm32之TIM+ADC+DMA采集50HZ交流信號
eba bsp 軟件 tco 輸入 工作方式 int32 rest ext http://cache.baiducontent.com/c?m=9d78d513d98207f04fece47f0d01d7174a02d1743ca6c76409c3e03984145b563
玩轉X-CTR100 l STM32F4 l 舵機控制
主程 控制 borde 接口 set span 效果 uart lac 我造輪子,你造車,創客一起造起來!塔克創新資訊【塔克社區 www.xtark.cn 】【塔克博客 www.cnblogs.com/xtark/ 】 本文介紹X-CTR100控制器的舵
基於fpga的舵機控制(MG995)
1、MG995舵機原理 a、這是一款由脈衝控制的舵機,週期為20ms,高脈衝部分所佔多少就決定了舵機轉動多少度。 b、高脈衝部分與角度關係 0.5ms-------------------0° 1ms---------------------45° 1.5ms---------------
樹莓派 基於 wiringPi庫 舵機控制
樹莓派 基於 wiringPi庫 舵機控制
arduino學習筆記5 舵機控制
舵機控制 舵機是一種位置伺服的驅動器,主要是由外殼、電路板、無核心馬達、齒輪與位置檢測器所構成。其工作原理是由接收機或者單片機發出訊號給舵機,其內部有一個基準電路,產生週期為20ms,寬度為1.5ms的基準訊號,將獲得的直流偏置電壓與電位器的電壓比較,獲得電壓差輸出。經由電路板
[20個專案學會BBC micro:bit程式設計] 11-模擬舵機控制實驗
--實驗程式設計 程式網址:https://makecode.microbit.org/_4i6UibMT5C5f --實驗結果 按A鍵模擬舵機(劃重點)轉到150度,按B鍵模擬舵機轉到30度。 注意事項: 1. 三線舵機接線時,橙色線為訊號線(通用標識),中間紅色線為VCC,需要接到3.3
【STM庫應用】stm32 之 TIM (詳解二 脈衝寬度、週期測量)
昨天已經把這個研究出來了,但是由於該專利申請書,一直沒有時間上傳,今天補上! 今天主要是用TIM3進行PWM的輸入模式,進行對矩形波的脈衝訊號寬度以及其週期進行測量,先來看一幅圖。 圖1 TIM內部邏輯圖 我們先來看看datasheet上是怎麼說的:
STM32之定時器中斷控制LED閃爍
上篇部落格我們是用延時函式實現了LED的閃爍,今天我們使用STM32的定時器來使LED閃爍。 關於32的定時器的種類,今天我在這先不做過多的說明,有時間我會再另寫一篇部落格來專門介紹32的定時器。今天我們使用32的定時器3來產生中斷,以實現LED的閃爍。 今
筆記-模擬舵機:基於STM32F103ZET的SG90舵機控制
寫在前面:筆者是一名小白,如有錯誤,還請及時指正。 1、舵機基本知識 1、SG90舵機是一個模擬舵機,而非數字舵機,這兩者的區別是這樣,數字舵機只要給一個PWM訊號即可,這個訊號是目的地的位置,舵機會自動旋轉到這個位置,而模擬舵機需要一直給予目的角度的PWM訊號。由於舵機
STM32之SPI從機DMA例程
#include "stm32f10x.h" /* RCC時鐘配置 */ void RCC_config(void) { ErrorStatus HSEStartUpStatus;/* RCC暫存器設定為預設配置 */RCC_DeInit();/* 開啟外部高速時鐘 */R
STM32之使用PWM控制多路舵機
前言 最近在玩一個6自由度的機械臂,我手上這臺機械臂的核心控制器件就是那六個能夠180度旋轉的舵機了。想想之前在學校還沒有系統性的把舵機給玩明白,所以就索性拿手上的STM32來自己寫驅動程式碼,將6個舵機給驅動起來。舵機控制原理 舵機的控制原理還是比較簡單的,而且
[stm32][hal]stm32f103rct6控制996r舵機
配置cub 程式碼 https://github.com/qdtom/diy/tree/master/stm32/stm32f103rct6_hal_duoji2 int main(void) { /* USER CODE
Arduino控制16路PWM舵機驅動板(PCA9685)
gin 很多 unsigned ets pan bits ble signed setup 最近買了塊16路PWM舵機驅動板,測試後做個總結。 舵機原理網上資料很多就不詳細介紹了,一般以9g舵機為例,一個20ms的周期內通過0.5ms到2.5ms的脈沖寬度控制舵機角度。 板
STM32 PWM波驅動模擬舵機(庫函式版)
數字舵機 vs 模擬舵機 “數字舵機區別於傳統的模擬舵機,模擬舵機需要給它不停的傳送PWM訊號,才能讓它保持在規定的位置或者讓它按照某個速度轉動,數字舵機則只需要傳送一次PWM訊號就能保持在規定的某個位置。” "到底模擬舵機與數碼舵機在實際使用中有什麼區別呢?我自己總結大致
stm32 12路pwm舵機控制器
用於以pwm訊號控制模擬舵機 使用 //@stm32f103 72mhz PWM_Init(1000-1,1440-1);//開12路pwm 50hz,arr=1000 RATIO_0(150);//設定位置,對模擬舵機CCR:100右極限,200左極限 h
STM32單線串列埠對匯流排舵機的控制
1 匯流排舵機的介紹匯流排伺服舵機即序列匯流排智慧舵機,實際上可以理解為數字舵機的衍生品,數字舵機與模擬舵機相比而言是控制系統設計上的顛覆,而匯流排伺服舵機對於舵機而言則是在功能和運用上的顛覆。舵機的運用方式實際上只能發揮出匯流排伺服舵機非常小的一部分功能。這款TS-315是通過單線的串列埠通訊對旋轉進行控