一、功能描述
使用 STM32F103 上使用 PA8 引脚控制舵机 SG90,通过 PWM 脉冲宽度调制实现。
舵机通常需要 50Hz 周期 20ms 的 PWM 信号,脉冲宽度在 0.5ms(0°)~ 2.5ms(180°) 之间。
二. 认识舵机
1.硬件连接
舵机信号线 → PA8(TIM1_CH1,STM32F103 的高级定时器)
舵机 VCC → 外部电源(5V,建议单独供电,避免电流不足)
舵机 GND → STM32 的 GND

SG90 舵机产品参数

尺寸
代码实现
步骤 1:配置 TIM1 生成 PWM
使用 STM32CubeMX 配置:
启用 TIM1(高级定时器)。
设置 Channel1 为 PWM Generation。
设置 Prescaler 和 Counter Period 以生成 50Hz 的 PWM:
时钟频率(假设 72MHz):
Prescaler = 72-1 → 定时器时钟 = 1MHz(1μs 分辨率)
Counter Period = 20000-1 → 20ms 周期(50Hz)
PWM 模式:PWM Mode 1(向上计数)
Pulse(初始脉宽):
0° → 500(0.5ms)
90° → 1500(1.5ms)
180° → 2500(2.5ms)
启用 TIM1_CH1 对应的 GPIO(PA8)。
手动计算(无 CubeMX):
定时器时钟 = 72MHz(STM32F103 默认)
Prescaler = 72 - 1 → 定时器时钟 = 1MHz(1μs 分辨率)
Counter Period = 20000 - 1 → 20ms 周期(50Hz)
PWM 脉宽:
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pulse_width);
pulse_width 范围:500 ~ 2500(对应 0.5ms ~ 2.5ms)
三、cube mx 配置
配置步骤
(1) CubeMX 设置
1.
选择 TIM1 → Channel1 → PWM Generation CH1
Counter Period(ARR):PWM 分辨率
Pulse(CCR):初始占空比
GPIO Settings确认 PA8 模式:应显示 TIM1_CH1
通道 1 模式,PWM Generation CH1,产生 PWM 信号
对应引脚,PA8,TIM1_CH1 输出引脚

四、代码
初始
TIM_HandleTypeDef htim1;
/* TIM1 init function */
void MX_TIM1_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE BEGIN TIM1_Init 1 */
/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 719;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 1999;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */
/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);
}
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
{
if(tim_pwmHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM1_MspInit 0 */
/* TIM1 clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
/* USER CODE BEGIN TIM1_MspInit 1 */
/* USER CODE END TIM1_MspInit 1 */
}
}
主函数
int main(void)
{
// 重置所有外设,初始化Flash接口和Systick(系统滴答定时器)
HAL_Init();
// 配置系统时钟(如HSE、HSI、PLL等)
SystemClock_Config();
// 初始化所有配置的外设(如GPIO、TIM1等)
MX_GPIO_Init();
MX_TIM1_Init();
// 用户自定义代码区域2(外设初始化后)
// 启动TIM1的PWM通道1(PA8引脚输出PWM信号)
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
/* USER CODE END 2 */
while (1)
{
// 定义延时时间(单位:毫秒)
int i = 1000; // 循环延时1秒(1000ms)
// 设置PWM脉宽为50(对应舵机0°位置)
// 假设TIM1的PWM配置为:
// - 计数器时钟 = 1MHz(1μs分辨率)
// - 周期 = 20000(20ms)
// - 脉宽50 = 50μs(实际应为500~2500,此处可能是示例错误)
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 50);
HAL_Delay(i); // 延时1秒
// 设置PWM脉宽为250(对应舵机180°位置)
// 250 = 250μs(实际应为500~2500,此处可能是示例错误)
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 250);
HAL_Delay(i); // 延时1秒
}
}五、实现效果
我要赚赏金
