痛苦!數據流過大?數據轉換各種組包拆包?指針及數組你試過沒!
今天的是干貨,是真的干。作為一個從業(yè)4年,工齡6年的嵌入式開發(fā)程序員,在做通訊設備領域時最痛苦的事莫過于數據流過大問題,以及數據轉換時各種組包拆包等問題,特別是在控制器內存資源有限時。這種問題更加突出。
以太網數據收發(fā)時以太網的協(xié)議棧占用內存約20Kbyte,單個SOCKET傳輸數據時最少預留了532byte字節(jié)的緩存空間,當取出網絡下傳的數據時,需要拆掉網絡傳輸頭并在末尾增加CRC,串口上行數據時,需要增加網絡傳輸數據頭以及去掉末尾CRC值,如果此時碰到慣用for循環(huán)copy數據或者使用memcpy函數進行數據組包的大佬,內存空間基本就是捉襟見肘。
解決以上問題的辦法之一就是使用指針配合數組進行組包與拆包,如下圖;
預留包頭46字節(jié) | 數據部分536字節(jié) | 末尾預留10字節(jié) |
網絡端向串口發(fā)送:聲明數組時申明比實際數據所需空間更大的數組unsigned char Buff[592],以及一個指針unsigned char *datapoint;將datapoint指向Buff[46]的位置,讀入數據,將數據從指針datapoint指向的位置開始存入數組,同時使用另外的變量unsigned int length存儲當次讀入的數據的長度,進行數據拆包操作時(去包頭6字節(jié)),直接將指針datapoint指向Buff[52]的位置,隨后將計算所得CRC(2byte)值從Buff[46 + length]位置存入數組,并得出最終需要傳輸的長度length+2,串口發(fā)送數據只需要輸入起始地址datapoint,長度length,將數據存入串口發(fā)送環(huán)形隊列即可完成發(fā)送。
代碼如下
unsigned char Buff[592];
unsigned char *datapoint;
unsigned int length;
datapoint = & Buff[46];//指針指向數組中間
net_dataread(datapoint,& length);//讀取數據,獲得數據長度
CRC(&Buff[46+length],datapoint,& length);//獲取校驗值并存入數組
Uart_send(datapoint,length+2);
串口向網絡發(fā)送時,數據從環(huán)形隊列讀出,需要加上TCP modbus協(xié)議的包頭部分(6byte),去掉CRC校驗,同樣聲明數組以及指針、長度變量,將datapoint指向Buff[46]的位置,讀入數據,將數據從指針datapoint指向的位置開始存入數組;將指針指向當前指向地址的前6個地址位置存入6字節(jié),然后按照新的datapoint位置,長度length+4將數據從網絡發(fā)出;
代碼如下
unsigned char Buff[592];
unsigned char *datapoint;
unsigned int length;
datapoint = & Buff[46];//指針指向數組中間
uart_read(datapoint,& length);//讀取數據,獲得數據長度
datapoint = datapoint-6;
memcpy(datapoint,包頭暫存數組首地址,6);
Uart_send(datapoint,length+4);
以上實例簡單說明了利用指針組包的簡單應用,但是在實際應用中可能由于設備需要使用多種協(xié)議,組包方式不同,例如包頭之前加入注冊包等,數據實際讀取完成之后不是直接操作而是直接傳入子函數,進行組包與拆包,此時僅需要傳入datapoint與長度,進子函數,由于datapoint指向的數組前后均有預留空間,子函數內依然可以使用指針,且在Buff[]數組的范圍內,指針可以前后自由移動,在不需要進行大量數據拷貝的前提下完成數組的拆組包過程,同時也避免了反復拷貝數據對空間的浪費。
以上就是指針的簡單應用之一,指針除了對數組,還可以對函數操作,結合結構體,基本上可以在C語言中實現類似C++中類功能。
今天的分享就到這里啦,EBYTE每一天都致力于更好的助力物聯化、智能化、自動化的發(fā)展,提升資源利用率,更多嵌入式工業(yè)計算產品更多資料,感興趣的小伙伴可以登錄我們的億佰特官網和企業(yè)公眾號(微信號:cdebyte)進行了解,也可以直接撥打400電話咨詢技術專員!
相關閱讀: