STM32 | 串口初始化发送0xFE的Bug

  版权信息:
● 本博客使用CC 3.0协议,转载请保留该信息。
● 原文作者: 戴晓天 @ 云飞机器人实验室
● 原文地址: STM32 | 串口初始化发送0xFE的Bug

最近在使用STM32F103串口功能时,发现第一个发出的串口数据帧总是不能被正确识别,在监听串口的原始报文后,我发现原来是数据帧前面多了一个0xFE。在经过一些尝试性的程序调整之后,我发现这个问题竟然和串口时钟初始化所在的位置有关。

这是存在问题的初始化程序:

 /* GPIO Configuration */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* USART configuration */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

USART_InitStructure.USART_BaudRate = u32BaudRate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);

USART_Cmd(USART1, ENABLE); // Enable USART 

这是修改后工作正常的代码:

		/* GPIO Configuration */
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOA, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
		GPIO_Init(GPIOA, &GPIO_InitStructure);

		/* USART configuration */
		USART_InitStructure.USART_BaudRate = u32BaudRate;
		USART_InitStructure.USART_WordLength = USART_WordLength_8b;
		USART_InitStructure.USART_StopBits = USART_StopBits_1;
		USART_InitStructure.USART_Parity = USART_Parity_No;
		USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
		USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
		USART_Init(USART1, &USART_InitStructure);

		USART_Cmd(USART1, ENABLE);				// Enable USART

这两者唯一的区别在于后者将串口时钟初始化放在了GPIO引脚初始化之前!

我现在还没有办法解释这种情况发生的原因,但是我推测是一些隐晦的时序问题导致串口数据线上产生了一个错误的数据,我还将进一步跟踪这个问题。(文中所用编译器为Keil MDK,有读者反应IAR无此问题,待测试验证)

%d bloggers like this: