天天看點

STM32 LL庫序列槽丢包問題與解決

在CubeMx生成代碼時,預設為 HAL 庫,但也可以指定為 LL庫,LL庫基本是直接操作寄存器,功能較為單一,但是效率更高。序列槽使用HAL如果每次接收一個字次,由于HAL庫的效率,容易丢包,若一次性接收多個位元組,又需要固定的位元組數。

于是這次使用了 LL 庫,在LL庫中:

LL_USART_TransmitData8();

為發送一個位元組函數,通過檢視定義可知,它直接操作了DR寄存器,是以效率很高。

這次想設計一個簡單的程式:當收到字元A的時,發送字元E,但是發現居然有丢包的現象,這是由于程式邏輯問題導緻的,這也是庫函數使用者對寄存器操作不熟悉的原因,最後調整程式如下:

while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      static uint8_t recv;

      if(USART1->SR&(1<<5))                          //如果接受到資料
      {
          recv = LL_USART_ReceiveData8(USART1);      //讀取資料
          if(recv == 'A')                            //如果是字元A
          {
             LL_USART_TransmitData8(USART1,'E');     //發送字元E
             while((USART1->SR&0X40)==0);            //等待資料發送完成
             
          }
      }

    /* USER CODE BEGIN 3 */
  }
           

上文程式不斷的輪詢,判斷是否接受到資料,再進行值的讀取,将資料發送出去以後,等待資料發送完成,經測試效果穩定:

STM32 LL庫序列槽丢包問題與解決

可以看到,100B/s 的速度發送了近4萬個位元組,也接到同樣的資料,說明程式未丢包。

如果把

recv = LL_USART_ReceiveData8(USART1)

,移出

if

語句,如下:

// !!錯誤代碼示例
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      static uint8_t recv;
      recv = LL_USART_ReceiveData8(USART1);          //讀取資料
      if(USART1->SR&(1<<5))                          //如果接受到資料
      {
          if(recv == 'A')                           //如果是字元A
          {
             LL_USART_TransmitData8(USART1,'E');    //發送字元E
             while((USART1->SR&0X40)==0);           //等待資料發送完成
             
          }
      }
    /* USER CODE BEGIN 3 */
  }
           

即未接收到新的資料,也不斷的讀取DR的值,程式測試會出現比較頻繁的丢包。

STM32 LL庫序列槽丢包問題與解決

可以看到,同樣的資料發送,241個位元組,才收到92個位元組,丢包嚴重。原因可能是頻繁的調用

LL_USART_ReceiveData8()

(讀取DR的值),導緻序列槽外設一直忙碌,最後導緻了丢包。

繼續閱讀