这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【let'sdo2026年第3期】任务3:步进电机驱动

共1条 1/1 1 跳转至页

【let'sdo2026年第3期】任务3:步进电机驱动

高工
2026-11-11 21:20:06     打赏

本次活动使用SeeedStudio的步进电机,产品介绍页面如下

https://wiki.seeedstudio.com/Gear_Stepper_Motor_Driver_Pack/

产品的主要规格如下

ItemValue
Operating Voltage5V
Phase4
Reduction ratio1/64
Step Angle5.625°/64
Diameter28mm / Nema 11
Idle In-traction Frequency>500HZ
Idle Out-traction Frequency>1000HZ
Resistance21±7%
Noise≤40dB
Drive modefour-phase eight-stepping

步进电机通过ULN2003驱动,驱动方式为四相八拍(半步)模式,是在“单相通电”和“两相通电”之间交替切换,从而将步距角减半,使转动更平滑。

Step_Motor_Interface.jpg

拍数IN1 (A相)IN2 (B相)IN3 (C相)IN4 (D相)通电状态
11000仅A相
21100A+B相
30100仅B相
40110B+C相
50010仅C相
60011C+D相
70001仅D相
81001D+A相

循环执行这8步,电机就完成一个“电气周期”的旋转。反转时,只需将序列顺序倒过来执行即可。

使用NUCLEO-C562RE的Arduino接口的数字引脚来控制步进电机

Arduino_D7_D4.png

NUCLEO-C562RE开发板和步进电机的驱动接口的连接如下

STM32C562RET6ULN2003 Module
Arduino D7(PA8)IN1
Arduino D6(PB10)IN2
Arduino D5(PB4)IN3
Arduino D4(PC1)IN4
GNDGND
3V3VCC
5VVM
1、CubeMX2工程配置

之前的工程中使用的CubeMX2工程将工程另存为新的工程文件,可以达到工程复用的目的。

Save_CubeMX2_as_project.png

在此基础上添加步进电机驱动引脚的设置,将PA8、PB10、PB4、PC1设置为GPIO输出模式,初始电平设置为低电平。

GPIO_Initial.png

保存并生成代码

gen_project.png

2、步进电机驱动代码

按照四相八拍的顺序控制步进电机的相位变化,从而驱动电机转动,定义电机驱动引脚的宏定义和函数声明如下

stepmotor.h

 #ifndef __STEPMOTOR_H_  
 #define __STEPMOTOR_H_  

 #ifdef __cplusplus  
 extern "C" {  
 #endif  

 #include "main.h"  

 /* 步进电机引脚定义(PA8、PB10、PB4、PC1)*/  
 #define STEPPER_PIN0_PORT   HAL_GPIOA  
 #define STEPPER_PIN0_PIN    HAL_GPIO_PIN_8  
 #define STEPPER_PIN1_PORT   HAL_GPIOB  
 #define STEPPER_PIN1_PIN    HAL_GPIO_PIN_10  
 #define STEPPER_PIN2_PORT   HAL_GPIOB  
 #define STEPPER_PIN2_PIN    HAL_GPIO_PIN_4  
 #define STEPPER_PIN3_PORT   HAL_GPIOC  
 #define STEPPER_PIN3_PIN    HAL_GPIO_PIN_1  

 /* 方向定义 (正数=顺时针,负数=逆时针)*/  
 #define STEPPER_CW   1   /* 顺时针 */  
 #define STEPPER_CCW  -1   /* 逆时针 */  

 /* 公共函数 */  
 void stepper_init(void);  
 void stepper_step(int32_t steps, uint16_t delay_ms);  
 void stepper_rotate(int32_t angle, uint16_t delay_ms);  
 void stepper_stop(void);  

 void stepper_test(void);    /* 测试 */  

 #ifdef __cplusplus  
 }  
 #endif  

 #endif /* C562RE_STEPMOTOR_CMAKE_STEPMOTOR_H_ */

步进电机驱动函数具体实现以及测试代码的实现如下

 #include "stepmotor.h"  

 /* 四相八拍励磁序列(8 个状态) 
    位序: [PA8、PB10、PB4、PC1] 对应 [A, B, C, D] 相 */  
 static const uint8_t step_sequence[8] = {  
     0b0001,  /* 1: A */  
     0b0011,  /* 2: A+B */  
     0b0010,  /* 3: B */  
     0b0110,  /* 4: B+C */  
     0b0100,  /* 5: C */  
     0b1100,  /* 6: C+D */  
     0b1000,  /* 7: D */  
     0b1001   /* 8: D+A */  
 };  

 /* 每圈步数(参考实测值)*/  
 #define STEPPER_STEPS_PER_REV   509U  

 /* 私有:将励磁状态写入 4 个引脚 */  
 static void stepper_write_phase(uint8_t seq)  
 {  
     HAL_GPIO_WritePin(STEPPER_PIN0_PORT, STEPPER_PIN0_PIN,  
                       (seq & 0x01) ? HAL_GPIO_PIN_SET : HAL_GPIO_PIN_RESET);  
     HAL_GPIO_WritePin(STEPPER_PIN1_PORT, STEPPER_PIN1_PIN,  
                       (seq & 0x02) ? HAL_GPIO_PIN_SET : HAL_GPIO_PIN_RESET);  
     HAL_GPIO_WritePin(STEPPER_PIN2_PORT, STEPPER_PIN2_PIN,  
                       (seq & 0x04) ? HAL_GPIO_PIN_SET : HAL_GPIO_PIN_RESET);  
     HAL_GPIO_WritePin(STEPPER_PIN3_PORT, STEPPER_PIN3_PIN,  
                       (seq & 0x08) ? HAL_GPIO_PIN_SET : HAL_GPIO_PIN_RESET);  
 }  

 /** 
   * @brief  初始化步进电机 
   * @note   引脚已在 CubeMX 中配置为输出,需确保初始状态为低电平 
   */  
 void stepper_init(void)  
 {  
     stepper_stop();  
 }  

 /** 
   * @brief  驱动电机旋转指定步数 
   * @note   steps 单位为"完整序列周期"(8 个相位/周期) 
   * @param  steps:     正数=顺时针,负数=逆时针 
   * @param  delay_ms:  步间延时(ms) 
   */  
 void stepper_step(int32_t steps, uint16_t delay_ms)  
 {  
     int32_t direction = (steps >= 0) ? 1 : -1;  
     uint32_t cycles = (steps >= 0) ? (uint32_t)steps : (uint32_t)(-steps);  
     uint32_t i, j;  

     for (i = 0; i < cycles; i++)  
     {  
         for (j = 0; j < 8; j++)  
         {  
             uint8_t phase_idx;  
             if (direction > 0)  
             {  
                 phase_idx = j;       /* 正序 0,1,2,...,7 */  
             }  
             else  
             {  
                 phase_idx = 7 - j;   /* 逆序 7,6,5,...,0 */  
             }  
             stepper_write_phase(step_sequence[phase_idx]);  
             HAL_Delay(delay_ms);  
         }  
     }  
 }  

 /** 
   * @brief  旋转指定角度 
   * @param  angle:     正数=顺时针,负数=逆时针 
   * @param  delay_ms:  步间延时(ms) 
   */  
 void stepper_rotate(int32_t angle, uint16_t delay_ms)  
 {  
     int32_t steps = (int32_t)(angle * (STEPPER_STEPS_PER_REV / 360.0f));  
     stepper_step(steps, delay_ms);  
 }  

 /** 
   * @brief  停止电机:所有线圈断电(释放扭矩) 
   */  
 void stepper_stop(void)  
 {  
     HAL_GPIO_WritePin(STEPPER_PIN0_PORT, STEPPER_PIN0_PIN, HAL_GPIO_PIN_RESET);  
     HAL_GPIO_WritePin(STEPPER_PIN1_PORT, STEPPER_PIN1_PIN, HAL_GPIO_PIN_RESET);  
     HAL_GPIO_WritePin(STEPPER_PIN2_PORT, STEPPER_PIN2_PIN, HAL_GPIO_PIN_RESET);  
     HAL_GPIO_WritePin(STEPPER_PIN3_PORT, STEPPER_PIN3_PIN, HAL_GPIO_PIN_RESET);  
 }  

 /** 
   * @brief  测试:正转 90° → 停 → 反转 90° → 停,循环 
   * @note   用于验证电机接线和驱动是否正常 
   */  
 void stepper_test(void)  
 {  
     /* 顺时针转 90° */  
     stepper_rotate(90, 2);  
     stepper_stop();  
     HAL_Delay(500);  

     /* 逆时针转 90° */  
     stepper_rotate(-90, 2);  
     stepper_stop();  
     HAL_Delay(500);  
 }

将步进电机的驱动代码添加到工程中,并在CMakeLists.txt添加源码的管理

add_source_file_to_cmake.png

3、串口控制电机运行

后续训练中需要控制电机的速度,用于采集不同工况下的传感器数据,通过串口指令控制步进电机的旋转角度以及速度是很不错的选择。程序运行流程如下

[PC/串口终端] 
      │ (USB/串口指令: "90,CW")
      ▼
[NUCLEO-C562RE]
      │ 
      │ 1. 解析指令 → 角度、方向
      │ 2. 角度 → 步数 (步数 = 角度/360 × 4096)
      │ 3. 根据方向选择相序遍历顺序
      ▼
[ULN2003 驱动板] 
      │ (IN1~IN4 接收相序信号,放大电流)
      ▼
[28BYJ-48 步进电机] 
      │ (内置 1/64 减速箱)
      ▼
[输出轴旋转指定角度]

从指令中提取电机旋转的角度和速度的函数实现如下

 /** 
   * @brief  解析 JSON 命令并执行电机动作 
 */  
 static void parse_json_cmd(int *angle, uint32_t *speed)  
 {  
   char *p = (char *)uart_rx_buf;  
   /* 解析两种格式:带空格和不带空格 */  
   if (sscanf(p, "{\"angle\":%d,\"speed\":%lu}", angle, speed) != 2)  
   {  
     sscanf(p, "{\"angle\": %d, \"speed\": %lu}", angle, speed);  
   }  
 }  
 /**

main函数中初始化串口和电机接口,在主循环中解析串口接收到的指令,提供其中的角度和速度值,用于控制电机的转角和速度

    mx_basic_stdio_init(); 
    stepper_init();  
    printf("\r\n=== Stepper Motor JSON Command Test ===\r\n");  
    printf("Usage: {\"angle\": 5, \"speed\": 1.2}\r\n");  
    printf("angle>0 CW, angle<0 CCW, speed=ms/step\r\n\r\n");  

    /* 启动 UART 中断接收 */  
    HAL_UART_ReceiveToIdle_IT(mx_usart2_uart_gethandle(), rx_buf, RX_BUF_SIZE);

    while (1) {
         if (rx_data_ready)  
         {  
           /* 解析指令 */  
           parse_json_cmd(&target_angle, &target_speed);  
           printf("OK: angle=%d, speed=%lu\r\n", target_angle, target_speed);  

           /* 电机转动:正角度=顺时针,负角度=逆时针 */  
           stepper_rotate(target_angle, (uint16_t)target_speed);  
           stepper_stop();  

           /* 清空接收缓冲区 */  
           memset(rx_buf, 0, sizeof(rx_buf));  
           rx_data_len = 0;  
           rx_data_ready = 0;  
           HAL_UART_ReceiveToIdle_IT(mx_usart2_uart_gethandle(), rx_buf, RX_BUF_SIZE);
         }  

         HAL_Delay(10);      

    }

烧录程序到开发板,串口输入电机控制指令{"angle": 5, "speed": 1.2},实现电机控制。电机控制的效果见视频中的演示。





关键词: Let do 3         

共1条 1/1 1 跳转至页

回复

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