这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【Let'sdoDigiKey2026第3期】+基于STM32C562RE的步进

共1条 1/1 1 跳转至页

【Let'sdoDigiKey2026第3期】+基于STM32C562RE的步进电机控制与三轴振动数据采集

菜鸟
2026-10-27 14:04:05     打赏

一、项目背景

在上一篇文章中,我完成了 NUCLEO-C562RE 开发环境搭建,并验证了板载 LED、用户按键、蜂鸣器和 USART2 串口通信。

本篇在此基础上继续完成两项基础功能:

  1. 使用 NUCLEO-C562RE 控制 28BYJ-48 类步进电机;

  2. 使用 Grove LIS3DHTR 三轴加速度计采集电机振动数据,并通过串口输出 CSV 数据。

这两部分完成后,就可以进一步使用 NanoEdge AI Studio 进行“停止 / 慢速 / 中速 / 快速”四类电机状态模型训练。

活动页面:Let's do 2026 年第 3 期活动介绍

6c052a9044403aa20db89145aa0f6133.jpg

二、硬件与软件环境

硬件

  • 主控板NUCLEO-C562RE
  • 步进电机Gear Stepper Motor Driver Pack,5 V、四相八拍、1/64

  • 减速加速度计Grove LIS3DHTR 三轴数字加速度计

  • 调试器板载 ST-LINK

  • 电机电源外部 5 V/1 A 以上电源

软件

  • STM32CubeMX2:配置芯片、时钟及外设

  • VScode+STM32CubeIDE组件:编译、下载和调试

  • 串口调试助手:查看串口输出

三、系统设计与连接说明

1. 步进电机驱动板接线

电机驱动板使用 5 V 独立电源,控制信号连接到 NUCLEO-C562RE 的 Arduino 数字排针。

驱动板NUCLEO-C562REMCU 引脚
IN1CN9 pin 5 / D4PC1
IN2CN9 pin 6 / D5PB4
IN3CN9 pin 7 / D6PB10
IN4CN9 pin 8 / D7PA8
GNDCN6 pin 6/7GND
VCC外部 5 V—
VM外部 5 V 或按板上开关选择—

电机驱动板与 NUCLEO 必须共地。

电源注意事项:

  • 不要使用 STM32 的 3.3 V 给电机供电;

  • 不要从 ST-LINK USB 的 5 V 直接驱动电机;

  • 建议使用 5 V/1 A 以上独立电源;

  • 驱动板附近增加 100 µF 电解电容和 100 nF 陶瓷电容;

  • 电机动力线与 I2C 信号线尽量分开走线。

2. LIS3DHTR 加速度计接线

LIS3DHTRNUCLEO-C562RE说明
VCCCN6 pin 4 / 3V3使用 3.3 V
GNDCN6 pin 6/7共地
SDACN5 pin 9 / D14PB7 / I2C1_SDA
SCLCN5 pin 10 / D15PB6 / I2C1_SCL
INT1CN8 pin 4 / A3可选,接 PB0
SDO悬空或接 GND悬空地址 0x19,接 GND 为 0x18

四、开发环境搭建与外设配置

1. GPIO 配置

引脚模式Pull初始状态标签
PC13GPIO_InputNo Pull—B1_USER
PA5GPIO_Output Push-PullNo PullLowLED_LD1
PC6GPIO_Output Push-PullNo PullLowBUZZER
PC1GPIO_Output Push-PullNo PullLowIN1
PB4GPIO_Output Push-PullNo PullLowIN2
PB10GPIO_Output Push-PullNo PullLowIN3
PA8GPIO_Output Push-PullNo PullLowIN4

2. I2C1 配置

I2C1
Mode: I2C
Speed: Fast Mode
Clock Speed: 400 kHz
SCL: PB6
SDA: PB7

3. USART2 配置

USART2
Mode: Asynchronous
Baud Rate: 921600
Word Length: 8 Bits
Parity: None
Stop Bits: 1
Flow Control: None
TX: PA2
RX: PA3

USART2 与板载 ST-LINK VCP 对应,因此烧录、调试和串口打印可以共用 CN1 的 USB-C 接口。

五、步进电机控制设计

1. 电机状态定义

为了方便后续采集“停止、慢速、中速、快速”数据,程序使用状态机管理电机:

typedef enum
{
  MOTOR_STOP = 0,
  MOTOR_SLOW,
  MOTOR_MEDIUM,
  MOTOR_FAST,
  MOTOR_STATE_COUNT
} motor_state_t;

各状态步进间隔:

static const uint16_t motor_step_intervals[MOTOR_STATE_COUNT] =
{
  0U, 5U, 3U, 2U
};

对应关系:

状态步进间隔近似步频
STOP—0
SLOW5 ms200 步/s
MEDIUM3 ms约 333 步/s
FAST2 ms500 步/s

2. 八拍相序

步进电机按八拍方式驱动:

A → AB → B → BC → C → CD → D → DA

对应相序表:

static const uint8_t sequence[8] =
{
  0x01U, 0x03U, 0x02U, 0x06U,
  0x04U, 0x0CU, 0x08U, 0x09U
};

输出函数:

static void motor_write_step(uint8_t step)
{
  uint8_t pattern = sequence[step & 0x07U];

  HAL_GPIO_WritePin(MOTOR_IN1_PORT, MOTOR_IN1_PIN,
                    (pattern & 0x01U) ? HAL_GPIO_PIN_SET : HAL_GPIO_PIN_RESET);

  HAL_GPIO_WritePin(MOTOR_IN2_PORT, MOTOR_IN2_PIN,
                    (pattern & 0x02U) ? HAL_GPIO_PIN_SET : HAL_GPIO_PIN_RESET);

  HAL_GPIO_WritePin(MOTOR_IN3_PORT, MOTOR_IN3_PIN,
                    (pattern & 0x04U) ? HAL_GPIO_PIN_SET : HAL_GPIO_PIN_RESET);

  HAL_GPIO_WritePin(MOTOR_IN4_PORT, MOTOR_IN4_PIN,
                    (pattern & 0x08U) ? HAL_GPIO_PIN_SET : HAL_GPIO_PIN_RESET);
}

3. 非阻塞电机任务

电机换相不放在延时函数中,而是通过 HAL_GetTick() 判断时间:

static void motor_task(void)
{
  uint32_t now;

  if (motor_running == 0U)
  {
    return;
  }

  now = HAL_GetTick();

  if ((now - motor_last_step_tick) >= motor_step_interval_ms)
  {
    motor_last_step_tick = now;
    motor_write_step(motor_step_index);
    motor_step_index = (motor_step_index + 1U) & 0x07U;
  }
}

这样主循环仍然可以处理按键、蜂鸣器和传感器数据。

4. 按键切换电机状态

用户按键 B1 接 PC13,按下为高电平。每按一次,电机状态按下面顺序循环:

SLOW → MEDIUM → FAST → STOP → SLOW

按键处理中同时完成:

  • 更新电机状态;

  • 更新 LED;

  • 启动蜂鸣器短鸣;

  • 串口打印当前状态。

核心逻辑:

motor_state = (motor_state_t)(((uint32_t)motor_state + 1U) %
                              (uint32_t)MOTOR_STATE_COUNT);

motor_running = (motor_state != MOTOR_STOP) ? 1U : 0U;
motor_step_interval_ms = motor_step_intervals[motor_state];

led_on = motor_running;

HAL_GPIO_WritePin(LED_PORT, LED_PIN,
                  led_on ? HAL_GPIO_PIN_SET : HAL_GPIO_PIN_RESET);

六、三轴加速度采集设计

1. LIS3DHTR 初始化

LIS3DHTR 的 I2C 地址为:

0x19

如果 SDO 接 GND,地址为:

0x18

HAL 接口要求使用左移后的地址:

#define LIS3DH_I2C_ADDR (0x19U << 1U)

初始化流程:

  1. 读取 WHO_AM_I 寄存器 0x0F;

  2. 确认返回值为 0x33;

  3. 配置 CTRL_REG1;

  4. 配置 CTRL_REG4。

/* 1.344 kHz 高分辨率,XYZ 使能 */
reg_value = 0x97U;
HAL_I2C_MASTER_MemWrite(hi2c, LIS3DH_I2C_ADDR,
                        LIS3DH_REG_CTRL_REG1,
                        HAL_I2C_MEM_ADDR_8BIT,
                        &reg_value, 1U, 100U);

/* BDU、±2g、高分辨率 */
reg_value = 0x88U;
HAL_I2C_MASTER_MemWrite(hi2c, LIS3DH_I2C_ADDR,
                        LIS3DH_REG_CTRL_REG4,
                        HAL_I2C_MEM_ADDR_8BIT,
                        &reg_value, 1U, 100U);

2. 读取三轴数据

从 OUT_X_L 寄存器 0x28 开始连续读取 6 个字节:

uint8_t data[6];

HAL_I2C_MASTER_MemRead(hi2c,
                       LIS3DH_I2C_ADDR,
                       LIS3DH_REG_OUT_X_L | 0x80U,
                       HAL_I2C_MEM_ADDR_8BIT,
                       data,
                       sizeof(data),
                       100U);

拼接为有符号 16 位数据:

ax = (int16_t)((uint16_t)data[0] | ((uint16_t)data[1] << 8));
ay = (int16_t)((uint16_t)data[2] | ((uint16_t)data[3] << 8));
az = (int16_t)((uint16_t)data[4] | ((uint16_t)data[5] << 8));

3. 串口 CSV 输出

为了便于后续导入 NanoEdge AI Studio,串口按 CSV 格式输出:

printf("%lu,%d,%d,%d,%s\r\n",
       (unsigned long)now,
       ax, ay, az,
       motor_state_names[motor_state]);

输出示例:

t_ms,ax,ay,az,state
18590,-2000,736,14928,SLOW
18600,1600,1168,15744,SLOW
18610,2160,1360,16768,SLOW
18620,976,1280,17488,SLOW

当前为了兼容普通串口调试助手,将打印周期设置为 10 ms,约 100 Hz:

#define SENSOR_SAMPLE_INTERVAL_MS 10U

    1af479e9314870cf6d48ada419202446.png


    七、小结

    本篇完成了两项关键功能:

    1. 使用 NUCLEO-C562RE 控制 5 V 四相八拍步进电机,实现停止、慢速、中速、快速四档状态;

    2. 使用 LIS3DHTR 三轴加速度计采集电机振动数据,并通过 USART2 输出 CSV 格式数据。

    调试过程中也验证了电源稳定性和共地对于 I2C 通信的重要性。电机启动时的电源波动会影响传感器工作,因此后续需要继续优化电源、布线和数据采集方式。

    下一步将使用高采样率采集电机振动数据,结合 NanoEdge AI Studio 训练四类电机状态模型,并部署到 STM32C562RE 上进行实时状态识别。



共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]