1 复制工程模板
直接复制工程模板里的系统文件和固件库文件到新的工程文件01_USART_Printf
2 新建keil工程
参考上一篇博文:【GD32】---- 移植工程模板及点灯测试
3 编写代码
3.1 创建USART文件
创建一个USART.c
文件,放于05_UserDriver
文件夹中
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); //设置波特率115200usart_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){}
}
测试结果
基本函数功能正常,可以输出内容
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
如果勾选后编译报错,且报错内容为:
.\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时编译报错问题
编译烧录运行
串口调试助手正常显示
串口调试及printf调试成功