【RA-Eco-RA4E2-64PIN-V1.0 开发板】步进电机的串口控制

【RA-Eco-RA4E2-64PIN-V1.0 开发板】步进电机的串口控制

本文介绍了 RA-Eco-RA4E2-64PIN-V1.0 开发板通过串口指令实现 28BYJ-48 步进电机旋转角度和速度的精确控制的项目设计。

项目介绍

  • 硬件连接:28BYJ-48 步进电机、ULN2003 驱动板、Jlink 调试器、供电电源等;
  • 工程创建:部署 GPIO 、 UART 、串口中断等配置;
  • 工程代码:包括主函数、步进电机驱动代码、串口配置代码等;
  • 测试效果:包括串口发送指令、步进电机旋转控制、串口打印状态信息等。

硬件连接

接线方式如下

ULN2003 驱动板RA4E2说明
IN1P100步进脉冲 A
IN2P101步进脉冲 B
IN3P104步进脉冲 C
IN4P112步进脉冲 D
VCC5V驱动板电源
GNDGND共地

串口通信使用板载 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 系列产品在工业自动化、科研仪器控制等相关领域的开发设计和应用提供了参考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/94270.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/94270.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PiscCode基于 Mediapipe 的人体多模态关键点检测与可视化系统 —— HumanMultiLandmarker 深度解析

一、引言 在计算机视觉领域&#xff0c;人体关键点检测&#xff08;Human Pose Estimation&#xff0c;HPE&#xff09;一直是研究和应用的热点方向之一。随着深度学习与实时图像处理技术的发展&#xff0c;人体姿势估计已经从传统的 2D 检测走向了 3D 空间建模&#xff0c;并…

文献阅读笔记【物理信息机器学习】:Physics-informed machine learning

文献阅读笔记&#xff1a;Physics-informed machine learningSummaryResearch ObjectiveBackground / Problem Statement问题背景研究现状需解决的问题问题出现的原因分析问题解决思路Method(s)问题建模作者解决问题的方法/算法1. 观测偏差&#xff08;Observational Biases&am…

Linux服务环境搭建指南

实验拓扑概述**实验拓扑&#xff1a; APPSRV&#xff1a; 主机名&#xff1a;appsrv.example.com ip地址&#xff1a;192.168.100.10 网关&#xff1a;192.168.100.254 网卡为NAT模式 STORAGESRV&#xff1a; 主机名&#xff1a;storagesrv.example.com ip地址&#xff1a;192.…

[特殊字符] 数据库知识点总结(SQL Server 方向)

一、数据库基础概念数据库&#xff08;Database&#xff09;&#xff1a;存储和管理数据的容器。数据表&#xff08;Table&#xff09;&#xff1a;以行和列形式组织数据。行&#xff08;Row&#xff09;&#xff1a;一条记录。列&#xff08;Column&#xff09;&#xff1a;字…

【PSINS工具箱】MATLAB例程,二维平面上的组合导航,EKF融合速度、位置和IMU数据,4维观测量

文章目录关于工具箱程序简介代码概述核心功能与步骤运行结果MATLAB代码关于工具箱 本文所述的代码需要基于PSINS工具箱&#xff0c;工具箱的讲解&#xff1a; PSINS初学指导&#xff1a;https://blog.csdn.net/callmeup/article/details/137087932 本文为二维平面上的定位&am…

MiMo-VL 技术报告

摘要 我们开源了 MiMo-VL-7B-SFT 和 MiMo-VL-7B-RL 两个强大的视觉语言模型,它们在通用视觉理解和多模态推理方面均展现出最先进的性能。MiMo-VL-7B-RL 在 40 项评估任务中的 35 项上优于 Qwen2.5-VL-7B,并在 OlympiadBench 上获得 59.4 分,超越了参数量高达 780 亿的模型。…

CTFshow Pwn入门 - pwn 19

先看main函数&#xff1a;fclose(_bss_start) fclose(stdout) 关闭了默认fd1的输出&#xff0c;所以system的结果无法直接看到。 思路&#xff1a; 输出重定向。 ls 1>&0 ls >&0 ls >&2 ###三种写法均可将输出重定向到能回显的终端并获得一个新的交互…

Redis(以Django为例,含具体操作步骤)

简介Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的内存数据结构存储系统&#xff0c;支持多种数据结构&#xff08;如字符串、哈希、列表、集合、有序集合等&#xff09;&#xff0c;可用作数据库、缓存或消息队列。其核心特点包括&#xff1a;高性能&am…

浏览器解析网址的过程

问题浏览器解析网址的过程我的回答当你在浏览器地址栏输入一个URL&#xff08;比如www.example.com&#xff09;并按下回车后&#xff0c;会发生以下一系列步骤&#xff1a;首先&#xff0c;浏览器会解析URL结构&#xff0c;确定要访问的协议、域名和路径。如果你没有输入协议部…

NVIDIA Nsight Systems性能分析工具

* 性能分析 NVIDIA Nsight Systems (推荐)&#xff1a; 这是 NVIDIA 官方推荐的更现代、功能更强大的分析工具。 安装 Nsight Systems在 Docker 容器中启动程序&#xff1a;# 确保你在启动容器时挂载了/usr/local/cuda/targets/x86_64-linux/lib/ 和 /usr/local/nvidia/lib64 #…

后台管理系统-14-vue3之tag标签页的实现

文章目录 1 tag静态实现 1.1 CommonTag.vue(el-tag) 1.2 Main.vue(普通组件标签) 2 tag通过pinia管理 2.1 CommonAside.vue(菜单点击事件) 2.2 stores/index.js(selectMenu()和tags) 2.3 CommonTag.vue(计算属性tags) 3 点击tag之后跳转到指定页面 3.1 views/Mail.vue(商品) 3.…

CMake2: CMakeLists.txt的常用命令

参考链接: 爱编程的大丙 | CMake教程 CMakeLists指令以及常用方法 现代 CMake 教程 文章目录1. cmake_minimum_required( )2. project( )3. add_executable( )4. set()5. aux_source_directory( )6. file( )7. include_directories( )8. add_library( )9. link_libraries()与li…

Ansible入门:自动化运维基础

Ansible 基础概念与安装1. 自动化动机 (Motivation for Automation)概念解释&#xff1a; 指为什么要用Ansible等工具来替代手动管理服务器。核心动机包括&#xff1a;效率与速度&#xff1a; 同时在上百甚至上千台服务器上执行任务&#xff0c;秒级完成&#xff0c;远非人工可…

【测试】基于博客系统的测试报告

前言 本篇博客对简易的博客系统做的测试总结一份测试报告&#xff0c;包含功能测试&#xff0c;自动化测试&#xff0c;性能测试 &#x1f493; 个人主页&#xff1a;zkf ⏩ 文章专栏&#xff1a;测试 若有问题 评论区见&#x1f4dd; &#x1f389;欢迎大家点赞&#x1f44d;…

Oracle:配置让插入语句时id自动输入

Oracle:配置让插入语句时id自动输入无需手动指定&#xff0c;核心是利用 序列&#xff08;Sequence&#xff09; 或 自增列&#xff08;Identity Column&#xff09; 来自动生成唯一值。以下是两种常用方案&#xff1a;方案 1&#xff1a;使用序列&#xff08;Sequence&#xf…

秒杀服务的回调方案

在秒杀场景中&#xff0c;用户点击“抢购”后&#xff0c;后端需要通过异步处理应对高并发&#xff08;避免请求阻塞&#xff09;&#xff0c;同时需通过实时回调机制将最终结果&#xff08;成功/失败&#xff09;推送给客户端并展示。核心方案是&#xff1a;“前端发起请求→后…

php apache无法接收到Authorization header

Apache 默认不传递 Authorization头到后端环境&#xff08;如 PHP&#xff09;。其表现是&#xff1a;print_r($_SERVER)时&#xff0c; 没有 [Authorization] &#xff1a;Array ([Accept-Language] > zh,en;q0.9,zh-CN;q0.8,en-US;q0.7[Accept-Encoding] > gzip, defla…

当我们想用GPU(nlp模型篇)

在个人设备上“把 GPU 真正用起来”做 NLP&#xff0c;分五步&#xff1a;准备 → 安装 → 验证 → 训练/推理 → 踩坑排查。下面每一步都给出可复制命令和常见错误。 ────────────────── 1. 硬件准备 • 一张 NVIDIA GPU&#xff0c;算力 ≥ 6.1&#xff08…

CryptSIPVerifyIndirectData函数分析

可以使用此函数从SIP接口对应的文件中提取签名信息 CryptSIPVerifyIndirectData&#xff1a;将当前文件的哈希结果做为“指纹”&#xff0c;并与从CryptSIPGetSignedDataMsg中提取的签名信息进行比较。 如果哈希结果相同&#xff0c;则意味着当前文件与之前签名的文件相同&…

20250823解决荣品RD-RK3588-MID开发板在充电的时候大概每10s屏幕会像水波纹闪烁一下

20250823解决荣品RD-RK3588-MID开发板在充电的时候大概每10s屏幕会像水波纹闪烁一下 2025/8/23 17:58【结论】&#xff1a;使用直流电源供电&#xff0c;给电池【快速】充电&#xff0c;但是直流电源的电压稳定&#xff0c;电流抖动导致的&#xff01;那个是2.4G 已经知道了我司…