首页 > 行业资讯 > 正文

3.1 原理图分析

查看EK-RA6M4的原理图,如下图所示,串口 UART0 挂在了Pmod2接口的 P411,P410 这两个引脚上,而这两个引脚又可以复用为 SPI1 功能的两个引脚。此时,我们将希望修改FSP配置,让这两个引脚作为程序的 printf() 标准输出调试打印。

基于单片机的串口调试打印-单片机串口教程

3.2 Pins引脚配置

接下来我们打开项目中的FSP配置文件,配置使能相应串口的Pin功能,并重新生成代码。

基于单片机的串口调试打印-单片机串口教程1

3.3 Stack配置

接下来我们选择 Stacks , 点击 “New Stack” -> “Connectivity” -> “UART(r_sci_uart)” 添加串口通信功能协议栈。

基于单片机的串口调试打印-单片机串口教程2

如下图所示,我们可以配置串口的相应属性,如波特率等。配置好之后,点击 “Generate Project Content” 按钮,将会自动生成串口的相关代码。

基于单片机的串口调试打印-单片机串口教程3

通过 Name 字段可以修改串口的设备名为 g_uart0,它将在IDE自动生成的文件 ra_gen/hal_data.c/h 中定义串口操作相关的变量; 通过 Channel 字段可以修改串口通道,这里设置为0,下面的 Pins 将自动选择 TXD0、RXD0 的相关引脚; 串口的波特率、奇偶校验位、数据位、停止位、误码率等都在这里设置,具体将定义在 ra_gen/hal_data.c 文件里的 g_uart0_cfg 变量中;

3.4 测试串口通信

接下来,我们可以修改 src/hal_entry.c 源文件,在里面添加串口的初始化 和 发送测试函数如下:

复制void hal_entry (void) { … … #define HELLO_MSG “Hello EK-RA6M4 Board ” R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg); R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)HELLO_MSG, strlen(HELLO_MSG)); while (1) { … … }

其中:

串口的操作函数 R_SCI_UART_Open() 和 R_SCI_UART_Write() 定义在 ra/fsp/src/r_sci_uart/r_sci_uart.c 源文件中,它由e2studio动态生成; 打开串口函数里的两个参数 g_uart0_ctrl 和 g_uart0_cfg ,定义在 ra_gen/hal_data.c/h 文件中,该C文件由上一步配置并动态生成;

使用 USB转串口连接 UART0的相应引脚( TxD0:P411, RxD0:P410 ),重新编译运行程序,串口上将会打印相应的字符串。

基于单片机的串口调试打印-单片机串口教程4

3.5 printf函数实现

首先,我们在项目中创建 src/console.h 头文件如下。

复制#ifndef CONSOLE_H_ #define CONSOLE_H_ #include #include “r_sci_uart.h” #include “hal_data.h” #define g_console(x) &g_uart0_##x #define g_console_ctrl g_console(ctrl) #define g_console_cfg g_console(cfg) extern volatile bool g_console_txComplete; /* Function declaration */ extern fsp_err_t console_initialize(void); extern fsp_err_t deinit_console(void); extern void console_callback(uart_callback_args_t *p_args); extern int _write(int fd,char *pBuffer,int size); #endif /* CONSOLE_H_ */

接下来创建 src/console.c 源文件如下:

复制#include “console.h” /* Tx complete flags */ volatile bool g_console_txComplete = false; int _write(int fd,char *pBuffer,int size) { fsp_err_t err = FSP_SUCCESS; (void)fd; g_console_txComplete = false; err = R_SCI_UART_Write(g_console_ctrl, (uint8_t *)pBuffer, (uint32_t)size); if(FSP_SUCCESS != err) __BKPT(); while(g_console_txComplete == false) { } return size; } fsp_err_t console_initialize(void) { fsp_err_t err = FSP_SUCCESS; /* Initialize console UART */ err = R_SCI_UART_Open (g_console_ctrl, g_console_cfg); FSP_ERROR_RETURN(FSP_SUCCESS == err, err); return FSP_SUCCESS; } fsp_err_t deinit_console(void) { fsp_err_t err = FSP_SUCCESS; /* Close module */ err = R_SCI_UART_Close (g_console_ctrl); FSP_ERROR_RETURN(FSP_SUCCESS == err, err); return FSP_SUCCESS; } void console_callback(uart_callback_args_t *p_args) { switch (p_args->event) { case UART_EVENT_TX_COMPLETE: g_console_txComplete = true; break; default: break; } } Renesas MCU的printf()重定向函数为 _write(),在该函数中我们将通过调用串口发送函数将相关字符串发送出去; 在使用串口发送函数时,我们应该要等待串口发送完成。所以在_write()函数里我们将等待 g_console_txComplete 标志完成; 该标志将会在 console_callback() 函数里更新,这个是串口中断发送的回调函数。接下来我们需要在 FSP 配置中设置它。 在该文件中,我们还添加 了 console 的初始化相关函数;

在添加上面的源文件后,我们需要把自己定义的 console 串口回调函数,加入到串口中断回调函数中去,这时需要修改 FSP 的相关配置。具体方式如下图所示:

基于单片机的串口调试打印-单片机串口教程5

这里通过Callback字段设置串口收发的中断回调函数 console_callback(),它将配置在 g_uart0_cfg 变量中,该函数需要我们自己实现; 另外,我们也可以在这里修改串口中断的优先级;

另外,printf() 函数工作还需要修改堆栈大小,这里我们调整 Heap 的大小为 1024,然后重新生成代码即可。

基于单片机的串口调试打印-单片机串口教程6

如果使能了printf()函数,不用J-link调试的话,开发板上电重启后不能正常启动运行。这是因为printf将会阻塞在 J-link的semihosting输出 ,这时我们在编译时要取消semihosting的支持。这时只需要在下面的项目配置中,删除 –specs=rdimon.specs 链接选项即可。 一般单片机的printf()函数默认并不支持浮点运行和浮点打印,因为它们比较占空间。如果想使能printf()打印浮点类型数的话,可以在项目配置中做如下设置。

基于单片机的串口调试打印-单片机串口教程7

接下来再修改 src/hal_entry.c 源文件如下,此时 printf函数就能够正常工作了。

复制 #include “console.h” void hal_entry (void) { console_initialize(); printf(“Hello EK-RA6M4 Board “); while (1) { }

编译重新运行后,串口上能够正常打印相应字符串。

基于单片机的串口调试打印-单片机串口教程4

猜你喜欢