打印
[其他ST产品]

STM32串口发送第一个字节丢失怎么办

[复制链接]
132|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sj8zw8|  楼主 | 2023-10-11 16:11 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
第一次遇到这个问题的时候,甚至有点怀疑自己,为什么直到现在才发现有这个问题

直接说解决方法吧,那就是在串口发送字符函数加上下面这句话:

USARTx->SR;
接下来说原因:哈哈哈其实是因为自己比较懒,来了新公司以后直接拿别人的串口相关函数来用了,他的串口发送字符的函数是这样的:
<p>
</p><p>void UART_PutChar(USART_TypeDef* USARTx, uint8_t Data)  //发送单字节</p><p>{  </p><p>    USART_SendData(USARTx,(uint8_t) Data);  </p><p>    while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET){}  </p><p>} </p>


使用特权

评论回复
沙发
sj8zw8|  楼主 | 2023-10-11 16:11 | 只看该作者
乍一看好像没什么问题,但是可以注意到这里while循环是等待USART_FLAG_TC被清0, 但TC 和 TXE 标志位在复位的时候被置1,因此第一个字符发送时while循环就是没有用的,直接跳过去了。这样导致了首次第一个字符还没有被输出,就被后面的字符覆盖掉了。

最终没有问题的串口发送字符函数应该是这样的:

void UART_PutChar(USART_TypeDef* USARTx, uint8_t Data)  //发送单字节
{  
    USARTx->SR;
    USART_SendData(USARTx,(uint8_t) Data);  
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET){}  
}

使用特权

评论回复
板凳
sj8zw8|  楼主 | 2023-10-11 16:11 | 只看该作者
这是因为TC标志位的清0过程是:先读取SR寄存器的值,再向DR寄存器写入数据;

而TXE标志位只需要向DR寄存器写入数据就可以被清0。

使用特权

评论回复
地板
sj8zw8|  楼主 | 2023-10-11 16:12 | 只看该作者
保险起见我现在还在串口初始化完成之后加上了这行代码:

USART_ClearFlag(USART1,USART_IT_TC);
也就是在初始化完成后就先将TC标志位清0。当然也有的人会在发送字符串函数里面加上这句话,以防再出现TC不能及时被清零的问题。但我的习惯是字符串发送函数一般都是调用发送字符函数来实现的,所以就没有加。

使用特权

评论回复
5
sj8zw8|  楼主 | 2023-10-11 16:12 | 只看该作者
两种字符串发送函数:
void UART_PutStr (USART_TypeDef* USARTx, uint8_t *str)    //发送字符串
{
    int i=0;
  while ( i<14)
    {
      UART_PutChar(USARTx, *str);
      str++;
            i++;
    }
}
void USART_SendString(USART_TypeDef* USARTx, unsigned char *DataString,uint16_t len)
{
    int i = 0;
    USART_ClearFlag(USARTx,USART_FLAG_TC);     //发送字符前清空标志位(否则缺失字符串的第一个字符)
    while(i<len)                                                //字符串结束符
    {
        USART_SendData(USARTx,DataString[i]);                       //每次发送字符串的一个字符
        while(USART_GetFlagStatus(USARTx,USART_FLAG_TC) == 0);     //等待数据发送成功
        USART_ClearFlag(USARTx,USART_FLAG_TC);                      //发送字符后清空标志位
        i++;
    }
}

使用特权

评论回复
6
sj8zw8|  楼主 | 2023-10-11 16:14 | 只看该作者
当然这种基础函数各有各的习惯,并不局限于一种实现方法,就像我以前也从来没发现还会有这样的差别。看别的博主说还可以将上面所有判断USART_FLAG_TC标志位的函数改成判断USART_FLAG_TXE标志位,不过我没有尝试。

使用特权

评论回复
7
sj8zw8|  楼主 | 2023-10-11 16:15 | 只看该作者
看来今后还是要多翻翻参考手册了。

使用特权

评论回复
8
Stahan| | 2023-10-11 19:13 | 只看该作者
英文手册真是难搞啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

221

帖子

1

粉丝