串口UART=Universal Asynchronous Receiver / Transmitter,通用異步收發傳輸器,是工程師最常用的一種串行外設,常見的接口形式有TTL、 RS232、 RS485,但在實際應用中還是會經常遇到各種問題,比如:丟失一字節數據。下面就結合STM32來講講UART相關內容,談談容易丟失一字節數據的問題。
1、UART幾個標志位
STM32上UART狀態寄存器中的幾個標志位:TXE、TC、RXNE、ORE。這幾個標志位在編程中經常使用,數據丟失有可能就是對它們操作不當而導致出錯。
![9edda93c-7f1b-11ed-8abf-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5KAZZpUAACj8iuUBU4753.png)
TXE=Transmit dataregister empty,發送數據寄存器為空 |
0:數據未傳輸到移位寄存器; 1:數據傳輸到移位寄存器 |
TC=Transmission complete,發送完成 |
0:傳送未完成;
1:傳送已完成 |
RXNE=Read dataregister not empty,讀取數據寄存器不為空 |
0:未接收到數據;
1:已準備好讀取接收到的數據 |
ORE=Overrun error,上溢錯誤 |
0:無上溢錯誤;
1:檢測到上溢錯誤 |
2、UART接收丟失數據
UART接收丟失數據與軟件和硬件都有可能有關系,下面說幾個常見丟失數據的原因及解決辦法。
問題描述 | 解決辦法 | |
1.接收溢出丟失數據 | 指未及時取走數據導致溢出錯誤而丟失數據,通常是發生在大量數據、以查詢方式接收數據的情況下。在MCU啟動過程中、接收數據過多處理不及時、復雜系統響應不及時等情況都會出現數據丟失的情況。 |
(1)及時清除溢出錯誤標志;(2)利用通信協議過濾因數據丟失導致的問題 |
2.接收中斷丟失數據 | 使用UART中斷接收數據相比查詢接收數據的方式更常見,中斷方式比查詢方式響應更及時,但不合理處理同樣也會存在數據丟失的情況。在數據量大時,UART接收中斷函數耗時、優先級低等情況下容易丟失數據。 | (1)中斷函數里減少不必要的耗時;(2)合理分配中斷優先級;(3)使能中斷前清除標志位。 |
3.時鐘誤差導致丟失數據 | 在通信波特率較高的情況下,如果時鐘誤差加大,很可能導致數據丟失。 | (1)使用更高精度晶振;(2)降低通信波特率。 |
3、串口發送的幾種寫法
串口發送的幾種寫法:一、STM32用USART發送字符串
void UART_Send_Message(u8 *Data)
{
while(*Data!='')
{
USART_SendData(USART1, *Data);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);//讀取串口狀態
Data++;
}
}
void main(void)
{
u8 str_buf[500];
memset((char *) &str_buf, 0, sizeof(str_buf));
UART_Send_Message(str_buf);
}
![9f147b74-7f1b-11ed-8abf-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5KAKr1lAADaCfuVxoM451.jpg)
while(SET == USART_GetFlagStatus(USART1,USART_FLAG_RXNE));
含義是:當接收引腳有數據時,狀態寄存器的USART_FLAG_RXNE就會為1,此時USART_GetFlagStatus(USART1,USART_FLAG_RXNE)的返回值就為1(SET),若無數據則為RESET。
二、USART_FLAG_TXE和USART_FLAG_TC怎么用這里主要說的是在特殊情況下發送字符軟件代碼的寫法:特殊情況指的是:1)調用發送字符串函數“發送完”本機立即掉電;2)調用發送字符串函數“發送完”從機立即掉電;【上面兩種主要用于芯片對電源控制的項目中】3)調用發送字符串函數“發送完”立刻進入待機或停機。 主要說的是兩個標志位:USART_FLAG_TXE 和 USART_FLAG_TC。USART_FLAG_TXE發送緩沖區空標志:說明可以往數據寄存器寫入數據了,但并不代表數據發送完成了。USART_FLAG_TC發送完成標志:這個才是代表USART在緩沖區的數據發送完成了,即從機接收到了數據。這兩個標志的區別在于:它們分別表示數據在發送過程中,在兩個不同的階段中的完成情況。TXE表示數據被從發送緩沖區中取走,轉移到的移位寄存器中,此時發送緩沖是空的,可以向其中補充新的數據了。而TC則表示最后放入發送緩沖區的數據已經完成了從移位寄存器向發送信號線Tx上的轉移。所以,判定數據最終發送完成的標志是TC,而不是TXE。
4、UART發送丟失數據
UART發送丟失數據很多工程師都遇到過,通常情況下是傳輸未完成的原因。HAL庫已經有幾年了,但還是有很多工程師都使用標準外設庫,這時如果自己封裝接口不當,就會存在發送最后一字節數據丟失的問題。 1.UART傳輸未完成導致數據丟失:如下代碼,只考慮非空,但實際傳輸并未完成。
void UART_SendByte(uint8_t Data)
{
while(RESET==USART_GetFlagStatus(USART1,USART_FLAG_TXE));
USART_SendData(USART1, Data);
}
但發送非空不代表發送完成,雖然在某些場合更高效,但某些場合就會導致數據丟失。比如:使用此函數發送之后進入休眠、關閉接收端設備電源等情況下。解決辦法:等待發送完成之后,再次發送數據。
void UART_SendByte(uint8_t Data)
{
while(RESET==USART_GetFlagStatus(USART1,USART_FLAG_TXE));
USART_SendData(USART1, Data);
while(RESET == USART_GetFlagStatus(USART1, USART_FLAG_TC));
}
如果使用標準外設庫,要根據實際情況封裝函數,比如發送超時。或者使用HAL封裝的接口,代碼包含判斷傳輸完成:
HAL_StatusTypeDefHAL_UART_Transmit(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize,uint32_tTimeout)
2.線路延時導致數據丟失UART通常會使用232或者485以增加傳輸距離和增強干擾。但是一旦數據線路太長就存在傳輸延時的情況,特別是485傳輸長距離,并使用MCU控制傳輸方向的情況下。解決辦法:軟件增加延時處理;使用通信協議增加應答機制。 3.其他原因UART應用的場景比較多,有些應用在復雜的工廠,干擾較大從而導致數據丟失;有些應用在溫差較大的環境,時鐘偏移較大導致數據丟失。解決辦法需要根據實際情況,有針對性解決問題。比如:使用更好的通信線,軟件做好容錯處理等。 下面講述在不同代碼寫法下,得到不同實驗效果【調試助手接收數據】:常見寫法一:
![9f5bf9e0-7f1b-11ed-8abf-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5KAFZ1aAAALTrKKaP4720.png)
![9f74f774-7f1b-11ed-8abf-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5KAFY3ZAAAdFRfPn5I102.png)
![9f8444ea-7f1b-11ed-8abf-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5KAfCQhAAAKWjsaLQQ839.png)
![9f932b40-7f1b-11ed-8abf-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5KAY4vgAAAc5wK0SCo428.png)
![9fa14630-7f1b-11ed-8abf-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5OAXpnSAAALWgTxmTA313.png)
![9fb6976a-7f1b-11ed-8abf-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5OAN9NVAAAdF6NcPn4436.png)
![9fc86ada-7f1b-11ed-8abf-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5OAMNpNAAAJIDOgFXs744.png)
![9fe21340-7f1b-11ed-8abf-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5OAfdheAAAgHdBothY154.png)
![9ff57f48-7f1b-11ed-8abf-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5OAVNOsAAAJtYBIDMc443.png)
![a0104742-7f1b-11ed-8abf-dac502259ad0.png](https://file1.elecfans.com//web2/M00/9E/13/wKgZomToD5OACAMpAAAdl4VsIbs152.png)
審核編輯 :李倩
-
寄存器
+關注
關注
31文章
5363瀏覽量
121199 -
數據
+關注
關注
8文章
7145瀏覽量
89591 -
STM32
+關注
關注
2272文章
10924瀏覽量
357610 -
uart
+關注
關注
22文章
1243瀏覽量
101776
原文標題:探析STM32上UART丟失的那一字節數據
文章出處:【微信號:雨飛工作室,微信公眾號:雨飛工作室】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
TL16C554發送一串數據,在回環測試中總讀不出最后一字節數據,為什么?
如何限制IPD語句中的最大字節數?
TL16C752D具有64字節FIFO的雙路UART數據表
![TL16C752D具有64<b class='flag-5'>字節</b>FIFO的雙路<b class='flag-5'>UART</b><b class='flag-5'>數據</b>表](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
如何獲取FIFO中接收的字節數?
具有128字節FIFO的TL16C750E UART數據表
![具有128<b class='flag-5'>字節</b>FIFO的TL16C750E <b class='flag-5'>UART</b><b class='flag-5'>數據</b>表](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論