STM32串口调试笔记

现象: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,如果挨个写就没问题了。或者直接操作寄存器也是可以的。

第一字节消失的情况是怎么回事呢?先看数据手册
STM32串口调试笔记_第1张图片
 
STM32串口调试笔记_第2张图片
 一般我们的串口查询方式的发送代码如下,包括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 <stdio.h>

#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函数!!!如下图
STM32串口调试笔记_第3张图片
 

 

 

 

你可能感兴趣的:(STM32串口调试笔记)