最近刚好要做一个舵机的状态包反馈,用串口调试助手接收调试。然后发现中断接收数据后,将数据发送给上位机(调试助手)时只接收到了最后一个字节的数据,后来以为数据发送的太快了,然后在每个字节发送完都加了延时,结果发现只接收到第一个数据。

1、 在这个过程中,通过调试我发现中断似乎可以接收到完整的数据。但只要通过串口发给上位机,就只接收到第一个数据。所以我用下面的代码来调试。

            

stm32发送数据给上位机用串口调试助手接收为什么只接收到第一个字节数据?...

stm32发送数据给上位机用串口调试助手接收为什么只接收到第一个字节数据?...

stm32发送数据给上位机用串口调试助手接收为什么只接收到第一个字节数据?...

 

    其中,串口配置为USART1波特率9600,8位数据位,1位停止位,收发模式,无流控。接收中断打开。串口使能。delay_ms(1500)使用systick定时器设置的1.5s的延时函数。

    经过测试,这段代码只能接收到第一个1个字节的数据,也就是只收到0x01。如果延时函数去掉只接收到最后一个字节,即0x03。

    这是为什么呢?

    原来在发送第一个字节数据的时候我没有等待TXE(发送寄存器为空)标志位被置位,导致了第一个数据没有传输完成,第二个就已经在发送了。所以产生了错误。有人想说那我加了延时是吧?按道理说延时1.5S已经够一个字节的传输了,但是这种方法不行,具体原因我也不太清楚,只有通过等待TXE标志置位才能接着发送第二个字节数据。

    代码如下:

stm32发送数据给上位机用串口调试助手接收为什么只接收到第一个字节数据?...

stm32发送数据给上位机用串口调试助手接收为什么只接收到第一个字节数据?...

    这样就可以接收到完整的数据了。

 2、上面讲到的是我们可以接收到完整的数据来进行发送,解决了发送端的问题。其实我当时的感觉是不对的。haha。我并没有接收到完整的数据包。因为我用上面的代码来发送接收到的数据包时,也只接收到一个字节数据,0xff。下面来说说接收端的可能出现的问题。

    (1)首先,我们先来了解一下接收到的这个数据0xff是什么?

    原来,在发送的时候,当TE位被**时,USART会发送一个空闲帧数据,即0xff。空闲帧是什么请自行查阅数据手册。

    也就是说我除了空闲帧,我一个数据都没接收到。

    (2)为什么一个数据都没接收到?

    当我们的中断接收处理程序处理时间太长时,会发生溢出错误,导致后面的数据接收不到。

    当一个字符被接收时,RXNE位被置位。它表明移位寄存器的内容被转移到RDR(数据寄存器),换句话说,数据已经被接收并且可以被读出了。如果RXNE还没有被复位,又接收到一个字符,则发生溢出错误。数据只有当RXNE位被清零后才能从移位寄存器转移到RDR寄存器。RXNE标记是接收到每个字节后被置位的。如果下一个数据已被收到或先前DMA请求还没被服务时,RXNE标志仍是置起的,溢出错误产生。

    溢出错误产生时:

    ----RDR内容将不会丢失。读USART_DR寄存器仍能得到先前的数据。

    ----移位寄存器中以前的内容将被覆盖。随后接收到的数据都将丢失。

    ----如果RXNE=1,上一个有效数据还在接收寄存器RDR上,可以被读出。

    ----如果RXNE=0,这意味着上一个有效数据已经被读走,RDR已经没有东西可读。当上一个有效数据在RDR中被读取的同时又接收到新的(也就是丢失的)数据时,此种情况可能发生。在读序列期间(在USART_SR寄存器读访问和USART_DR读访问之间)接收到新的数据,此种情况也可能发生。

    解决了溢出错误,只接收到一个字节数据的问题基本已经解决了。

    本博文多参考数据手册,建议读者使用USART时将有关部分仔细阅读。