久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 5704|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

HAL庫串口中斷RX中的Overrun Error解決方案

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
[首先簡(jiǎn)單研究一下什么時(shí)候會(huì)出現(xiàn)overrun的問題,配置正常的HAL串口中斷接收如下
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
   /* judge interrupt source */
   if(huart ->Instance == USART2)
  {
       //send data to huart1 from huart2
       HAL_UART_Transmit(&huart1, (uint8_t*)recv_buf, 3,0xFFFF);
       //enable RX IT
       HAL_UART_Receive_IT(huart, (uint8_t*)recv_buf, 3);
  }
}
[
可以看出,分三種情況:
  • 發(fā)送數(shù)據(jù)=接收緩存,正常
  • 發(fā)送數(shù)據(jù)<接收緩存,BUF未滿,要等待下一次數(shù)據(jù)到來填滿緩存才會(huì)觸發(fā)中斷
  • 發(fā)送數(shù)據(jù)>接收緩存,BUF已滿,多余部分被截?cái)啵拖乱淮螖?shù)據(jù)一起觸發(fā)中斷

[其中,觸發(fā)兩次接收緩存溢出的時(shí)候,就會(huì)進(jìn)入Overrun Error。
[比如說BUF長度為3,連續(xù)發(fā)兩次長度為4的數(shù)據(jù),就會(huì)進(jìn)入ORE。或者說第一次發(fā)送長度為2的數(shù)據(jù),然后接著發(fā)送兩次長度為3的數(shù)據(jù),也是會(huì)觸發(fā)ORE的,后續(xù)的兩次長度為3的數(shù)據(jù)因?yàn)橛兄耙粭l長度為2的鋪墊,都是視作BUF溢出的數(shù)據(jù)。但是如果發(fā)送一次長度為4的數(shù)據(jù)之后,后續(xù)發(fā)長度一條長度為2的數(shù)據(jù),就會(huì)進(jìn)入正常狀態(tài),是有彈性的。彈性限度為BUF長度的兩倍,也就是說發(fā)送一次長度為6的數(shù)據(jù),會(huì)立即進(jìn)入ORE。
[ORE狀態(tài)下,串口進(jìn)入ORE溢出中斷,無法繼續(xù)接收數(shù)據(jù),但是可以發(fā)送數(shù)據(jù),相當(dāng)于接收數(shù)據(jù)不會(huì)觸發(fā)中斷了。
[對(duì)于ORE溢出常用解決方案有下:
  • 關(guān)閉ORE中斷
  • 采取雙重緩存

[無論哪一種方法都要理解HAL_UART_RxCpltCallback的實(shí)現(xiàn)原理:
  • HAL_UART_IRQHandler(UART_HandleTypeDef *huart)(中斷處理函數(shù))  
  • UART_Receive_IT(UART_HandleTypeDef *huart) (接收函數(shù))
  • HAL_UART_RxCpltCallback(huart)(中斷回調(diào)函數(shù))

[從上到下,層層封裝和調(diào)用。
  1. void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
  2. {
  3. uint32_t isrflags = READ_REG(huart->Instance->SR);
  4. uint32_t cr1its = READ_REG(huart->Instance->CR1);
  5. uint32_t cr3its = READ_REG(huart->Instance->CR3);
  6. uint32_t errorflags = 0x00U;
  7. uint32_t dmarequest = 0x00U;
  8. /* If no error occurs */
  9. errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
  10. //close ORE check
  11. //errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_NE));
  12. if (errorflags == RESET)
  13. {
  14. /* UART in mode Receiver -------------------------------------------------*/
  15. if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
  16. {
  17. UART_Receive_IT(huart);
  18. return;
  19. }
  20. }

復(fù)制代碼
[        想要關(guān)閉ORE中斷,將errorflags中的USART_SR_ORE 這一位去掉即可,相當(dāng)于對(duì)ORE錯(cuò)誤不予檢查,經(jīng)過實(shí)際的測(cè)試是可行的,實(shí)際的表現(xiàn)就是出現(xiàn)ORE溢出之后,串口只接受固定BUF長度的數(shù)據(jù),對(duì)于溢出的數(shù)據(jù)直接丟棄,但是還需要考慮ORE溢出之后,那個(gè)時(shí)刻中BUF肯定是有數(shù)據(jù),但是由于沒有清除BUF,后續(xù)的數(shù)據(jù)直接進(jìn)來會(huì)導(dǎo)致錯(cuò)位,因此想要真正實(shí)現(xiàn)完美的溢出數(shù)據(jù)丟棄處理且不影響后續(xù)的數(shù)據(jù),是要在程序中加入清除BUF的指令的。但是這些方法都會(huì)影響HAL庫的底層代碼,包括去掉USART_SR_ORE 這一位,這也是STM32IDE的一點(diǎn)的不好的地方,底層文件是沒有用戶代碼入口的,修改IOC文件之后,一切都會(huì)回到最初的起點(diǎn)。
[          其次就是雙重緩存,具體的就是將BUF長度設(shè)置為1,這樣子每一次收到一個(gè)字節(jié)的話都會(huì)調(diào)用回調(diào)函數(shù),為什么長度長度大于1的時(shí)候會(huì)發(fā)生ORE,而1的時(shí)候可以接受很長的數(shù)據(jù)而不ORE呢,我猜是因?yàn)?的時(shí)候?qū)⒛承┪恢梦涣耍g接關(guān)閉了ORE,然后用戶自己定義BUF區(qū),一個(gè)一個(gè)去讀取寫入,這個(gè)方法還可以實(shí)現(xiàn)不定長的接收,設(shè)置數(shù)據(jù)結(jié)束幀位就可以了。缺點(diǎn)也很明顯,當(dāng)數(shù)據(jù)很長的時(shí)候,中斷要進(jìn)入很多次,有點(diǎn)占資源了。
[用戶回調(diào)函數(shù)HAL_UART_RxCpltCallback只有接收到設(shè)定的BUF的長度才會(huì)調(diào)用一次,而不是有字節(jié)就調(diào)用,實(shí)現(xiàn)的方法在UART_Receive_IT函數(shù)中:
  1.   if (--huart->RxXferCount == 0U)
  2.   {
  3.      /* Disable the UART Data Register not empty Interrupt */
  4.      __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);

  5.      /* Disable the UART Parity Error Interrupt */
  6.      __HAL_UART_DISABLE_IT(huart, UART_IT_PE);

  7.      /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
  8.      __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

  9.      /* Rx process is completed, restore huart->RxState to Ready */
  10.      huart->RxState = HAL_UART_STATE_READY;

  11. #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
  12.      /*Call registered Rx complete callback*/
  13.      huart->RxCpltCallback(huart);
  14. #else
  15.      /*Call legacy weak Rx complete callback*/
  16.      HAL_UART_RxCpltCallback(huart);
  17. #endif /* USE_HAL_UART_REGISTER_CALLBACKS */
復(fù)制代碼

[if (--huart->RxXferCount == 0U)這一句,每次字節(jié)來都會(huì)調(diào)用UART_Receive_IT,然后RxXferCount減1,這個(gè)變量就是一開始設(shè)置的BUF接收長度,只有等這個(gè)到零了,才會(huì)調(diào)用HAL_UART_RxCpltCallback(huart)
[最終,因?yàn)樵陧?xiàng)目中串口是需要來高頻率接收固定長度的測(cè)量數(shù)據(jù)的,但是在之前要用串口發(fā)送上電指令,這個(gè)指令會(huì)返回一個(gè)和測(cè)量數(shù)據(jù)長度不同的ASK信號(hào),處理方法就是在上電之后,再開啟串口接收,這樣子就可以設(shè)置BUF長度為固定長度,同時(shí)稍微降低測(cè)量的頻率,讓串口接收有足夠的時(shí)間,避免ORE的產(chǎn)生。

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲a视频 | 久久久久国产 | 久久久女女女女999久久 | 亚洲人人 | 一区二区三区在线观看视频 | 少妇特黄a一区二区三区88av | 国产精品日日摸夜夜添夜夜av | 亚洲久在线 | 久久婷婷麻豆国产91天堂 | 亚洲精品aⅴ | 成人免费黄色片 | 欧美精品一区在线发布 | 超碰97人人人人人蜜桃 | 欧洲妇女成人淫片aaa视频 | 亚洲国产精品一区二区三区 | 91天堂网| 极品销魂美女一区二区 | 美女爽到呻吟久久久久 | 天堂网色 | jvid精品资源在线观看 | 一区精品视频在线观看 | 91免费版在线观看 | 色吧久久 | 99在线免费视频 | 中文在线一区二区 | 偷拍自拍第一页 | 成年人黄色一级毛片 | 狠狠艹| 91极品尤物在线播放国产 | 欧美成人精品一区二区男人看 | 久久久久久久国产精品 | 欧美日韩不卡在线 | 久久99精品久久久久久狂牛 | 久久久精品一区二区 | 超碰97免费观看 | 精品久久久999| 成人午夜电影在线观看 | 一a级片 | 中文天堂在线一区 | 久草网址| 久久久久91 |