[i=s] 本帖最后由 无垠的广袤 于 2025-6-2 05:55 编辑 [/i]<br />
<br />
【AT-START-M412测评】步进电机的驱动与控制
本文介绍了雅特力 AT32M412 开发板实现 28BYJ-48 步进电机的驱动,以及旋转角度和速度的精确控制,并串口打印旋转状态的项目设计。
项目介绍
- AT32M412 开发板结合 ULN2003 步进电机驱动板实现 28BYJ-48 步进电机的转动;
- 通过 4 相 8 拍调节,实现步数与旋转角度的转换,进而精确控制步进电机的旋转角度和速度(相位切换延时);
- 串口打印步进电机的实时旋转状态。
硬件连接
| AT32M412CBT7 | ULN2003驱动板 | 28BYJ-48 步进电机 | 
| PA3 | IN1 | 红 (A+) | 
| PA4 | IN2 | 蓝 (A-) | 
| PA5 | IN3 | 粉 (B+) | 
| PA6 | IN4 | 黄 (B-) | 
| 5V | VCC | 电机电源正极 | 
| GND | GND | 电机电源负极 | 
工程创建
- 打开 AT32 Work Bench 软件,选择工作空间,选择目标芯片 AT32M412CBT7,点击新建;
- 进入 外设-GPIO选项进行参数配置;
- 将引脚 PA3、PA4、PA5 和 PA6 配置为 GPIO 输出模式;

- 使能 USART1 选项,选择 异步模式,配置 PA9 和 PA10 引脚为 USART1 模式;
- 进入 SYSTEM 模块,选择 USART1 串口打印;
- 其他参数均为默认,点击 生成代码并打开项目。
流程图

工程代码
代码主要包括步进电机驱动函数、头文件、主函数三部分。
主函数
#include "at32m412_416_wk_config.h"
#include "wk_usart.h"
#include "wk_gpio.h"
#include "wk_system.h"
#include "step_motor.h"
int main(void)
{
  wk_system_clock_config();
  wk_periph_clock_config();
  wk_nvic_config();
  wk_timebase_init();
  wk_gpio_config();
  wk_usart1_init();
  while(1)
  {
        float angle = 180;
        int8_t speed = 10;
        printf("Rotating %.0f degree clockwise...\r\n", angle);
        Stepper_RotateAngle(angle, speed);
        Stepper_ReleaseTorque();
        wk_delay_ms(1000);
        printf("Rotating %.0f degree counter-clockwise...\r\n", angle);
        Stepper_RotateAngle(-angle, speed);
        Stepper_ReleaseTorque();
        wk_delay_ms(1000);
  }
}
电机驱动代码
新建 step_motor.c 文件,添加如下代码
#include "step_motor.h"
#include <stdlib.h>
#include "wk_system.h"
const uint8_t phase_table[8][4] = {
    {1, 0, 0, 0}, // A
    {1, 1, 0, 0}, // A+B
    {0, 1, 0, 0}, // B
    {0, 1, 1, 0}, // B+C
    {0, 0, 1, 0}, // C
    {0, 0, 1, 1}, // C+D
    {0, 0, 0, 1}, // D
    {1, 0, 0, 1}  // D+A
};
void Stepper_Init(void) {
    gpio_init_type gpio_init_struct;
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
    gpio_init_struct.gpio_pins = GPIO_PINS_3 | GPIO_PINS_4 | GPIO_PINS_5 | GPIO_PINS_6;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(GPIOA, &gpio_init_struct);
    Stepper_ReleaseTorque();
}
void Stepper_Step(int32_t steps, uint16_t delay_ms) 
{
    uint8_t direction = (steps > 0) ? 1 : 0;
    uint32_t step_count = abs(steps);
    int i;
    for (i = 0; i < step_count; i++) 
    {
        static uint8_t phase = 0;
    phase = direction ? (phase + 1) % 8 : (phase + 8 - 1) % 8;
        GPIOA->odt = (GPIOA->odt & ~0x78) |              // PA3-PA6
                (phase_table[phase][0] << 3) |       // PA3
                (phase_table[phase][1] << 4) |       // PA4
                (phase_table[phase][2] << 5) |       // PA5
                (phase_table[phase][3] << 6);        // PA6
    wk_delay_ms(delay_ms);
    }
}
void Stepper_RotateAngle(float angle, int8_t speed)
{
    uint16_t ROUND_VALUE = 4096;  // steps number for one round
  int32_t steps = (int32_t)(ROUND_VALUE * angle / 360.0f);
    float step_delay_ms;
    if (speed < 0 || speed > 10)
        {
        printf("Error: Speed must be between 0 and 10.");
        Stepper_ReleaseTorque();
        return;
        }
    if (speed == 0)
        {
        Stepper_ReleaseTorque();
        return;
        }
    step_delay_ms = (10 - 1) / 9 * (10 - speed) + 1;
    Stepper_Step(steps, step_delay_ms);
}
void Stepper_ReleaseTorque(void) 
{
    GPIOA->odt &= ~(GPIO_PINS_3 | GPIO_PINS_4 | GPIO_PINS_5 | GPIO_PINS_6); // PA3~PA6
}
电机驱动头文件
新建 step_motor.h 文件,添加如下代码
#ifndef __STEP_MOTOR_H
#define __STEP_MOTOR_H
#include "at32m412_416.h"
void Stepper_Init(void);
void Stepper_Step(int32_t steps, uint16_t delay_ms);
void Stepper_RotateAngle(float angle, int8_t speed);
void Stepper_ReleaseTorque(void);
#endif
保存代码,重新构建工程,上传固件至板端,复位运行。
效果演示
正反各旋转 180 度,间隔 1 秒

同时串口打印旋转状态

总结
本文介绍了雅特力 AT32M412 开发板实现 28BYJ-48 步进电机驱动和旋转,并串口打印旋转状态,为 AT32M412 系列单片机的应用和快速开发提供了参考。