一、功能描述
使用 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秒 } }
五、实现效果