【GD32】---- 使用GD32调试串口并实现printf打印输出

1 复制工程模板

直接复制工程模板里的系统文件和固件库文件到新的工程文件01_USART_Printf
image

2 新建keil工程

参考上一篇博文:【GD32】---- 移植工程模板及点灯测试

3 编写代码

3.1 创建USART文件

创建一个USART.c文件,放于05_UserDriver文件夹中
image

USART.h

/**
 * ************************************************************************
 * 
 * @file USART.h
 * @author zxr
 * @brief 
 * 
 * ************************************************************************
 * @copyright Copyright (c) 2024 zxr 
 * ************************************************************************
 */
#ifndef USART_H_
#define USART_H_

#include "gd32e23x_rcu.h"
#include "gd32e23x_gpio.h"
#include "gd32e23x_usart.h"

#define Printf_GPIO_RCU			RCU_GPIOA		//串口对应GPIO端口的时钟
#define Printf_USART_RCU		RCU_USART0	    //对应串口号的时钟

#define Printf_GPIO			    GPIOA	        //串口对应GPIO端口
#define Printf_GPIO_AF          GPIO_AF_1       //串口是GPIO引脚的复用功能1(查询芯片数据手册)
#define Printf_TX_PIN		    GPIO_PIN_9      //串口对应的GPIO引脚
#define Printf_RX_PIN           GPIO_PIN_10     //串口对应的GPIO引脚

#define Printf_USART		    USART0          //printf所使用的串口

/**
 * ************************************************************************
 * @brief 函数声明
 * ************************************************************************
 */
void USART_Init(void);
void USART_send_char(uint8_t ch);
void USART_send_string(uint8_t *string);

#endif

USART.c

/**
 * ************************************************************************
 * 
 * @file USART.c
 * @author zxr
 * @brief 
 * 
 * ************************************************************************
 * @copyright Copyright (c) 2024 zxr 
 * ************************************************************************
 */
#include "USART.h"

/**
 * ************************************************************************
 * @brief USART初始化配置
 * 
 * 
 * ************************************************************************
 */
void USART_Init(void)
{
	rcu_periph_clock_enable(Printf_GPIO_RCU);	//使能串口对应的GPIO端口的时钟
	rcu_periph_clock_enable(Printf_USART_RCU);	//使能串口时钟
	
	gpio_af_set(Printf_GPIO, Printf_GPIO_AF, Printf_TX_PIN);	//将PA9复用为串口的TX引脚
	gpio_af_set(Printf_GPIO, Printf_GPIO_AF, Printf_RX_PIN);	//将PA10复用为串口的RX引脚
	
	gpio_mode_set(Printf_GPIO, GPIO_MODE_AF, GPIO_PUPD_PULLUP, Printf_TX_PIN);	//复用模式,上拉
	gpio_mode_set(Printf_GPIO, GPIO_MODE_AF, GPIO_PUPD_PULLUP, Printf_RX_PIN);	//复用模式,上拉
	
	gpio_output_options_set(Printf_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Printf_TX_PIN);//推挽输出
	gpio_output_options_set(Printf_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Printf_RX_PIN);//推挽输出
	
	usart_deinit(Printf_USART);	//复位串口
	usart_baudrate_set(Printf_USART, 115200);	//设置波特率115200
	usart_parity_config(Printf_USART, USART_PM_NONE);	//无校验位
	usart_word_length_set(Printf_USART, USART_WL_8BIT);	//8位数据长度
	usart_stop_bit_set(Printf_USART, USART_STB_1BIT);	//1位停止位
	
	usart_enable(Printf_USART);	//使能串口
	usart_transmit_config(Printf_USART, USART_TRANSMIT_ENABLE);	//使能串口发送功能
	usart_receive_config(Printf_USART, USART_RECEIVE_ENABLE);	//使能串口接收功能
}

/**
 * ************************************************************************
 * @brief USART发送单个字符
 * 
 * @param[in] ch  要发送的字符
 * 
 * ************************************************************************
 */
void USART_send_char(uint8_t ch)
{
	usart_data_transmit(Printf_USART, (uint8_t)ch);	//发送一个字符
	while(usart_flag_get(Printf_USART, USART_FLAG_TBE) == RESET);	//等待发送数据缓冲区标志置位
	
}

/**
 * ************************************************************************
 * @brief USART发送字符串
 * 
 * @param[in] string  字符串
 * 
 * ************************************************************************
 */
void USART_send_string(uint8_t *string)
{
	while(string && *string)	//地址为空或者值为空跳出
	{
		USART_send_char(*string++);
	}
}



3.2 USART基本功能测试

/**
 * ************************************************************************
 * 
 * @file main.c
 * @author GD32
 * @brief 
 * 
 * ************************************************************************
 * @copyright Copyright (c) 2024 GD32 
 * ************************************************************************
 */
#include "gd32e23x.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"

#include "USART.h"
/**
 * ************************************************************************
 * @brief 主函数main
 * 
 * 
 * @return 
 * ************************************************************************
 */
int main(void)
{
	USART_Init();
	USART_send_string("hello\n");
	while(1)
	{

	}
}

测试结果

基本函数功能正常,可以输出内容
image

3.3 重定向printf

为了方便打印数字,小数等内容,重定向printf函数。首先c语言的printf函数中不断循环调用fputc函数,所以需要重写fputc函数,这个函数的功能就是打印输出一个字符。

添加头文件

打开USATR.h文件,在里面添加#include "stdio.h"

添加函数声明

然后再声明一下int fputc(int ch, FILE *f);函数

重写fputc函数

USART.c中,重写fputc函数

/**
 * ************************************************************************
 * @brief 重定向printf函数
 * 
 * @param[in] ch  Comment
 * @param[in] f  Comment
 * 
 * @return 
 * ************************************************************************
 */
int fputc(int ch, FILE *f)
{
    usart_data_transmit(Printf_USART, (uint8_t) ch);
    while(RESET == usart_flag_get(Printf_USART, USART_FLAG_TBE));
    return ch;
}

3.4 测试printf

补充main函数

main.c中添加测试代码

/**
 * ************************************************************************
 * 
 * @file main.c
 * @author GD32
 * @brief 
 * 
 * ************************************************************************
 * @copyright Copyright (c) 2024 GD32 
 * ************************************************************************
 */
#include "gd32e23x.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"

#include "USART.h"
/**
 * ************************************************************************
 * @brief 主函数main
 * 
 * 
 * @return 
 * ************************************************************************
 */
int main(void)
{
	USART_Init();
	//USART_send_string("hello\n");
	printf("hello\n");
	printf("%d\n", 10);
	while(1)
	{

	}
}

勾选微库

编译前记得勾选微库Use MicroLIB
image

如果勾选后编译报错,且报错内容为:
.\Objects\01_USART_Printf.axf: Error: L6218E: Undefined symbol __use_two_region_memory (referred from startup_gd32e23x.o).

.\Objects\01_USART_Printf.axf: Error: L6218E: Undefined symbol __initial_sp (referred from entry2.o).
解决办法可参考我的博文:关于keil中勾选微库"Use MicroLIB"调试printf时编译报错问题

编译烧录运行

串口调试助手正常显示
image

串口调试及printf调试成功

posted @ 2024-05-07 16:29  晚风也温柔  阅读(110)  评论(0编辑  收藏  举报