C語言小結--float short等非char型資料傳輸問題
阿新 • • 發佈:2018-11-02
1.問題描述
最近開發中需要使用can傳輸float和short型資料,我們知道一般的嵌入式平臺的通訊埠如CAN、串列埠、網路等都是以位元組(byte)為單位傳輸的,那麼怎麼傳輸float、short等型別的資料呢?尤其是帶符號位的資料。
2.解決思路
使用共用體(union)
首先建立一個結構體,然後在結構體成員中建立共用體。如下所示:
//底盤狀態結構體 typedef struct _T_UnderPanState { uint32_t TimeStopCount; //運動停止計時 bool TimeCountFlag; //開始運動計數標誌 bool TimeStopCountFlag; //運動停止計時標誌 int16_t GetLeftSpeed; //左輪反饋速度 int16_t GetRightSpeed; //右輪反饋速度 float InitDenc[3]; //起始編碼器位置 union { int16_t MotorSpeed; //電機轉速 uint8_t ucMotorSpeed[2]; }; union { uint32_t TimeCount; //運動時間計數 uint8_t ucTimeCount[4]; }; union { float Distance; //運動距離 mm uint8_t ucDistance[4]; }; union { float Angle; //轉動角度 uint8_t ucAngle[4]; }; union { float VxMMPS; //直線運動速度 mm/s uint8_t ucVxMMPS[4]; }; union { float OmegaRPM; //旋轉速度 uint8_t ucOmegaRPM[4]; }; }T_UnderPanState; extern T_UnderPanState UnderPanState;
這麼做的好處就是在運算的時候,我們可以直接使用float型資料做運算,然後在傳輸的時候,使用uint8_t型別的陣列傳輸,在接收端,同樣定義一個這樣的結構體,使用uint8_t型別的陣列接收資料,然後使用float型的變數做運算,這樣不但節省了記憶體,而且跨平臺,通用性好。
接下來貼一個我的打包傳送程式碼片段,大家體會一下。
memcpy(&wifimesstemp[0], UnderPanState.ucMotorSpeed, 2); memcpy(&wifimesstemp[2], UnderPanState.ucTimeCount, 4); memcpy(&wifimesstemp[6], UnderPanState.ucDistance, 4); memcpy(&wifimesstemp[10], UnderPanState.ucAngle, 4); memcpy(&wifimesstemp[14], UnderPanState.ucVxMMPS, 4); memcpy(&wifimesstemp[18], UnderPanState.ucOmegaRPM, 4); WifiMsgPack(23, APP_GET_UNDERPAN_STATE_BACK, wifimesstemp,TRUE,&WifiTcpMessage);
在接收端的處理非常簡單:
我們先定義一個同傳送端一樣的結構體:
//底盤狀態結構體 typedef struct _T_TestUnderPanState { int16_t MotorSpeed; //電機轉速 uint32_t TimeCount; //運動時間計數 float Distance; //運動距離 mm float Angle; //轉動角度 float VxMMPS; //直線運動速度 mm/s float OmegaRPM; //旋轉速度 }T_TestUnderPanState;
然後直接拷貝資料到該結構體中:
//模擬傳送部分
memcpy(&temp[0], UnderPanState.ucMotorSpeed, 2);
memcpy(&temp[2], UnderPanState.ucTimeCount, 4);
memcpy(&temp[6], UnderPanState.ucDistance, 4);
memcpy(&temp[10], UnderPanState.ucAngle, 4);
memcpy(&temp[14], UnderPanState.ucVxMMPS, 4);
memcpy(&temp[18], UnderPanState.ucOmegaRPM, 4);
//假設我們收到的資料存在temp陣列中
memcpy((uint8_t *)(&TestUnderPanState.MotorSpeed), temp, 22); //接收
是不是使用起來非常方便。
在keil中這樣定義一個無名union的時候記得要勾選上 GNU extensios,如下圖,否則會報錯。