串列埠通訊中整型和浮點型資料的處理和傳送

2021-07-03 21:15:28 字數 2702 閱讀 3798

在做下位機通訊時往往會用到串列埠,包括下位機將資料傳輸給上位機,或者是下位機與下位機之間進行資料傳輸,這時候就會遇到傳送資料的問題,微控制器通過串列埠 傳送資料時往往是一次乙個位元組(8位),如果傳輸char(8位)型資料則很好辦,只需要直接傳送就可以了,但是在傳送int型資料和float型資料時 就會稍微有些複雜。

下面就以常用的8位微控制器89c51為例來進行說明。

當傳送int型或long型資料時還比較簡單,乙個int型資料是16位,long是32位,把int型/long型資料變成2/4個char型資料傳送出去就可以了,程式如下

voidlong_char(unsigned long l,unsigned char *s)

*s = l>>24;

*(s+1) = l>>16;

*(s+2) = l>>8;

*(s+3) = l; 

在串列埠助手上就可以接收到相應的long型資料了。

當傳送float型資料時稍微有些複雜。下面簡單介紹下float型資料在記憶體中的儲存方式(double類似,以下部分參考了別人的部落格)。

float遵從的是ieee r32.24 在儲存中都分為三個部分:

1.符號位(sign) : 0代表正,1代表為負

2.指數字(exponent):用於儲存科學計數法中的指數資料,並且採用移位儲存

3.尾數部分(mantissa):尾數部分

float的儲存方式如下圖所示:

r32.24和r64.53的儲存方式都是用科學計數法來儲存資料的,比如8.25用十進位制的科學計數法表示就為:8.25*,而120.5可以表示為:1.205*

而計算機根本不認識十進位制的資料,他只認識0,1,所以在計算機儲存中,首先要將上面的數更改為二進位制的科學計數法表示,8.25用二進位制表示可表示為1000.01,120.5用二進位制表示為:1110110.1。用二進位制的科學計數法表示1000.01可以表示為1.00001*,1110110.1可以表示為1.1101101*,任何乙個數都的科學計數法表示都為1.****, 尾數部分就可以表示為***x,第一位都是1,所以可以將小數點前面的1省略,所以23bit的尾數部分,可以表示的精度卻變成了24bit,道理就是在 這裡,那24bit能精確到小數點後幾位呢,我們知道9的二進位制表示為1001,所以4bit能精確十進位制中的1位小數點,24bit就能使float能 精確到小數點後6位,而對於指數部分,因為指數可正可負,8位的指數字能表示的指數範圍就應該為:-127-128了,所以指數部分的儲存採用移位儲存, 儲存的資料為元資料 127,下面就看看8.25和120.5在記憶體中真正的儲存方式。

首先看下8.25,用二進位制的科學計數法表示為:1.00001*

按照上面的儲存方式,符號位為:0,表示為正,指數字為:3127=130 ,位數部分為,故8.25的儲存方式如下圖所示:

而單精度浮點數120.5的儲存方式如下圖所示:

那麼如果給出記憶體中一段資料,並且告訴你是單精度儲存的話,你如何知道該資料的十進位制數值呢?其實就是對上面的反推過程,比如給出如下記憶體數 據:0100001011101101000000000000,首先我們現將該資料分段,0 10000 0101 110 1101 0000 0000 0000 0000,在記憶體中的儲存就為下圖所示:

根據我們的計算方式,可以計算出,這樣一組資料表示為:1.1101101*=120.5而雙精度浮點數的儲存和單精度的儲存大同小異,不同的是指數部分和尾數部分的位數。

介紹完了float型資料在記憶體中的儲存方式後能夠知道如何傳送float型資料了,直接按照int型類似的傳送肯定是不行的,這就需要採用指標的方法(在keil中資料的排放格式是大端模式):

voidfloat_char(float f,unsigned char *s)

unsignedchar *p;

p =(unsigned char *)&f;

*s = *p;

*(s+1) = *(p+1);

*(s+2) = *(p+2);

*(s+3) = *(p+3);

通過這種方法把陣列s傳送出去,在接受端接受到的就是標準的ieee754結構的原始資料,也就是float型資料在記憶體中存放的值,如果需要得到這個float型資料的值還需要進行乙個轉換。

這種方法比較簡單明瞭,這時候的串列埠接收端可以用現成的,不需要自己編寫。

還可以採用共用體的方法,如果採用共用體時串列埠的接收端軟體需要自己編寫。

voidfloat_char(float f,unsigned char *s)

union change

float d;

unsigned char dat[4];

}r1;

r1.d = f;

*s = r1.dat[0];

*(s+1) = r1.dat[1];

*(s+2) = r1.dat[2];

*(s+3) = r1.dat[3]; 

接收端採用同樣的程式編寫就可以得到float型資料的值了,不再需要其他的轉換。類似的,傳輸long型或int型時也可以採用共用體的方法:

voidlong_char(unsigned long l,unsigned char *s)

union change

long d;

unsigned char dat[4];

}r1;

r1.d = l;

*s = r1.dat[0];

*(s+1) = r1.dat[1];

*(s+2) = r1.dat[2];

*(s+3) = r1.dat[3]; 

串列埠通訊中的float型資料的處理

1 將串列埠接收的資料轉換為float型資料 float cxxdlg fourchar2float char szbuf,hex asc資料 bool bbigendian false 指示是否是big endian結構 float4byte float4byte f4b if bbigendia...

序列通訊中浮點數和整型數的處理辦法

序列通訊中浮點數和整型數的處理辦法 序列通訊中浮點數和整型數的處理辦法 序列通訊是以位元組為單位進行傳送的,對於浮點數和整型數都需要進行轉換才能進行通訊。mcu和pc的浮點數都是基於ieee754格式的。有4位元組 float 8位元組 double 10位元組 有一些不支援 這裡以4位元組 flo...

串列埠通訊中垃圾資料的處理

在雙機串列埠通訊中,開關機 串列埠開閉 期間傳送方有時候會發一些無效的垃圾資料,同時因為有的協議解析只有接收到一定數量才能解析。這就會出現乙個現象 如果開頭的資料是錯誤的,又沒有及時丟棄,後面正確的資料接著位置儲存,最終造成解析失敗。現象就是有時候資料互動正確,有時候錯誤 冷啟動第一次出現錯誤的機率...