stm32f103vet6的sg90舵机标准库程序
时间: 2025-01-01 20:23:50 浏览: 9
### STM32F103VET6 控制 SG90 舵机标准库示例代码
对于STM32F103VET6单片机而言,控制SG90舵机通常通过PWM信号实现。PWM波形的周期固定为20ms (50Hz),而占空比决定了舵机的角度位置。具体来说:
- 占空比约为0.5ms时对应0度;
- 占空比约为1.5ms时对应90度;
- 占空比约为2.5ms时对应180度。
为了简化开发过程并提高代码可移植性和稳定性,在此提供一段基于官方标准外设库(Standard Peripheral Library, SPL)编写用于驱动SG90舵机的例子[^1]。
#### 初始化定时器配置 PWM 输出功能
```c
// 定义TIM2通道1对应的GPIO端口和引脚
#define SERVO_TIM TIM2
#define SERVO_CHANNEL TIM_Channel_1
#define SERVO_GPIO_PORT GPIOA
#define SERVO_PIN GPIO_Pin_0
void Servo_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// RCC_APB1PeriphClockCmd(SERVO_TIM_CLK, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
// 配置PA0作为复用推挽输出模式
GPIO_InitStructure.GPIO_Pin = SERVO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SERVO_GPIO_PORT,&GPIO_InitStructure);
// 设置自动重装载寄存器ARR=7999即频率f=SystemCoreClock/(8*8000)=1kHz
TIM_TimeBaseStructure.TIM_Period = 7999;
TIM_TimeBaseStructure.TIM_Prescaler = 7;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 配置OCxM=6表示PWM模式1;CCR1初始值设定为中间角度1.5ms处
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 计算得到中心位置计数值 CCR=(1.5/20)*8000≈600
uint16_t CenterPosition = (uint16_t)((float)(SERVO_CENTER_MS * ARR_VALUE)/(PERIOD_MS));
TIM_OCInitStructure.TIM_Pulse = CenterPosition;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
// 启动定时器
TIM_Cmd(TIM2, ENABLE);
}
```
上述初始化函数完成了对指定IO口以及相应定时器资源的基础设置,并预设了默认居中的脉宽参数以便后续调整使用。
#### 动态改变PWM宽度来转动舵机至特定角度
```c
/**
* @brief Set servo angle.
*
* @param Angle The target angle of the servo motor ranging from 0 to 180 degrees.
*/
void SetServoAngle(uint8_t Angle){
float DutyCycleRatio;
uint16_t PulseWidth;
if(Angle>180 || Angle<0)return ;
// 将角度转换成相应的脉冲宽度
DutyCycleRatio=((float)Angle*(MAX_WIDTH_MIN_WIDTH)+MIN_WIDTH)/PERIOD_MS;
PulseWidth=DutyCycleRatio*ARR_VALUE;
// 更新比较寄存器值从而改变PWM输出高低电平时间比例达到旋转目的
TIM_SetCompare1(TIM2,PulseWidth);
}
int main(){
// System initialization...
Servo_Init();
while(1){
// Example: Rotate the servo between two angles periodically
SetServoAngle(0);
Delay_ms(1000);
SetServoAngle(90);
Delay_ms(1000);
SetServoAngle(180);
Delay_ms(1000);
}
}
```
这段程序展示了如何利用之前定义好的`SetServoAngle()`接口让舵机按照一定规律循环摆动三个不同方向的位置。实际项目里可以根据需求修改这些逻辑以适应具体的场景应用。
阅读全文