【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 系列產品在工業自動化、科研儀器控制等相關領域的開發設計和應用提供了參考。