【RA-Eco-RA4E2-64PIN-V1.0 开发板】步进电机的串口控制
本文介绍了 RA-Eco-RA4E2-64PIN-V1.0 开发板通过串口指令实现 28BYJ-48 步进电机旋转角度和速度的精确控制的项目设计。
项目介绍
- 硬件连接:28BYJ-48 步进电机、ULN2003 驱动板、Jlink 调试器、供电电源等;
- 工程创建:部署 GPIO 、 UART 、串口中断等配置;
- 工程代码:包括主函数、步进电机驱动代码、串口配置代码等;
- 测试效果:包括串口发送指令、步进电机旋转控制、串口打印状态信息等。
硬件连接
接线方式如下
ULN2003 驱动板 | RA4E2 | 说明 |
---|---|---|
IN1 | P100 | 步进脉冲 A |
IN2 | P101 | 步进脉冲 B |
IN3 | P104 | 步进脉冲 C |
IN4 | P112 | 步进脉冲 D |
VCC | 5V | 驱动板电源 |
GND | GND | 共地 |
串口通信使用板载 USB 转 TTL 工具,对应 P109 (TXD9) 和 P110 (RXD9) 引脚。
实物图
工程创建
- 打开 e2 studio 软件;
- 依次点击
文件
-新建
-瑞萨 C/C++ 项目
-Renesas RA
; - 依次进行工程命名,路径设置,FSP版本,目标开发板选择,Device 选择
R7FA4E2B93CFM
,工具链选择GNU ARM Embedded
,调试器选择 J-Link ,完成工程创建 ;
串口配置
- 进入 FSP 配置界面,打开 Pins 标签页,根据原理图或开发板丝印,将 P109 和 P110 引脚分别配置为 TXD9 和 RXD9 串口模式;
- 新建串口通信堆栈
New Stack
-Connectivity
-UART (r_sci_uart)
; - 串口属性配置,General 标签下的 Channel 改为 9,名称改为
g_uart9
,中断回调函数命名为user_uart_callback
; - 进入 BSP 标签页,配置 RA Common 属性,RA Common 标签下的 Heap size 改为
0x1000
,Main Stack Size 设置为0x2000
以确保堆栈空间充足;
GPIO 配置
-
进入 FSP 配置界面,打开 Pins 标签页,选中 P100 引脚,模式配置为初始低电平的输出模式;
-
同理,将 P101、P104 和 P112 管脚也配置为初始低电平的输出模式;
-
点击
Generate Project Content
按钮,生成工程代码。
流程图
工程代码
在左侧的项目目录中,打开 src/hal_entry.c
文件,添加如下关键代码
hal_entry.c
#include "hal_data.h"
#include "stepper_motor.h"
#include <stdio.h>FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTERfsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;// 你的串口回调函数
void user_uart_callback(uart_callback_args_t * p_args) {if (p_args->event == UART_EVENT_TX_COMPLETE) {uart_send_complete_flag = true;}// 添加接收中断处理else if (p_args->event == UART_EVENT_RX_CHAR) {stepper_motor_uart_callback(p_args); // 调用我们的接收处理函数}
}/*------------- 串口重定向 -------------*/
#ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#endifPUTCHAR_PROTOTYPE {err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);if (FSP_SUCCESS != err) __BKPT();while(uart_send_complete_flag == false) {}uart_send_complete_flag = false;return ch;
}int _write(int fd, char *pBuffer, int size) {for (int i = 0; i < size; i++) {__io_putchar(*pBuffer++);}return size;
}void hal_entry(void)
{/* TODO: add your own code here */// 初始化UARTerr = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);assert(FSP_SUCCESS == err);if (FSP_SUCCESS != err) {printf("UART open failed: 0x%x\r\n", err);return;}printf("RA4E2 - Stepper Motor - UART Debug\r\n");//printf("UART initialized at 115200 baud\r\n");// 初始化步进电机stepper_motor_init();// 测试直接调用 - 确认电机本身工作正常//printf("Testing direct call: rotating 90 degrees...\r\n");//stepper_motor_rotate_degrees(90.0f);//stepper_motor_stop();//R_BSP_SoftwareDelay(2000, BSP_DELAY_UNITS_MILLISECONDS);//printf("Direct call test completed.\r\n");//printf("Now testing UART reception...\r\n");// 启用UART接收uint8_t dummy;err = R_SCI_UART_Read(&g_uart9_ctrl, &dummy, 1);if (err != FSP_SUCCESS) {printf("UART read start failed: 0x%x\r\n", err);}// 设置回调函数g_uart9_ctrl.p_callback = user_uart_callback;// 启用全局中断__enable_irq();printf("Ready to receive angle values.\r\n");printf("Send numbers like: 90, -45, 180, 360\r\n");printf("Waiting for UART data...\r\n");uint32_t counter = 0;while (1) {// 显示系统运行状态if (counter % 100 == 0) {//printf("System running: %lu, Buffer index: %u\r\n", counter, g_uart_buffer_index);}// 检查是否有数据接收if (g_uart_received) {printf("Data received! Processing...\r\n");stepper_motor_process_command();}// 检查缓冲区是否有内容但未完成接收if (g_uart_buffer_index > 0 && !g_uart_received) {printf("Buffer content: ");for (uint16_t i = 0; i < g_uart_buffer_index; i++) {printf("%c(0x%02X) ", g_uart_buffer[i], g_uart_buffer[i]);}printf("\r\n");}R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);counter++;}#if BSP_TZ_SECURE_BUILD/* Enter non-secure code */R_BSP_NonSecureEnter();
#endif
}
stepper_motor.h
新建 stepper_motor.h
头文件,添加如下代码
#ifndef STEPPER_MOTOR_H_
#define STEPPER_MOTOR_H_#include "hal_data.h"
#include <stdbool.h>// 引脚定义
#define MOTOR_PIN_IN1 BSP_IO_PORT_01_PIN_00
#define MOTOR_PIN_IN2 BSP_IO_PORT_01_PIN_01
#define MOTOR_PIN_IN3 BSP_IO_PORT_01_PIN_04
#define MOTOR_PIN_IN4 BSP_IO_PORT_01_PIN_12// 每转步数
#define STEPS_PER_REVOLUTION 509.0f
#define UART_BUFFER_SIZE 32// 全局变量声明
extern char g_uart_buffer[UART_BUFFER_SIZE];
extern volatile uint16_t g_uart_buffer_index;
extern volatile bool g_uart_received;// 函数声明
void stepper_motor_init(void);
void stepper_motor_rotate_steps(int32_t steps);
void stepper_motor_rotate_degrees(float degrees);
void stepper_motor_set_velocity(uint32_t velocity_ms);
void stepper_motor_stop(void);
void stepper_motor_show_help(void);
void stepper_motor_uart_callback(uart_callback_args_t *p_args);
void stepper_motor_process_command(void);
float parse_angle_command(const char *command);#endif /* STEPPER_MOTOR_H_ */
stepper_motor.c
新建 stepper_motor.c
源文件,添加如下代码
#include "stepper_motor.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>// 四相八拍序列
const uint8_t STEP_SEQ[8][4] = {{1, 0, 0, 1}, {1, 0, 0, 0}, {1, 1, 0, 0}, {0, 1, 0, 0},{0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 1}, {0, 0, 0, 1}
};// 全局变量
static uint32_t g_step_delay_ms = 1;void stepper_motor_init(void) {// 初始化引脚R_IOPORT_PinWrite(&g_ioport_ctrl, MOTOR_PIN_IN1, BSP_IO_LEVEL_LOW);R_IOPORT_PinWrite(&g_ioport_ctrl, MOTOR_PIN_IN2, BSP_IO_LEVEL_LOW);R_IOPORT_PinWrite(&g_ioport_ctrl, MOTOR_PIN_IN3, BSP_IO_LEVEL_LOW);R_IOPORT_PinWrite(&g_ioport_ctrl, MOTOR_PIN_IN4, BSP_IO_LEVEL_LOW);printf("Stepper motor initialized.\r\n");
}static void set_coil_state(uint8_t in1, uint8_t in2, uint8_t in3, uint8_t in4) {R_IOPORT_PinWrite(&g_ioport_ctrl, MOTOR_PIN_IN1, in1 ? BSP_IO_LEVEL_HIGH : BSP_IO_LEVEL_LOW);R_IOPORT_PinWrite(&g_ioport_ctrl, MOTOR_PIN_IN2, in2 ? BSP_IO_LEVEL_HIGH : BSP_IO_LEVEL_LOW);R_IOPORT_PinWrite(&g_ioport_ctrl, MOTOR_PIN_IN3, in3 ? BSP_IO_LEVEL_HIGH : BSP_IO_LEVEL_LOW);R_IOPORT_PinWrite(&g_ioport_ctrl, MOTOR_PIN_IN4, in4 ? BSP_IO_LEVEL_HIGH : BSP_IO_LEVEL_LOW);
}void stepper_motor_rotate_steps(int32_t steps) {if (steps == 0) {printf("No steps to rotate.\r\n");return;}int8_t direction = (steps >= 0) ? 1 : -1;uint32_t absolute_steps = (uint32_t)abs(steps);printf("Rotating %s, steps: %lu, delay: %lums\r\n",(direction > 0) ? "CW" : "CCW", absolute_steps, g_step_delay_ms);for (uint32_t i = 0; i < absolute_steps; i++) {if (direction > 0) {// 顺时针for (int phase = 0; phase < 8; phase++) {set_coil_state(STEP_SEQ[phase][0], STEP_SEQ[phase][1],STEP_SEQ[phase][2], STEP_SEQ[phase][3]);R_BSP_SoftwareDelay(g_step_delay_ms, BSP_DELAY_UNITS_MILLISECONDS);}} else {// 逆时针for (int phase = 7; phase >= 0; phase--) {set_coil_state(STEP_SEQ[phase][0], STEP_SEQ[phase][1],STEP_SEQ[phase][2], STEP_SEQ[phase][3]);R_BSP_SoftwareDelay(g_step_delay_ms, BSP_DELAY_UNITS_MILLISECONDS);}}// 每100步输出进度if ((i + 1) % 100 == 0) {printf("Progress: %lu/%lu steps\r\n", i + 1, absolute_steps);}}printf("Rotation completed.\r\n");
}void stepper_motor_rotate_degrees(float degrees) {// 计算步数float steps_float = degrees * (STEPS_PER_REVOLUTION / 360.0f);int32_t steps = (int32_t)steps_float;printf("Angle: %.1f° -> Steps calculation:\r\n", degrees);//printf(" Steps/revolution: %.0f\r\n", STEPS_PER_REVOLUTION);//printf(" Calculated steps: %.1f\r\n", steps_float);//printf(" Rounded steps: %ld\r\n", steps);stepper_motor_rotate_steps(steps);
}void stepper_motor_set_velocity(uint32_t velocity_ms) {g_step_delay_ms = velocity_ms;//printf("Speed set to: %lums/step\r\n", g_step_delay_ms);
}void stepper_motor_stop(void) {set_coil_state(0, 0, 0, 0);printf("Motor stopped.\r\n");
}void stepper_motor_show_help(void) {printf("=== Stepper Motor Simple Control ===\r\n");printf("Send angle values via UART:\r\n");printf(" Examples:\r\n");printf(" 90 - Rotate 90 degrees clockwise\r\n");printf(" -45 - Rotate 45 degrees counter-clockwise\r\n");printf(" 180 - Rotate 180 degrees\r\n");printf(" 360 - Rotate full circle\r\n");printf(" Fixed speed: 1ms/step\r\n");printf("====================================\r\n");
}
stepper_motor_uart.c
新建 stepper_motor_uart.c
源文件,添加如下代码
#include "stepper_motor.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>// 全局变量定义
char g_uart_buffer[UART_BUFFER_SIZE];
volatile uint16_t g_uart_buffer_index = 0;
volatile bool g_uart_received = false;// 固定速度
static uint32_t g_fixed_velocity = 1; // 固定为1ms// 串口中断回调函数
void stepper_motor_uart_callback(uart_callback_args_t *p_args) {if (p_args->event == UART_EVENT_RX_CHAR) {uint8_t received_char = (uint8_t)p_args->data;// 回车或换行表示命令结束if (received_char == '\r' || received_char == '\n') {if (g_uart_buffer_index > 0) {g_uart_buffer[g_uart_buffer_index] = '\0';g_uart_received = true;}g_uart_buffer_index = 0;}// 添加到缓冲区else if (g_uart_buffer_index < UART_BUFFER_SIZE - 1) {g_uart_buffer[g_uart_buffer_index++] = received_char;}// 缓冲区满else {g_uart_buffer_index = 0; // 重置缓冲区}}
}// 解析角度命令
float parse_angle_command(const char *command) {if (command == NULL || strlen(command) == 0) {printf("Empty command\r\n");return 0.0f;}printf("Received command: %s\r\n", command);// 直接转换为浮点数char *endptr;float angle = strtof(command, &endptr);// 检查转换是否成功if (endptr == command) {printf("Invalid number format: %s\r\n", command);return 0.0f;}// 检查是否有额外字符while (*endptr != '\0') {if (!isspace(*endptr)) {printf("Extra characters in command: %s\r\n", endptr);break;}endptr++;}printf("Parsed angle: %.1f°\r\n", angle);return angle;
}// 处理接收到的命令
void stepper_motor_process_command(void) {if (g_uart_received) {// 复制缓冲区内容char local_buffer[UART_BUFFER_SIZE];strncpy(local_buffer, g_uart_buffer, UART_BUFFER_SIZE);printf("Processing command: %s\r\n", local_buffer);// 解析角度float angle = parse_angle_command(local_buffer);if (fabsf(angle) > 0.1f) {printf("Executing: %.1f° at fixed speed: %lums/step\r\n", angle, g_fixed_velocity);// 设置固定速度stepper_motor_set_velocity(g_fixed_velocity);// 执行旋转stepper_motor_rotate_degrees(angle);// 停止电机stepper_motor_stop();printf("Execution completed.\r\n");} else if (fabsf(angle) > 0.0f) {printf("Angle too small: %.1f°\r\n", angle);}// 重置标志g_uart_received = false;g_uart_buffer_index = 0;memset(g_uart_buffer, 0, sizeof(g_uart_buffer));}
}
-
保存代码,右键项目 - 构建程序;
-
右键项目 - 调试项目 - 上传固件至开发板。
测试效果
- 28 BYJ-48 步进电机、ULN2003 驱动板、RA4E2 开发板接线硬件连接完成;
- TypeC - USB 数据线连接开发板串口和电脑;
- 打开串口调试助手,配置对应的波特率等参数;
- 打开串口,即可接收芯片发送的字符串;
同时串口打印输出步进电机状态
» 90
« Data received! Processing...
Processing command: 90
Received command: 90
Parsed angle: 90.0°
Executing: 90.0° at fixed speed: 1ms/step
Angle: 90.0° -> Steps calculation:
Rotating CW, steps: 127, delay: 1ms
Progress: 100/127 steps
Rotation completed.
Motor stopped.
Execution completed.
动态效果
总结
本文介绍了 RA-Eco-RA4E2-64PIN-V1.0 开发板通过串口指令实现 28BYJ-48 步进电机旋转角度和速度的精确控制的项目设计,包括硬件连接、工程创建、工程代码、测试效果等流程,为 Renesas RA 系列产品在工业自动化、科研仪器控制等相关领域的开发设计和应用提供了参考。