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