STM32 PWM 控制舵机学习记录

今天主要学习了定时器 PWM 的基本概念,以及如何用 STM32 HAL 库控制 SG90 舵机。

一、几个核心概念

1. PSC 是什么

PSC 是 预分频器

它的作用是把定时器输入时钟先分频,再送给计数器。

可以理解成:

  • 时钟跑得太快
  • PSC 先把速度降下来
  • CNT 才能慢慢数

2. CNT 是什么

CNT 是 计数器当前值

它就像一个正在数数的小人:

  • 从 0 开始数
  • 一直数到 ARR
  • 然后重新回到 0

3. ARR 是什么

ARR 是 自动重装载值

它决定 CNT 数到多少时结束一轮计数。

也可以理解为:

  • CNT 数到 ARR
  • 就产生一次更新事件
  • 然后重新开始数

二、PWM 的本质

PWM 就是 脉冲宽度调制

在定时器里可以简单理解成:

  • ARR 决定周期
  • CCR 决定占空比

1. ARR 决定周期

PWM 信号多久重复一次,由 ARR 决定。

2. CCR 决定占空比

CCR 决定高电平持续多久,也就是脉宽。


三、PWM 控制函数

1. 开启 PWM

HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);

作用:开启定时器 3 的 3 通道 PWM 输出。

2. 设置比较值

__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, sg90_angle);

作用:设置比较寄存器 CCR 的值,也就是 PWM 的占空比。


四、PWM 控制舵机的方法步骤

第一步:开启定时器 PWM 运行

放在 /* USER CODE BEGIN 2 */ 里面:

HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);

第二步:设置比较寄存器的值

还是在初始化后设置初始脉宽:

__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, sg90_angle);

第三步:定义初始值

sg90_angle 是你当前输出的比较值,通常提前定义:

uint16_t sg90_angle = 500;

这个值就是舵机上电后的初始脉宽。


五、舵机为什么能转

SG90 舵机不是看电压大小,而是看 PWM 脉宽。

一般来说:

  • 0.5 ms 左右,对应一个方向极限
  • 1.5 ms 左右,对应中间位置
  • 2.5 ms 左右,对应另一个方向极限

所以你改变 CCR 的值,舵机就会转到不同角度。


六、我的按键控制思路

这次的逻辑是:

  • 按 K1,舵机角度增加
  • 按 K2,舵机角度减小
  • 每次改变后重新写入比较值
  • 通过 PWM 改变舵机位置
#define SG90_MIN  500
#define SG90_MAX  2500
#define SG90_STEP 500

uint16_t sg90_angle = 500;

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_TIM3_Init();

    HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, sg90_angle);

    while (1)
    {
        if (HAL_GPIO_ReadPin(GPIOA, K1_Pin) == GPIO_PIN_SET)
        {
            if (sg90_angle + SG90_STEP <= SG90_MAX)
            {
                sg90_angle += SG90_STEP;
                __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, sg90_angle);
            }
            HAL_Delay(300);
            while (HAL_GPIO_ReadPin(GPIOA, K1_Pin) == GPIO_PIN_SET);
        }

        if (HAL_GPIO_ReadPin(GPIOA, K2_Pin) == GPIO_PIN_SET)
        {
            if (sg90_angle - SG90_STEP >= SG90_MIN)
            {
                sg90_angle -= SG90_STEP;
                __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, sg90_angle);
            }
            HAL_Delay(300);
            while (HAL_GPIO_ReadPin(GPIOA, K2_Pin) == GPIO_PIN_SET);
        }
    }
}

七、今天最重要的记忆点

1. PWM 三个关键值

  • PSC:分频
  • ARR:周期
  • CCR:占空比

2. 舵机控制本质

  • 改变 CCR
  • 改变脉宽
  • 改变舵机角度

3. 最常用的两个函数

HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, sg90_angle);

八、容易写错的地方

1. 函数名不要写错

正确的是:

__HAL_TIM_SET_COMPARE

不是:

_HAL_TIM_SET_COMPARE

2. 条件判断方向要对

比如减小角度时,应该判断:

sg90_angle - SG90_STEP >= SG90_MIN

不是加号。


九、总结

今天学到的 PWM 控舵机流程可以记成一句话:

开 PWM,改 CCR,看舵机转。

以后只要记住:

  • PSC 控速度
  • ARR 控周期
  • CCR 控脉宽
  • 舵机靠 PWM 脉宽定位

就能很快上手这类项目。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐