目录
源代码下载地址:
FSP-Project-RA8-uart-test:RenesasR7FA8D1BH(Cortex-M85)串口应用总结资源-CSDN文库
概述
本文主要记录使用Renesas R7FA8D1BH (Cortex®-M85)串口模块时,存在的问题,并详细的记录问题产生的实验现象。笔者通过仔细研究FSP中和UART相关的接口函数和实用案例,通过详细的测试,找到了解决printf函数在打印字符串中不能完整打印数据的问题,并给出解决方案。
1 软硬件
1.1 软硬件环境信息
软硬件信息 | 版本信息 |
---|---|
Renesas MCU | R7FA8D1BH |
Keil | MDK ARM 5.38 |
FSP 版本 | 5.3.0 |
调试工具:N32G45XVL-STB | DAP-LINK |
1.2 开发板信息
笔者选择使用野火耀阳开发板_瑞萨RA8,该板块的主控MCU为R7FA8D1BHECBD,7FA8D1BHECBD的内核为ARM Contex-M85。
1.3 调试器信息
对于R7FA8D1BHECBD芯片,其使用的内核为Cortex®-M85 Core, ST-LINK-V2或者J-LINK-V9不支持下载和调试功能。笔者经过多次尝试,发现N32G45XVL-STB板卡上自带的DAP-LINK可以下载和调试R7FA8D1BHECBD。
下图为N32G45XVL-STB开发板实物图:
2 FSP和KEIL配置串口
2.1 配置参数
根据原理图可知,debug UART使用的PIN引脚为PA14和PA15,其对应UART-9接口。
在FSP上的配置参数如下:
注意点:
使能SCI接口之后,必须保证该模块对应的时钟被使能,其具体配置方法如下:
串口中断配置参数:
2.2 生成基于Keil的软件架构
使用FSP完成参数配置之后,就可以生成基于Keil IED的软件架构,产出项目代码后,使用Keil打卡项目文件,其结果如下:
创建bsp_uart.c文件实现和串口相关的驱动程序。
3 FSP代码
3.1 FSP中UART接口函数
打开RA Flexible Software Package Documentation Release v5.3.0,可以看见如下函数
打开文档链接:
RA/sc_v2024-04_fsp_v5.3.0/fsp_documentation/v5.3.0/fsp_user_manual_v5.3.0/group___s_c_i___b___u_a_r_t.html
该页面上对上述函数做了详细的介绍,FSP还提供了一个UART应用的案例功供程序员参考。
3.2 案例代码介绍
案例代码实现功能:
1)在 r_sci_b_uart_basic_example (void)函数中,实现初始化串口,然后接收一个包的数据;完成数据接收后,由进行发送一个包的数据。
2)中断回调函数:void example_callback (uart_callback_args_t * p_args)
接收数据,并根据事件控制字,判断接收或者,发送数据是否完成
uint8_t g_dest[TRANSFER_LENGTH];
uint8_t g_src[TRANSFER_LENGTH];
uint8_t g_out_of_band_received[TRANSFER_LENGTH];
uint32_t g_transfer_complete = 0;
uint32_t g_receive_complete = 0;
uint32_t g_out_of_band_index = 0;
void r_sci_b_uart_basic_example (void)
{
/* Initialize p_src to known data */
for (uint32_t i = 0; i < TRANSFER_LENGTH; i++)
{
g_src[i] = (uint8_t) ('A' + (i % 26));
}
/* Open the transfer instance with initial configuration. */
fsp_err_t err = R_SCI_B_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
assert(FSP_SUCCESS == err);
err = R_SCI_B_UART_Read(&g_uart0_ctrl, g_dest, TRANSFER_LENGTH);
assert(FSP_SUCCESS == err);
err = R_SCI_B_UART_Write(&g_uart0_ctrl, g_src, TRANSFER_LENGTH);
assert(FSP_SUCCESS == err);
while (!g_transfer_complete)
{
}
while (!g_receive_complete)
{
}
}
void example_callback (uart_callback_args_t * p_args)
{
/* Handle the UART event */
switch (p_args->event)
{
/* Received a character */
case UART_EVENT_RX_CHAR:
{
/* Only put the next character in the receive buffer if there is space for it */
if (sizeof(g_out_of_band_received) > g_out_of_band_index)
{
/* Write either the next one or two bytes depending on the receive data size */
if (UART_DATA_BITS_8 >= g_uart0_cfg.data_bits)
{
g_out_of_band_received[g_out_of_band_index++] = (uint8_t) p_args->data;
}
else
{
uint16_t * p_dest = (uint16_t *) &g_out_of_band_received[g_out_of_band_index];
*p_dest = (uint16_t) p_args->data;
g_out_of_band_index += 2;
}
}
break;
}
/* Receive complete */
case UART_EVENT_RX_COMPLETE:
{
g_receive_complete = 1;
break;
}
/* Transmit complete */
case UART_EVENT_TX_COMPLETE:
{
g_transfer_complete = 1;
break;
}
default:
{
}
}
}
3.3 案例代码存在的问题
笔者在使用案例程序,进行数据发送时,存在如下问题:
问题1:
使用如下代码发送数据时,如果连续发送多包数据,只有第一包发送成功:
err = R_SCI_B_UART_Write(&g_uart0_ctrl, g_src, TRANSFER_LENGTH); assert(FSP_SUCCESS == err); while (!g_transfer_complete) { }
问题2:
连续多次发送数据时,程序会卡在某一个位置,具体位置如下:
问题3:
定义printf函数的接口,其详细代码如下:
int fputc(int ch, FILE *f) { fsp_err_t err; (void)f; err = R_SCI_B_UART_Write(&g_uart0_ctrl, (uint8_t *)&ch, 1); assert(FSP_SUCCESS == err); while (!g_transfer_complete) { } g_transfer_complete = 0; return ch; }
使用printf函数,打印一个字符串,会发现,其只能打印一个byte
4 UART代码实现
4.1 功能函数介绍
1)发送数据函数
代码24行:发送数据接口
代码25行: 判断发送数据是否成功
代码26行:等待中断函数中的发送完成控制字置位
代码28行:实现1ns的延时,这一条语句很重要, 解决了上述3.3小节中的问题
2)设置baud函数
代码40行:计算baud
代码42行:设置baud
代码46行:初始化串口
3)中断函数
代码第57行:处理串口中断事件
代码第86行:发送数据完成事件函数
4)printf函数结构
代码第103行:串口写数据函数
代码第105行:接收数据完成标志位
代码第107行:延时1ns,这个函数非常重要,没有这句语句,printf发送数据时只发送一个byte
4.2 完整代码
在bsp_uart.c文件中实现如下代码:
/*
FILE NAME : bsp_uart.c
Description: debug uart function library
Author : tangmingfei2013@126.com
Date : 2024/06/03
*/
#include "bsp_uart.h"
#include "string.h"
#include <stdarg.h>
#define TRANSFER_LENGTH 128
uint8_t g_src[TRANSFER_LENGTH];
uint8_t g_out_of_band_received[TRANSFER_LENGTH];
uint32_t g_transfer_complete = 0;
uint32_t g_receive_complete = 0;
uint32_t g_out_of_band_index = 0;
void r_sci_b_uart0_sendArry ( uint8_t *str, uint32_t len)
{
fsp_err_t err;
// send the messsage infor
err = R_SCI_B_UART_Write(&g_uart0_ctrl,str, len);
assert(FSP_SUCCESS == err);
while (!g_transfer_complete)
{
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MICROSECONDS);
}
g_transfer_complete = 0;
}
void r_sci_b_uart0_set_baud (uint32_t baud_rate)
{
fsp_err_t err ;
sci_b_baud_setting_t baud_setting;
bool enable_bitrate_modulation = false;
uint32_t error_rate_x_1000 = SCI_B_UART_BAUDRATE_ERROR_PERCENT_5;
err = R_SCI_B_UART_BaudCalculate(baud_rate, enable_bitrate_modulation, error_rate_x_1000, &baud_setting);
assert(FSP_SUCCESS == err);
err = R_SCI_B_UART_BaudSet(&g_uart0_ctrl, (void *) &baud_setting);
assert(FSP_SUCCESS == err);
/* Open the transfer instance with initial configuration. */
err = R_SCI_B_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
assert(FSP_SUCCESS == err);
printf("Board message: R7FA8D1BHECBD-BTB \r\n");
printf("next Board message: R7FA8D1BHECBD-BTB \r\n");
}
void g_uart0_CallbackFunc (uart_callback_args_t * p_args)
{
/* Handle the UART event */
switch (p_args->event)
{
/* Received a character */
case UART_EVENT_RX_CHAR:
{
/* Only put the next character in the receive buffer if there is space for it */
if (sizeof(g_out_of_band_received) > g_out_of_band_index)
{
/* Write either the next one or two bytes depending on the receive data size */
if (UART_DATA_BITS_8 >= g_uart0_cfg.data_bits)
{
g_out_of_band_received[g_out_of_band_index++] = (uint8_t) p_args->data;
}
else
{
uint16_t * p_dest = (uint16_t *) &g_out_of_band_received[g_out_of_band_index];
*p_dest = (uint16_t) p_args->data;
g_out_of_band_index += 2;
}
}
break;
}
/* Receive complete */
case UART_EVENT_RX_COMPLETE:
{
g_receive_complete = 1;
break;
}
/* Transmit complete */
case UART_EVENT_TX_COMPLETE:
{
g_transfer_complete = 1;
break;
}
default:
{
}
}
}
int fputc(int ch, FILE *f)
{
fsp_err_t err;
(void)f;
err = R_SCI_B_UART_Write(&g_uart0_ctrl, (uint8_t *)&ch, 1);
assert(FSP_SUCCESS == err);
while (!g_transfer_complete)
{
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MICROSECONDS);
}
g_transfer_complete = 0;
return ch;
}
/* End of this file */
5 测试
5.1 测试功能描述
使用printf函数打印字符串,PC端使用终端工具接收数据,测试函数如下:
void log_message(void)
{
printf("\n \\ | /\n");
printf("- Conxtex-M85 - test System\n");
printf(" / | \\ build %s %s\n", __DATE__, __TIME__);
printf(" 2024 - 2029 Copyright by mingfei.tang\n");
}
5.2 运行测试代码
编译代码下载到板卡中,其运行结果如下:
串口终端上接收到的数据