STM32驅動舵機
阿新 • • 發佈:2018-11-10
舵機控制原理:
提供週期為20ms的pwm訊號,調節pwm的佔空比為0.5ms-2.5ms可使舵機從0-180度線性變化
舵機控制程式:
首先我們要利用stm32定時器產生合適週期的pwm輸出訊號,這裡使用的是PWM高階定時器1的CH1(即PA8),可以通過配置輸入引數arr和psc產生合適的頻率的pwm脈衝訊號。
//高階定時器1pwm輸出初始化 //arr:自動重灌值(週期) psc:時鐘預分頻數 void tim1_pwmInit(uint16_t arr, uint16_t psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); // 使能定時器1的外設時鐘 RCC_APB2PeriphClockCmd(TIM1_CH1_GPIO_CLK, ENABLE); //使能GPIO外設時鐘使能 //設定該引腳為複用輸出功能,輸出TIM1 CH1的PWM脈衝波形 GPIO_InitStructure.GPIO_Pin = TIM1_CH1_PIN; //TIM_CH1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //複用推輓輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(TIM1_CH1_PORT, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = arr; //設定在下一個更新事件裝入活動的自動重灌載暫存器週期的值 80K TIM_TimeBaseStructure.TIM_Prescaler = psc; //設定用來作為TIMx時鐘頻率除數的預分頻值 不分頻 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設定時鐘分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的引數初始化TIMx的時間基數單位 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //選擇定時器模式:TIM脈衝寬度調製模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能 //TIM_OCInitStructure.TIM_Pulse = 0; //設定待裝入捕獲比較暫存器的脈衝值 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //輸出極性:TIM輸出比較極性低 TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根據TIM_OCInitStruct中指定的引數初始化外設TIMx TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主輸出使能 TIM_Cmd(TIM1, ENABLE); //使能TIM1 }
在有了pwm訊號源之後我們便可以根據舵機的控制原理構建舵機驅動函數了。
// 72M / (719 + 1) = 0.1M 故記一個數的時間為10us 定時週期:(1999 + 1) * 10us = 20ms
#define SERVO_TIM_ARR 1999
#define SERVO_TIM_PSC 719
void servo_init(void) { tim1_pwmInit(SERVO_TIM_ARR,SERVO_TIM_PSC); TIM_SetCompare1(TIM1,150); //使舵機恢復到中間位置 } //0.5ms--0° 2.5ms--180° void servo_angle(uint16_t angle) { uint16_t pulse; //針對舵機可轉角度限輻 if(angle <= 5) angle = 5; if(angle >= 175) angle = 175; //將角度值轉換為脈衝值 pulse = (uint16_t)(50 + angle * 100/90.0); //此轉換公式需根據pwm的arr及psc配置來做相應變化 TIM_SetCompare1(TIM1, pulse); } void servo_debug(void) { uint8_t i; for(i = 0; i < 10; ++i) { delay_ms(500); servo_angle(45); delay_ms(500); servo_angle(90); delay_ms(500); servo_angle(135); delay_ms(500); servo_angle(90); } }
在主函式中初始化舵機驅動後,便可以呼叫servo_angle(uint16_t angle)函式實現舵機在5-175度之間任意角度的旋轉,選擇5-175度限輻是為了保護舵機(防止舵機處於打死的狀態),也可改為0-180度。