平時用單片機編寫程序經常會遇到將一個16位數拆封爲兩個8位數,或者將將兩個8位數組成一個16位數。如:
data = data_h * 256 + data_l;
data_h = data / 256;
data_l = data % 256;
對於8位單片來說計算乘法和除法比較耗時,也比較浪費單片機資源。除了將乘法和除法轉換爲 左移 或者 右移運算外,有沒有其他好的方法來解決這個問題。無意間看到了聯合體之後,發現用聯合體來解決這個問題是再好不過的。
關於聯合體的定義:
在進行某些算法的C語言編程的時候,需要使幾種不同類型的變量存放到同一段內存單元中。也就是使用覆蓋技術,幾個變量互相覆蓋。這種幾個不同的變量共同佔用一段內存的結構,在C語言中,被稱作“共用體”類型結構,簡稱共用體,也叫聯合體。
數據類型可以共用一段內存,那麼就可以讓兩個8位數和一個16位數共用一段內存就行了。這樣在用兩個8位數組成16位數的時候,可以分別存儲兩個 8位數,讀取的時候直接讀取16位數就行。一個16位數分成兩個8位數的時候,直接存儲16位數,然後分別讀取兩個8位數就行。 那麼先寫一段代碼測試測試:
union Value
{
unsigned char c[2];
unsigned int i;
};
union Value v;
unsigned char data_h;
unsigned char data_l;
unsigned int data;
void main( void )
{
SysClkInit();
while( 1 )
{
data_h = 0x01;
data_l = 0x02;
v.c[0] = data_h;
v.c[1] = data_l;
data = v.i;
data += 1000;
v.i = data;
data_h = v.c[0];
data_l = v.c[1];
v.i = 0;
}
}
在聯合體中定義一個字符數組,數組長度爲2位,再定義一整形變量,這樣兩個字符變量和一個整形變量共享16位地址。然後在程序中先給字符數組中兩個變量賦值,然後讀取整形變量,看看整形變量的值是不是由兩個字符變量組成的。然後再給整形變量賦值,觀察兩個字符變量是不是整形變量拆分的。
可以看到給c[0]賦值0x01,給c[1]賦值0x02, i 的值就變成了 0x0102,說明c[0]的值爲高8位,c[1]的值爲低8位。符合預期效果。然後再給0x0102加上1000,賦給i,看看c[0]和c[1]值得變化。
可以看到0x0102加上1000後變成了0x04EA,將0x04EA值賦給i後,c[0]的值變爲了0x04,爲高8位,c[1]的值變爲了0xEA爲低8位。看來這樣使用聯合體是正確的。
但是在實際應用的時候,用數組區分高8位和低8位不直觀,而且容易搞混。能不能將數組直接換成兩個變量?那麼很自然的會想到最常用的結構體。用結構體來替換這個數組。於是修改程序如下。
union Data
{
struct
{
unsigned char h;
unsigned char l;
};
unsigned int i;
};
union Data d;
unsigned char data_h;
unsigned char data_l;
unsigned int data;
void main( void )
{
SysClkInit();
while( 1 )
{
data_h = 0x03;
data_l = 0x04;
d.h = data_h;
d.l = data_l;
data = d.i;
data += 1000;
d.i = data;
data_h = d.h;
data_l = d.l;
d.i = 0;
}
}
測試結果如下:
給h賦值0x03,給l賦值0x04,i的值變爲0x0304.
將data的值0x0304加上1000後變爲0x06EC,在賦給i,於是h的值變爲0x06,l的值變爲0xEC,結果正常。
通過聯合體和結構體的組合使用,可以很輕鬆的組合或者拆分16位數。在以後的應用中就可以不使用乘除法來處理數據拆分組合問題了。