历史上的今天
今天是:2025年07月27日(星期日)
2019年07月27日 | STM32串口第一字节消失或者误码的原因和解决方案
2019-07-27 来源:eefocus
现象:stm32复位之后串口打印的第一个字节误码或者消失。
误码原因:误码多是由于端口初始化有问题。使用ST官方v3.5的标准库时,对串口输出端口进行了重复初始化。
如下代码:
/* PA[15:0] 设置为推挽输出 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 串口TX端口PA9 设置为复用推挽输出 */
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);
可以看到串口TX端口所在的PA9引脚被进行了两次初始化,这种情况会导致第一字节误码。
误码解决方案:上面的程序明显是为了偷懒用了GPIO_Pin_All,如果挨个写就没问题了。或者直接操作寄存器也是可以的。
第一字节消失原因:
先看数据手册


一般我们的串口查询方式的发送代码如下,包括ST官方例程里的printf串口打印的实现也是这样的代码。
{
USART_SendData(USART1, dat);
/* Loop until the end of transmission */
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}
}
结合上面的图和程序很容易发现问题。
‘TXE’和‘TC’ 标志位复位值都是‘1’。
那么当我们复位之后通过USART_SendData函数向USART_DR寄存器写入第一个字节,然后通过while查询TC标志的时候,因为TC初始值是‘1’,所以直接就跳出了while,哪怕此时串口并没有开始发送!第一字节就是这样被跳过去了。。
第一字节消失的解决方案:调用USART_SendData函数之前,先将‘TC’标志位清‘0’就OK,代码如下
{
USART_ClearFlag(USART1, USART_FLAG_TC);
USART_SendData(USART1, dat);
/* Loop until the end of transmission */
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}
}
----------------------------------------------------------------printf-----------------------------------------------------------------
在keil中使用printf函数,ST官方有例程,需要在main.c中添加如下代码:
#include #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__ */ /** * @brief Retargets the C library printf function to the USART. * @param None * @retval None */ PUTCHAR_PROTOTYPE { /* Place your implementation of fputc here */ /* e.g. write a character to the USART */ USART_ClearFlag(USART1, USART_FLAG_TC); USART_SendData(USART1, (uint8_t) ch); /* Loop until the end of transmission */ while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} return ch; } 注意:还需要在设置中添加MicroLib才能够正常使用printf函数!!!如下图



史海拾趣
|
1 引言 20世纪末,全球范围内兴起的信息革命浪潮,为汽车工业的突破性发展提供了千载难逢的机遇,信息技术的广泛应用是解决汽车带来的诸如交通拥挤、交通安全、环境污染、能源枯竭等问题的最佳途径。同时,随着汽车电子技术的发展,电子组件 ...… 查看全部问答> |
|
最近用164做了个倒计时,我用的是定时器1的方式1,倒计时可以跑起来,而且完全正常,我现在想用两个外部中断来调整时和分,但是一加上外部中断定时中断都不在响应了,我把外部中断的入口屏蔽了,倒计时正常了。如果我把定时器换为定时器0所有中断都 ...… 查看全部问答> |
|
串口0为片内自带的,初始化的时候,U0FCR这个寄存器总是写不进去值,请教高手~~~ 附代码:[code] INT8U UART0_Init( INT32U baudrate) { INT32U Fdiv; PINSEL0 &= 0 ...… 查看全部问答> |
|
ndis5.1中对应的函数为 VOID NdisInitializeWorkItem( IN PNDIS_WORK_ITEM WorkItem, IN NDIS_PROC Routine, IN PVOID Context ); n ...… 查看全部问答> |
|
;*******************************; 主 程 序;*******************************MAINPG: ANL PCA0MD,#0 ...… 查看全部问答> |
|
MSP430: Trouble Writing Memory Block at 0x0 on Page 0 of Length 0x4: Could not perform access, BSL memory segments are protected. MSP430: GEL: File: D:\\workspace_v5_2\\12864\\Debug\\12864.out: Load failed.… 查看全部问答> |




