一、项目背景
在上一篇文章中,我完成了 NUCLEO-C562RE 开发环境搭建,并验证了板载 LED、用户按键、蜂鸣器和 USART2 串口通信。
本篇在此基础上继续完成两项基础功能:
使用 NUCLEO-C562RE 控制 28BYJ-48 类步进电机;
使用 Grove LIS3DHTR 三轴加速度计采集电机振动数据,并通过串口输出 CSV 数据。
这两部分完成后,就可以进一步使用 NanoEdge AI Studio 进行“停止 / 慢速 / 中速 / 快速”四类电机状态模型训练。
二、硬件与软件环境
硬件
- 主控板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 数字排针。
| IN1 | CN9 pin 5 / D4 | PC1 |
| IN2 | CN9 pin 6 / D5 | PB4 |
| IN3 | CN9 pin 7 / D6 | PB10 |
| IN4 | CN9 pin 8 / D7 | PA8 |
| GND | CN6 pin 6/7 | GND |
| 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 加速度计接线
| VCC | CN6 pin 4 / 3V3 | 使用 3.3 V |
| GND | CN6 pin 6/7 | 共地 |
| SDA | CN5 pin 9 / D14 | PB7 / I2C1_SDA |
| SCL | CN5 pin 10 / D15 | PB6 / I2C1_SCL |
| INT1 | CN8 pin 4 / A3 | 可选,接 PB0 |
| SDO | 悬空或接 GND | 悬空地址 0x19,接 GND 为 0x18 |
四、开发环境搭建与外设配置
1. GPIO 配置
| PC13 | GPIO_Input | No Pull | — | B1_USER |
| PA5 | GPIO_Output Push-Pull | No Pull | Low | LED_LD1 |
| PC6 | GPIO_Output Push-Pull | No Pull | Low | BUZZER |
| PC1 | GPIO_Output Push-Pull | No Pull | Low | IN1 |
| PB4 | GPIO_Output Push-Pull | No Pull | Low | IN2 |
| PB10 | GPIO_Output Push-Pull | No Pull | Low | IN3 |
| PA8 | GPIO_Output Push-Pull | No Pull | Low | IN4 |
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 |
| SLOW | 5 ms | 200 步/s |
| MEDIUM | 3 ms | 约 333 步/s |
| FAST | 2 ms | 500 步/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)
初始化流程:
读取 WHO_AM_I 寄存器 0x0F;
确认返回值为 0x33;
配置 CTRL_REG1;
配置 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, ®_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, ®_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
使用 NUCLEO-C562RE 控制 5 V 四相八拍步进电机,实现停止、慢速、中速、快速四档状态;
使用 LIS3DHTR 三轴加速度计采集电机振动数据,并通过 USART2 输出 CSV 格式数据。
七、小结
本篇完成了两项关键功能:
调试过程中也验证了电源稳定性和共地对于 I2C 通信的重要性。电机启动时的电源波动会影响传感器工作,因此后续需要继续优化电源、布线和数据采集方式。
下一步将使用高采样率采集电机振动数据,结合 NanoEdge AI Studio 训练四类电机状态模型,并部署到 STM32C562RE 上进行实时状态识别。


我要赚赏金
