單片機下串口(UART)協議包接收程序


該段代碼僅僅是本人使用過的一段,非原創也不算抄襲,如果代碼有什么不恰當、不優雅的地方,歡迎在評論留下寶貴的建議和意見。

 

代碼編寫在51單片機上,用於從接收緩沖區中提取有用數據(協議包)。基本邏輯亦可用於其他語言,其他情況下的接收程序。

數據的轉移主要分了3步,接收緩沖區=》待處理數據=》有用數據。

接收緩沖區提取到待處理數據:由於可能下一個包馬上就要過來,所以應把數據提取出來再做處理,以免直接處理的過程中收到新的數據造成混亂。

待處理數據提取到有用數據:例如在某些環境下,會收到其他協議的包(由其他程序處理),或者帶有地址區分是否發給本機的包,所以需要設置一些條件來提取真正有用的數據。

 

單片機串口UART在接收中斷程序中寫入接收緩沖區,一定時間沒有收到數據則標志為接收空閑(完成一個包的接收)。

本段代碼先判斷串口處於接收空閑狀態,然后判斷包太小則放棄,認為是錯誤包。

失能中斷,把接收緩沖區提取出來后,重新使能中斷,以盡快准備好接收下一次數據傳輸。

然后則開始搜索包頭(幀頭),然后把符合協議的部分提取出來,清空包頭以免重復處理,最后解析該包。

int WaitingBuf(void)
{
    int return_err=5;
    uint8 bytecnt;
    uint8 i;    
    uint16 dest_p;
    uint16 ScanningAddr;
    uint8 buffer[RXBUFSIZE];//如果太小,收到數據CNT比他大,則程序崩潰    
    uint8 ReceiveBuf[20];
    
    if(rs_state==RS_IDLE)//uart中斷接受處於空閑狀態,表示一個包接受結束,利用一定時間內沒有收到數據判斷
    {        
        bytecnt=r_count;
        if(bytecnt<=5)//包太小,誤傳,錯誤包,電壓不穩定等 
            return 3;
        UA_IER &= (~RDA_IEN | ~RLS_IEN);    //禁止中斷,提取本次接收完成后,接受緩沖區的數據
        for(i=0;i<bytecnt;i++)
        {
            buffer[i]=r_buf[i];
        }
        r_count=0;//讓緩沖區重新從頭開始儲存
        UA_IER |= (RDA_IEN | RLS_IEN);   //使能中斷,提取數據完畢,准備下一次接收數據
        for(ScanningAddr=0;ScanningAddr<(bytecnt-1);ScanningAddr++) //掃描數據
        {
            if(buffer[ScanningAddr] == 0xEF && buffer[ScanningAddr+1] == 0x01)//找到包頭
            {
                for(dest_p=0;dest_p<(bytecnt-ScanningAddr);dest_p++)//從本次收到的數據中,提取有用的部分(符合協議的)
                {
                    ReceiveBuf[dest_p]=buffer[ScanningAddr+dest_p];    
                }
                buffer[ScanningAddr]=0;//清除包頭,以免重復處理
                buffer[ScanningAddr+1]=0;
                return_err = ReceiveBufAnalysis(ReceiveBuf);//把收到的協議包送去處理
                break;//如果存在有1個以上數據包將快速發送過來的話,可能緩存區一次將包含2個有用的包,需要去掉該break;
            }
        }    
    }
    else 
        return_err = 2;
    return return_err;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM