STM32 printf重定向串口调试在 STM32 开发过程中经常需要查看程序运行过程中的变量和数据。使用串口将数据发送到电脑再通过串口调试助手查看是一种比较方便的调试方式。本文使用 STM32F1 标准外设库实现 USART1 的基本配置并将 printf 重定向到 USART1。配置完成后可以直接使用 printf() 输出字符串、整数、十六进制数据、浮点数等内容。一、硬件连接首先需要准备一个USB转TTL的串口模块用来实现STM32和电脑之间的通信。这里使用 STM32F1 的 USART1默认引脚为PA9 - USART1_TXPA10 - USART1_RX然后将 STM32 的串口引脚与模块上的 TX 和 RX 进行交叉连接并且要连接上 GND 保证电平一致连接完成后电脑会识别出一个 COM 端口需要提前安装好CH340驱动打开串口调试助手设置为也就是常见的115200 8N1。二、USART1 初始化首先开启 GPIOA 和 USART1 的时钟然后配置 PA9 和 PA10最后配置 USART1 的通信参数。PA9 是 USART1 的发送引脚因此配置为复用推挽输出PA10 是接收引脚配置为上拉输入。USART1 设置为 115200 波特率、8 位数据位、1 位停止位、无校验、无硬件流控同时开启发送和接收功能。完整初始化代码如下voidUSART1_Init(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);GPIO_InitTypeDef GPIO_InitStructure{0};GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_InitStructure.GPIO_PinGPIO_Pin_9;GPIO_Init(GPIOA,GPIO_InitStructure);GPIO_InitStructure.GPIO_PinGPIO_Pin_10;GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;GPIO_Init(GPIOA,GPIO_InitStructure);USART_InitTypeDef USART_InitStructure{0};USART_InitStructure.USART_BaudRate115200;USART_InitStructure.USART_WordLengthUSART_WordLength_8b;USART_InitStructure.USART_StopBitsUSART_StopBits_1;USART_InitStructure.USART_ParityUSART_Parity_No;USART_InitStructure.USART_ModeUSART_Mode_Tx|USART_Mode_Rx;USART_InitStructure.USART_HardwareFlowControlUSART_HardwareFlowControl_None;USART_Init(USART1,USART_InitStructure);NVIC_InitTypeDef NVIC_InitStructure{0};NVIC_InitStructure.NVIC_IRQChannelUSART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority5;NVIC_InitStructure.NVIC_IRQChannelSubPriority0;NVIC_InitStructure.NVIC_IRQChannelCmdENABLE;NVIC_Init(NVIC_InitStructure);USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);USART_Cmd(USART1,ENABLE);}三、实现单字节发送USART 配置完成后先实现最基本的单字节发送函数。voidUSART1_SendByte(uint8_tbyte){while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)RESET);USART_SendData(USART1,byte);}这里等待 USART_FLAG_TXE 置位表示发送数据寄存器为空可以写入新的数据。有了单字节发送函数之后就可以进一步实现字符串发送voidUSART1_SendString(char*str){while(*str){USART1_SendByte(*str);}}例如USART1_SendString(Hello STM32\r\n);此时就可以在电脑的串口调试助手中看到输出内容。不过这种方式只能方便地发送固定字符串如果需要输出变量还需要自己进行数据转换。因此通常会进一步使用 printf()。四、printf重定向C 标准库中的 printf() 最终会通过 fputc() 输出字符因此可以重写 fputc()让每一个字符都通过 USART1 发送。#includestdio.hintfputc(intch,FILE*f){USART1_SendByte((uint8_t)ch);returnch;}这样就完成了 printf() 到 USART1 的重定向。同时需要在 Keil 中开启 MicroLIB以使用精简版 C 运行库减少程序的代码和内存资源占用。五、测试代码配置完成后可以直接使用下面的代码测试printf是否正常工作。#includestm32f10x.h#includeusart.h#includestdio.hintmain(void){USART1_Init();printf(\r\n);printf( STM32 USART Test \r\n);/* 字符串 */printf(String : Hello STM32!\r\n);/* 字符 */printf(Char : %c\r\n,A);/* 有符号整数 */printf(Int : %d\r\n,-12345);/* 无符号整数 */printf(Uint : %u\r\n,12345);/* 十六进制 */printf(Hex : 0x%X\r\n,0x1234ABCD);/* 八进制 */printf(Octal : %o\r\n,12345);/* 长整数 */printf(Long : %ld\r\n,123456789L);/* 浮点数 */printf(Float : %.2f\r\n,3.1415926);/* 多个变量 */intx100;inty200;printf(x %d, y %d\r\n,x,y);/* 模拟传感器数据 */int16_tax1234;int16_tay-567;int16_taz16384;printf(ACC: X%d, Y%d, Z%d\r\n,ax,ay,az);/* 模拟状态信息 */uint8_tstate2;printf(State %d\r\n,state);printf(\r\n);while(1){}}能够正常看到以下内容就说明 STM32 USART1 配置、USB-TTL 连接、串口参数以及 printf 重定向均已正常工作。