前言
记住,要实现一个功能前,应该先想好应该怎么调试该功能,并为其准备好完备的调试手段。
串口打印log信息是最常见的调试手段,下面我要实现该调试手段。
其中,串口的相关知识将在串口章节补充。
功能设计
功能要求如下:
- 打印分类标签,包括trace, errror, debug
- 打印文件名+行号
- 打印关键提示信息和参数
功能实现
-
串口初始化
static VOID UART1_GpioInit(VOID) { GPIO_InitPara GPIO_InitStructure; RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_GPIOA , ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_PIN_9 ; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ; GPIO_Init( GPIOA , &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_PIN_10; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN_FLOATING;; GPIO_Init( GPIOA , &GPIO_InitStructure); } static VOID UART1_Config(VOID) { USART_InitPara USART_InitStructure; RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_USART1 , ENABLE); USART_DeInit( USART1 ); USART_InitStructure.USART_BRR = 115200; /* 波特率 */ USART_InitStructure.USART_WL = USART_WL_8B; /* 数据位 */ USART_InitStructure.USART_STBits = USART_STBITS_1; /* 停止位 */ USART_InitStructure.USART_Parity = USART_PARITY_RESET; /* 校验位 */ USART_InitStructure.USART_HardwareFlowControl = USART_HARDWAREFLOWCONTROL_NONE; /* 流控 */ USART_InitStructure.USART_RxorTx = USART_RXORTX_RX | USART_RXORTX_TX; /* 收发使能 */ USART_Init(USART1, &USART_InitStructure); } VOID DRV_UART1_Init(VOID) { UART1_GpioInit(); UART1_Config(); USART_Enable(USART1, ENABLE); }
-
printf实现
原理是printf最终会调用putchar函数,所以我们把putchar函数实现了即可。
#ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif /* __GNUC__ */ PUTCHAR_PROTOTYPE { /* 等待发送完成 */ while (USART_GetBitState(USART1 , USART_FLAG_TBE) == RESET) { } USART_DataSend(USART1 , (U8)ch); while (USART_GetBitState(USART1 , USART_FLAG_TC) == RESET) { } return ch; }
-
调试宏实现
#define APP_ERROR(fmt, ...) do {printf("[ERROR][%s,%d]: " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__);} while(0)
#define APP_TRACE(fmt, ...) do {printf("[TRACE][%s,%d]: " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__);} while(0)
#define APP_DEBUG(fmt, ...) do {printf("[DEBUG][%s,%d]: " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__);} while(0)
使用举例
如下图,在LED的例子测试,效果如图
代码路径
https://github.com/YaFood/GD32F103/tree/master/TestLED
https://gitee.com/YaFOOD/GD32F103/tree/master/TestLED