大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是嵌入式里串口(UART)自動波特率識別程序設計與實現。

 

本篇是 《串口(UART)自動波特率識別程序設計與實現(中斷)》 的續集,上一篇我們利用 GPIO 模塊自帶的下降沿中斷功能實現了 RXD 電平跳變捕捉與計時,今天我們再試試古老的輪詢 RXD 管腳電平的方法去實現同樣的功能。

 

輪詢法Z大的缺點是會阻塞系統(不考慮 RTOS 調度),但是它也有中斷法所沒有的特點(或者說不太方便做到的),在做輪詢時,我們可以采取一些經典的管腳電平軟件消抖措施,從而降低誤識別率。

 

  • 程序主頁:https://github.com/JayHeng/cortex-m-apps/tree/master/components/autobaud

 

一、串口(UART)自動波特率識別程序設計

 

1.1 函數接口定義

輪詢法與中斷法函數接口保持一致,詳見 《串口(UART)自動波特率識別程序設計與實現(中斷)》  1.1 小節,兩者共享頭文件:autobaud.h,這樣方便項目設計時自由切換自動波特率識別方法。

 

1.2 識別設計思想

關于識別的思路,輪詢法與中斷法也是一致的,詳見 《串口(UART)自動波特率識別程序設計與實現(中斷)》  1.2 小節,但是輪詢法里多了手動檢測 RXD 引腳電平下降沿跳變的過程。

 

引腳電平跳變檢測其實也很簡單,就是不斷讀取引腳輸入電平值,并比較相鄰兩次輸入電平值,如果發現不一致,則是跳變發生之時。如果前一次電平值是高,那么此時便是下降沿。

 

 

1.3 主代碼實現

根據上一小節描述的設計思想,我們很容易寫出下面的主代碼(autobaud_poll_v2.1.c),代碼里痞子衡都做了詳細注釋。相比中斷法源代碼,我們其實只需要修改 autobaud_get_rate() 函數實現如下:

 

  //! @brief 讀取GPIO管腳輸入電平  extern uint32_t read_autobaud_pin(void);    bool autobaud_get_rate(uint32_t *rate)  {      // 僅當電平為低(非空閑態)時才開始識別      uint32_t currentEdge = read_autobaud_pin();      if (currentEdge != 1)      {          pin_transition_callback();          uint32_t previousEdge = currentEdge;          while (s_transitionCount < kFirstByteRequiredFallingEdges + kSecondByteRequiredFallingEdges)          {              // 檢查是否有電平翻轉              currentEdge = read_autobaud_pin();              if (currentEdge != previousEdge)              {                  // 僅當電平翻轉是下降沿時                  if (previousEdge == 1)                  {                      pin_transition_callback();                  }                  previousEdge = currentEdge;              }          }            // 計算出實際檢測到的波特率值          uint32_t calculatedBaud =              (microseconds_get_clock() * (kNumberOfBitsForFirstByteMeasured + kNumberOfBitsForSecondByteMeasured)) /              (uint32_t)(s_firstByteTotalTicks + s_secondByteTotalTicks);          // 對實際檢測出的波特率值做對齊處理          // 公式:rounded = stepSize * (value/stepSize + .5)          *rate = ((((calculatedBaud * 10) / kAutobaudStepSize) + 5) / 10) * kAutobaudStepSize;            return true;      }      else      {          return false;      }  }  

 

二、串口(UART)自動波特率識別程序實現

前面講的都是硬件無關設計,但Z終還是要落實到具體 MCU 平臺上的,其中 GPIO 讀取部分是跟 MCU 緊相關的。我們以恩智浦 i.MXRT1011 為例來介紹硬件實現。

 

2.1 軟件消抖實現

恩智浦 MIMXRT1010-EVK 有板載調試器 DAPLink,這個 DAPLink 中也集成了 USB 轉串口的功能,對應的 UART 引腳是 IOMUXC_GPIO_09_LPUART1_RXD 和 IOMUXC_GPIO_10_LPUART1_TXD,我們就選用這個管腳 GPIO1[9] 做自動波特率檢測,引腳電平讀取函數代碼如下:

 

  #define AUTOBAUD_PIN_DEBOUNCE_READ_COUNT (20U)    uint32_t read_autobaud_pin(void)  {      // 多次讀取管腳輸入電平值      uint32_t readCount = 0;      for (uint32_t i = 0; i < AUTOBAUD_PIN_DEBOUNCE_READ_COUNT; i++)      {          readCount += GPIO_PinRead(GPIO1, 9);      }        // 如某電平值出現幾率超過半數,則認定為有效電平      return (readCount < (AUTOBAUD_PIN_DEBOUNCE_READ_COUNT / 2)) ? 0 : 1;  }  

 

關于 I/O 軟件消抖,一般有兩種實現:一、是兩次 I/O 讀取之間加一D延時(us級別),如兩次值一樣,則認定有效,否則重復此過程;二、是多次讀取 I/O 值,取其中出現幾率超過一半的那個電平值。前者主要適用按鍵的場景,后者更適用本文輪詢法自動波特率識別場景。

 

2.2 在MIMXRT1010-EVK上實測

Z后就是在板子上實測,因為在設計上輪詢法與中斷法接口是一致的,因此測試主函數代碼完全不用修改,詳見 《串口(UART)自動波特率識別程序設計與實現(中斷)》  2.2 小節。測試結果同樣達到了預期效果。

 

至此,嵌入式里串口(UART)自動波特率識別程序設計與實現痞子衡便介紹完畢了,掌聲在哪里~~~