## 一、PWM 驱动电机的原理 PWM 通过固定频率的方波信号,改变高电平占空比(0%~100%)来调整输出功率。对于直流电机,平均电压 = 电源电压 × 占空比,从而改变电枢电流,实现转速调节。STM32 的定时器(如 TIM1~TIM8)具有硬件 PWM 生成能力,无需 CPU 干预即可持续输出波形。 关键参数: - **频率**:通常 10kHz~20kHz,避免 audible noise,同时保证电流纹波可控。 - **占空比**:决定平均电压,正转/反转需配合 H 桥方向引脚。 - **分辨率**:取决于定时器重载值(ARR),如 ARR=999 时,占空比步进为 0.1%。 ## 二、STM32 定时器 PWM 工作原理 以通用定时器 TIM3 为例,PWM 输出基于以下寄存器: - **TIMx_PSC**(预分频器):将时钟分频,得到计数频率。 - **TIMx_ARR**(自动重装载):决定 PWM 频率。 - **TIMx_CCR**(捕获/比较):与计数器值比较,控制占空比。 输出模式为 **PWM1** 时: - 计数器 < CCR → 输出有效电平(默认高) - 计数器 ≥ CCR → 输出无效电平(默认低) 因此,占空比 = CCR / (ARR+1)。通过修改 CCR 即可在线调速。 ## 三、硬件连接与 H 桥简介 MCU 的 GPIO 输出电流有限,不能直接驱动电机。常用方案是使用 **H 桥**(如 L298N、DRV8833)或集成 MOS 驱动。H 桥需要两个控制端: - **PWM 输入**:接收占空比信号 - **方向引脚**:控制正反转 例如,L298N 的 ENA 接 PWM,IN1/IN2 决定方向。注意共地,避免电流干扰。 ## 四、STM32CubeMX 配置步骤 ### 1. 选择定时器 - 打开 STM32CubeMX,配置 TIM3。 - 时钟源选择 **Internal Clock**。 - Channel1 选择 **PWM Generation CH1**。 - 设置 Prescaler = 71(72MHz/72 = 1MHz 计数时钟) - 设置 Counter Period (ARR) = 999(则 PWM 频率 = 1MHz / 1000 = 1kHz) - 初始占空比设为 500(50%) ### 2. 配置 GPIO - 若使用 L298N,需额外配置两个 GPIO 为输出,用于方向控制。 ### 3. 生成工程 - 选择 HAL 库,生成代码。 ## 五、HAL 库代码示例 以下为核心代码(基于 STM32F103,已包含在 main.c 中): ```c // 启动 PWM 输出(由 CubeMX 生成的初始化函数中已调用) HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // 方向控制引脚定义(假设 PA4=IN1, PA5=IN2) #define MOTOR_FORWARD {HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, SET); \ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, RESET);} #define MOTOR_BACKWARD {HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, RESET); \ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, SET);} #define MOTOR_STOP {HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, RESET); \ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, RESET);} // 调速函数(speed: 0~1000,对应 0%~100%) void Motor_SetSpeed(uint16_t speed) { if (speed > 1000) speed = 1000; __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, speed); } // 使用示例 int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM3_Init(); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); while (1) { MOTOR_FORWARD; Motor_SetSpeed(600); // 60% 占空比正转 HAL_Delay(3000); MOTOR_BACKWARD; Motor_SetSpeed(400); // 40% 占空比反转 HAL_Delay(3000); MOTOR_STOP; HAL_Delay(1000); } } ``` ## 六、调试与优化技巧 - 若电机有高频啸叫,检查 PWM 频率是否在 16kHz 以上(人耳听不见)。 - 低速时会出现死区(电机不转),可在软件中做非线性映射,或用 PID 补偿。 - 使用示波器观察 PWM 波形,确保占空比与预期一致,同时检查是否有毛刺(可能导致电机抖动)。 ## 七、注意事项 1. **共地问题**:电机电源和单片机必须共地,否则逻辑电平不稳定。 2. **电源滤波**:电机启动电流大,需在电源端并联 100μF~470μF 电解电容和 0.1μF 陶瓷电容。 3. **隔离与保护**:若电机功率较大,建议使用光耦隔离驱动信号;并对 PWM 引脚进行限流保护。 4. **死区时间**:若使用 H 桥全桥驱动,必须在上下管切换时插入死区,避免直通短路。可配置 STM32 高级定时器的死区寄存器(如 TIM1_BDTR)。 5. **频率选择**:不宜过高(>100kHz),否则开关损耗增大;也不宜过低(<5kHz),会引起扭矩波动。 ## 总结 本文从 PWM 原理切入,演示了 STM32 定时器生成 PWM 的配置与 HAL 代码。实际工程中,需根据电机型号、驱动器特性调整频率与死区,并配合速度闭环(如 PID)实现精准控制。基础打好,后续可扩展至 FOC 或 BLDC 控制。