STM32F103 + AM2857 完整实现方案

先重申硬件基础: 单颗 AM2857 = 单路 H 桥,驱动 1 台直流有刷电机 控制引脚:IN_AIN_B(2 个 3.3V 信号,STM32 GPIO 直接驱动) AM2857 真值表

表格

IN_A IN_B 工作状态
0 1 电机正转
1 0 电机反转
0 0 滑行(高阻,自由停止)
1 1 能耗刹车(短接制动)

⚠️ 重点:AM2857无硬件死区保护,禁止直接换向,防止上下 MOS 直通烧毁芯片。

一、两种工程实现方案(推荐方案 1,机器人底盘首选)

方案 1:一个引脚固定电平,另一个引脚输出 PWM【推荐】

硬件分配

  • IN_A:普通 GPIO 推挽输出(输出恒定高低电平,方向控制
  • IN_B:定时器复用功能 TIM_CHx,输出 PWM 波形(调速控制

全程不需要动态切换 GPIO 模式,代码最简单、稳定性最高。

工作逻辑

  1. 电机正转 IN_A = 0(固定低电平) IN_B = PWM波形 ✅ PWM 占空比越大 → 电机两端平均电压越高,转速越快

  2. 电机反转 IN_A = 1(固定高电平) IN_B = PWM波形

  3. 滑行停机 IN_A = 0 PWM占空比设置为0

时序优势

同一时刻只有一条信号线在高速跳变,EMI 干扰更小,降低对板载 ICM20948 陀螺仪的噪声干扰。


方案 2:IN_A、IN_B 轮流切换 PWM(不推荐)

正转:INA 固定 0,INB 输出 PWM

反转:INA 输出 PWM,INB 固定 0

缺陷:运行时需要动态切换 GPIO

「普通输出 <-> 定时器复用模式(PWM输出)」,代码复杂,容易出现配置 BUG。

二、参数配置建议(STM32F103)

  1. PWM 定时器:TIM1/TIM2/TIM3/TIM4,推荐 10kHz
    • <5kHz:电机人耳可闻噪声大
    • 20kHz:AM2857 开关损耗上升,发热加剧

  2. 定时器计数周期: 72MHz 系统时钟,预分频 71 → 定时器时钟 1MHz 自动重装载值 ARR=99 → 1MHz/(99+1)=10kHz 占空比范围:0~100(0%~100%)

三、标准可直接移植代码(STM32 HAL 库,方案 1 架构)

硬件定义示例

c

运行

//IN_A 普通GPIO
#define IN_A_PIN  GPIO_PIN_0
#define IN_A_PORT GPIOA
//IN_B TIM_CH PWM输出(例如TIM3_CH1)
extern TIM_HandleTypeDef htim3;
#define PWM_TIM_HANDLE htim3

c

运行

//电机初始化:启动PWM通道
void Motor_Init(void)
{
    HAL_TIM_PWM_Start(&PWM_TIM_HANDLE, TIM_CHANNEL_1);
    __HAL_TIM_SET_COMPARE(&PWM_TIM_HANDLE, TIM_CHANNEL_1, 0); //初始占空比0
    HAL_GPIO_WritePin(IN_A_PORT, IN_A_PIN, GPIO_PIN_RESET);
}

/**
 * @brief 电机控制函数
 * @param speed 范围 -100 ~ +100
 * speed>0:正转;speed<0:反转;speed=0:滑行停止
 */
void Motor_SetSpeed(int16_t speed)
{
    uint16_t duty = abs(speed);
    //第一步:先把PWM清零
    __HAL_TIM_SET_COMPARE(&PWM_TIM_HANDLE, TIM_CHANNEL_1, 0);
    HAL_Delay(1); //换向安全死区
    
    if(speed > 0)
    {
        //正转:IN_A=0,IN_B输出PWM
        HAL_GPIO_WritePin(IN_A_PORT, IN_A_PIN, GPIO_PIN_RESET);
    }
    else if(speed < 0)
    {
        //反转:IN_A=1,IN_B输出PWM
        HAL_GPIO_WritePin(IN_A_PORT, IN_A_PIN, GPIO_PIN_SET);
    }
    else
    {
        //停止
        HAL_GPIO_WritePin(IN_A_PORT, IN_A_PIN, GPIO_PIN_RESET);
        return;
    }
    //设置占空比,开启转速
    __HAL_TIM_SET_COMPARE(&PWM_TIM_HANDLE, TIM_CHANNEL_1, duty);
}

//滑行停止简易封装
void Motor_Stop(void)
{
    Motor_SetSpeed(0);
}

四、关键避坑要点(针对YB-ERF01-V3.0 控制板)

1. 换向必须加入死区延时!

禁止直接从 正转 → 立即反转 错误操作:电平瞬间翻转,MOS 关断存在延时,造成电源直通,直接烧毁 AM2857。 ✅ 规范流程:PWM 清零 → 等待 ≥1ms → 切换方向电平 → 恢复 PWM。

2. PWM 占空比含义

在这套代码里:

占空比 = IN_B 引脚上 PWM 波形的高电平占比

占空比 0 → IN_B 持续低,电机停止;

占空比 100 → IN_B 持续高,电机全速。

3. 刹车模式慎用

IN_A=1 && IN_B=1 为能耗刹车,仅适合紧急制动; 长时间堵转刹车会持续大电流,芯片过热触发 OTP 保护。 机器人底盘常规停止优先使用滑行模式(0,0)

4. PCB 布线注意

AM2857 功率回路(VM、电机输出线)远离 ICM20948 九轴陀螺仪; 电机两端 RC 吸收回路不能省略,抑制反向电动势,减少传感器漂移。

五、麦轮 / 差速底盘拓展说明

板子使用两颗 AM2857,左右电机各一套独立 IN_A + PWM 控制信号; STM32 运动学解算得到左右轮目标速度,分别调用Motor_SetSpeed()即可实现底盘前进、后退、转向。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐