0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

UART接收數(shù)據(jù)和解析的常見方式

strongerHuang ? 來源:strongerHuang ? 2023-04-19 14:31 ? 次閱讀

UART串口是嵌入式開發(fā)常見的一種通信方式,但還是有不少人不知道怎么使用串口。

今天就來圍繞串口,簡單分享幾點內容:

串口接收方式

處理接收數(shù)據(jù)

通信協(xié)議解析

串口接收方式

串口接收(通信另一端)的數(shù)據(jù),常見的方式:

輪詢(查詢)接收寄存器

中斷接收數(shù)據(jù)

輪詢,就是間隔一定時間(一般ms,甚至us)去查詢一下接收寄存器是否有數(shù)據(jù),如果有數(shù)據(jù),就處理接收到的數(shù)據(jù)。

中斷,平時沒有數(shù)據(jù)接收時,CPU干自己的事。當有接收數(shù)據(jù)時,UART串口控制器會響應中斷,通知CPU有事干了。

輪詢方式,大家想過有哪些弊端嗎?

效率低:CPU大部分時間都是去做查詢的工作;

響應不實時:如果短時間內有多個接收數(shù)據(jù),CPU正在處理一件相對耗時的事情(比如:發(fā)送一個數(shù)據(jù)包),沒來得及查詢接收到的數(shù)據(jù),此時,數(shù)據(jù)就可能丟失。(特別是早些年串口沒有FIFO功能的時候)

所以,不管是UART串口,還是I2C、 SPI、 CAN等串行通信,用的最多,最常見的還是中斷接收,很少有用輪詢的方式。

我之前維護一個老代碼(坑),CLI串口用輪詢方式,出現(xiàn)丟數(shù)據(jù)、溢出錯誤等眾多問題,讓我還加了好幾個班。。。

處理接收數(shù)據(jù)

中斷有數(shù)據(jù)來了,大家怎么處理接收到的數(shù)據(jù)?

我見過有些小項目,直接在中斷函數(shù)里面做一些應用的情況。比如:串口中斷接收一個傳感器發(fā)過來的數(shù)據(jù),顯示數(shù)據(jù)并做一些響應的動作。

中斷函數(shù),代碼能少盡少,耗時能少盡少,不能處理太多耗時的復雜的邏輯、應用等。

中斷有數(shù)據(jù)來了,一般是通過FIFO方式處理。

1.簡單的數(shù)組接收、應用解析并處理

比如:

static uint8_t gRxCnt = 0;
static uint8_t gRxBuf[10];


void USART1_IRQHandler(void)
{
  //...
  gDgus_RxBuf[gRxCnt] = (uint8_t)USART_ReceiveData(USART1);
  gRxCnt++;
  //...
  
}


void App(void)
{
  //...
  if(0 < gRxCnt)
  {
    //拷貝接收到的數(shù)據(jù)
????gRxCnt?=?0;
????//解析接收數(shù)據(jù)并處理
  }
}

2.中斷函數(shù)接收一幀完整數(shù)據(jù)再處理

比如:

void USART1_IRQHandler(void)
{
  static uint8_t RxCnt = 0;                      //計數(shù)值
  static uint8_t RxNum = 0;                      //數(shù)量


  if((USART1->SR & USART_FLAG_RXNE) == USART_FLAG_RXNE)
  {
    gDgus_RxBuf[RxCnt] = (uint8_t)USART_ReceiveData(USART1);
    RxCnt++;


    /* 判斷幀頭 */
    if(gDgus_RxBuf[0] != DGUS_FRAME_HEAD1)       //接收到幀頭1
    {
      RxCnt = 0;
      return;
    }
    if((2 == RxCnt) && (gDgus_RxBuf[1] != DGUS_FRAME_HEAD2))
    {
      RxCnt = 0;
      return;
    }


    /* 確定一幀數(shù)據(jù)長度 */
    if(RxCnt == 3)
    {
      RxNum = gDgus_RxBuf[2] + 3;
    }


    /* 接收完一幀數(shù)據(jù) */
    if((6 <= RxCnt) && (RxNum <= RxCnt))
    {
      RxCnt = 0;
      OSMboxPost(EventMBox_Touch, gDgus_RxBuf);  //發(fā)送消息郵箱(執(zhí)行觸控操作)
    }
  }
}

中斷函數(shù)解析完一幀數(shù)據(jù),可以通過標志位通知應用(裸機時),也可以通過消息隊列、郵箱等方式發(fā)送到應用(RTOS時)。

3.RTOS隊列、郵箱接收

比如:

void DEBUG_COM_IRQHandler(void)
{
  static uint8_t Data;


  if(USART_GetITStatus(DEBUG_COM, USART_IT_RXNE) != RESET)
  {
    Data = USART_ReceiveData(DEBUG_COM);
CLI_RcvDateFromISR(Data);//下面把這個函數(shù)分離出來了
  }
}


void CLI_RcvDateFromISR(uint8_t RcvData)
{
  static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;


  if(xCLIRcvQueue != NULL)
  {
    xQueueSendFromISR(xCLIRcvQueue, &RcvData, &xHigherPriorityTaskWoken);
  }
}

中斷來一字節(jié)數(shù)據(jù),就通過消息隊列發(fā)送一個字節(jié)數(shù)據(jù),如果沒有及時出來這個數(shù)據(jù),也是存儲在隊列中。

通信協(xié)議解析

像上面第2種,簡單通信協(xié)議,項目相對較小的情況下,可以直接在中斷函數(shù)里面處理。

但是,如果項目相對較大、復雜一點,協(xié)議也先對復雜一點,上面第2種在函數(shù)內部出來方式就不可取。

1.裸機環(huán)境

裸機的情況下,建議用第一種:中斷數(shù)組緩存數(shù)據(jù)(FIFO),應用解析通信協(xié)議。

2.RTOS環(huán)境

RTOS情況下,建議用第三種方式:消息隊列、郵箱等方式接收數(shù)據(jù),然后發(fā)送(通知)應用解析協(xié)議。

當然,以上說的都只是常見的方式,具體還需要結合你項目實際情況。

同時,其它類似I2C、CAN等通信,如有協(xié)議解析,也是類似。

比如之前給大家分享的MavLink,我就用CAN實現(xiàn)過:

void CAN_RX_IRQHandler(void)
{
  static CanRxMsg RxMessage;
  static MAVRCV_QUEUE_TypeDef MAVRcvQueue_Union;


  CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
                                                 //拷貝長度、 數(shù)據(jù)
  MAVRcvQueue_Union.MAVRcvStruct.MAVLink_Len = RxMessage.DLC;
  memcpy(&MAVRcvQueue_Union.MAVRcvStruct.MAVLink_Buf[0], &RxMessage.Data[0], RxMessage.DLC);


  MAVLink_RcvDateFromISR(&MAVRcvQueue_Union.MAVLinkRcv_Queue[0]);
}

最后,以上內容,僅提供思路,代碼不一定適合項目。

審核編輯 :李倩

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5359

    瀏覽量

    120818
  • uart
    +關注

    關注

    22

    文章

    1242

    瀏覽量

    101550
  • 嵌入式開發(fā)

    關注

    18

    文章

    1034

    瀏覽量

    47637

原文標題:UART接收數(shù)據(jù)和解析的常見方式

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    介紹內部EEPROM數(shù)據(jù)讀取和解析

    EEPROM數(shù)據(jù)讀取和解析上一篇我們簡單介紹了熱成像傳感器德國海曼的HTPA 32x32d,本文主要進一步介紹內部EEPROM數(shù)據(jù)讀取和解析。存儲結構一覽在說海曼這個傳感器之前,我們先
    發(fā)表于 12-07 12:14

    stm32 uart1如何通過DMA方式發(fā)送和接收數(shù)據(jù)?

    stm32 uart1如何通過DMA方式發(fā)送和接收數(shù)據(jù)?
    發(fā)表于 12-08 07:05

    如何去實現(xiàn)Stm32 Uart用DMA的方式接收數(shù)據(jù)

    DMA有何用途?如何去實現(xiàn)Stm32 Uart用DMA的方式接收數(shù)據(jù)呢?
    發(fā)表于 12-14 07:37

    如何使用查詢方式通過UART接收數(shù)據(jù)

    使用查詢方式通過UART接收數(shù)據(jù)實驗目的本節(jié)實驗目的為實現(xiàn)串口發(fā)送和接收。這一節(jié)計劃采取查詢的方式
    發(fā)表于 02-17 06:26

    常見數(shù)據(jù)發(fā)送接收處理方式

    文章目錄目的發(fā)送緩存數(shù)據(jù)接收解析總結目的發(fā)送緩存數(shù)據(jù)接收解析總結
    發(fā)表于 02-17 07:34

    uart pdma方式接收不定長數(shù)據(jù)如何解決?

    目前測試過用uart接收超時中斷在pdma方式接收時不起作用,那么有其他方式來解決接收不定長
    發(fā)表于 08-23 08:25

    請問如何接收和解析單片機串口的數(shù)據(jù),怎么防止丟失和斷貞?

    請問大家如何接收和解析單片機串口的數(shù)據(jù),怎么防止丟失和斷貞呢?
    發(fā)表于 11-08 07:57

    光耦隔離的4種常見方法對比

    光耦隔離的4種常見方法對比
    發(fā)表于 05-31 11:06 ?13.2w次閱讀
    光耦隔離的4種<b class='flag-5'>常見方</b>法對比

    STC單片機串口接收一幀數(shù)據(jù)全為0的原因和解決辦法

    STC單片機串口接收一幀數(shù)據(jù)全為0的原因和解決辦法typedef unsigned char BYTE;void UART_RX_DATA_JX(void){ volatile BYT
    發(fā)表于 12-03 19:06 ?16次下載
    STC單片機串口<b class='flag-5'>接收</b>一幀<b class='flag-5'>數(shù)據(jù)</b>全為0的原因<b class='flag-5'>和解</b>決辦法

    K210應用5-使用查詢方式通過UART接收數(shù)據(jù)

    使用查詢方式通過UART接收數(shù)據(jù)實驗目的本節(jié)實驗目的為實現(xiàn)串口發(fā)送和接收。這一節(jié)計劃采取查詢的方式
    發(fā)表于 12-20 19:37 ?10次下載
    K210應用5-使用查詢<b class='flag-5'>方式</b>通過<b class='flag-5'>UART</b><b class='flag-5'>接收</b><b class='flag-5'>數(shù)據(jù)</b>

    MCU批量生產下載程序的幾種常見方

    MCU批量生產下載程序的幾種常見方
    的頭像 發(fā)表于 10-24 17:22 ?1684次閱讀
    MCU批量生產下載程序的幾種<b class='flag-5'>常見方</b>法

    使用UART IDLE中斷接收不定長數(shù)據(jù)

    使用UART IDLE中斷接收不定長數(shù)據(jù)
    的頭像 發(fā)表于 09-18 15:41 ?1165次閱讀
    使用<b class='flag-5'>UART</b> IDLE中斷<b class='flag-5'>接收</b>不定長<b class='flag-5'>數(shù)據(jù)</b>

    無功補償?shù)脑?、作用?b class='flag-5'>常見方式

    無功補償?shù)脑?、作用?b class='flag-5'>常見方式? 無功補償是電力系統(tǒng)中的一項重要技術措施,用于改善電力質量和提高能源利用效率。本文將詳細介紹無功補償?shù)脑怼⒆饔靡约?b class='flag-5'>常見的補償方式。 一、無功補償?shù)脑?無功功率
    的頭像 發(fā)表于 01-19 14:19 ?9665次閱讀

    常見UART收發(fā)方式

    這種方式適合大多數(shù)單片機,只要有中斷就行。使用UART Write發(fā)送數(shù)據(jù)時,數(shù)據(jù)并不是直接寫入到UART發(fā)送器,而是放進了一個環(huán)形緩沖區(qū)中
    的頭像 發(fā)表于 02-19 16:23 ?933次閱讀

    如何采用“狀態(tài)機”解析UART數(shù)據(jù)

    如果一個系統(tǒng)接收上述“不定長度”的協(xié)議幀,將會有一個挑戰(zhàn)--如何高效接收解析。 為簡化系統(tǒng)設計,我們強烈建議您采用“狀態(tài)機”來解析UART
    的頭像 發(fā)表于 03-25 14:29 ?763次閱讀
    如何采用“狀態(tài)機”<b class='flag-5'>解析</b><b class='flag-5'>UART</b><b class='flag-5'>數(shù)據(jù)</b>幀