STM32串口如何代碼實現更高效的接收消息

這段時間一直在研究多旋翼飛行器,以及其它的事情,博客好外沒更新,再不堅持怕真荒廢了哦。
緩存

在上篇簡單實現MAVLink協議的解析,並演示按照設計好的命令執行對應的事件處理,以及又加入 CRC校驗,實現更穩定的通訊,但在上文結束時也提到當對一個包進行解析及對應事件處理時,是不能接收新的數據,直到事件處理完成,Msg_Rev.Get 狀態設置爲 RECEIVING 後方能再接收新的數據。這時,當事件處理須要必定時間,而又有新的數據不斷髮送過來時,很容易形成數據丟失現象。數據結構

如何提升串口通訊效率,並避免丟包現象了?函數

爲提升效率,首先想到採用DMA方式,然而考慮下發現,接收的數據包是不固定的;而且即便採用DMA,若MAVLink接收緩存仍設計成只接收一條消息大小,丟包問題仍然仍是會有滴。ui

這樣就想有沒方法軟件來實現,就相到若是開闢一個緩存空間,不斷接收的數據都放到那兒,而包的解析處理函數可從這裏面依次取出必定數據,來做處理。這樣只要設計比較合理,因軟件阻塞形成的丟包現象就容易解決了。那麼要設計一個怎樣的緩存呢 ? 其實很容易想到隊列(先進先出的特性),而爲了更有效且合理的利用空間,又就會想到環形隊列這種數據結構 。
spa

首先是其數據結構設計,以及插入刪除操做,很少說,以下代碼:設計

#define MAX_QUEUE_LEN  (4096) // 4K
#define RW_OK   0
#define FULL_ERROR    1
#define EMPTY_ERROR   2

typedef uint8_t boolean;

typedef struct
{
    u16 MemFrontSendIndex ;
    u16 MemRearRecvIndex ;
    u16 MemLength ;
    u8  MemDataBuf[MAX_QUEUE_LEN];
} Queue_Mem_Struct , * Queue_Mem_Struct_p ;

Queue_Mem_Struct Queue_Recv ;

boolean QueueMemDataInsert(u8 data)
{
    if (MAX_QUEUE_LEN == Queue_Recv.MemLength)
    {
        return FULL_ERROR;
    }
    else
    {
        Queue_Recv.MemDataBuf[Queue_Recv.MemRearRecvIndex] = data ;
        //        if(++Queue_Recv.MemRearRecvIndex >= MAX_QUEUE_LEN){Queue_Recv.MemRearRecvIndex = 0;}
        Queue_Recv.MemRearRecvIndex = (Queue_Recv.MemRearRecvIndex + 1) % MAX_QUEUE_LEN;
        Queue_Recv.MemLength ++ ;
        return RW_OK;
    }
}

boolean QueueMemDataDel(u8 *data)
{
    if (0 == Queue_Recv.MemLength)
    {
        return EMPTY_ERROR;
    }
    else
    {
        *data = Queue_Recv.MemDataBuf[Queue_Recv.MemFrontSendIndex]  ;
        Queue_Recv.MemFrontSendIndex = (Queue_Recv.MemFrontSendIndex + 1) % MAX_QUEUE_LEN;
        Queue_Recv.MemLength -- ;
        return RW_OK;
    }
}

這樣,只需經過QueueMemDataInsert函數把串口接收的數據依次填充到緩衝區Queue_Recv.MemDataBuf中去。而在處理時調用QueueMemDataDel函數取出對應個數的數據來處理。這樣就避免整個處理過程當中沒法同時接收數據而產生丟包的問題。固然此時要保證緩衝區的數據及時處理完,不然,尤爲當數據量很大時隊列填充滿後,又會形成數據沒法再填充進來。code

另外至此又會發現,如上設計可結合採用DMA方式。設計的好的話,能夠進一步大幅度提高STM32利用率及系統運行效率!隊列

相關文章
相關標籤/搜索