在C语言中,还有另外一种和结构体非常类似的语法,叫做共用体(Union),它的定义格式为:
union 共用体名{
成员列表
};
共用体有时也被称为联合或者联合体,这也是 Union 这个单词的本意。之前在写C程序的时候很少用到,最近发现共用体倒是非常好用,以下将最近应用到的例子记录一下
- 定义一个既能按位域寻址也可按字节寻址的新变量类型
//定义位 typedef union { unsigned char BYTE; //可以按字节寻址 struct { unsigned char BIT0 :1; unsigned char BIT1 :1; unsigned char BIT2 :1; unsigned char BIT3 :1; unsigned char BIT4 :1; unsigned char BIT5 :1; unsigned char BIT6 :1; unsigned char BIT7 :1; } BIT; //定义一个只能按位域寻址的新变量类型 } BITFIELD; //定义一个既能按位域寻址也可按字节寻址的新变量类型 BITFIELD Flag; //定义一个共用体变量 #define f_time_1ms Flag.BIT.BIT0 #define f_time_2ms Flag.BIT.BIT1 #define f_time_3ms Flag.BIT.BIT2 #define f_time_4ms Flag.BIT.BIT3 #define f_time_5ms Flag.BIT.BIT4 #define f_time_6ms Flag.BIT.BIT5 #define f_time_7ms Flag.BIT.BIT6 #define f_time_8ms Flag.BIT.BIT7 /*清所有标志位时*/ Flag.BYTE=0x00;
2.利用共用体的占用内存空间按最大字节变量的特性,用在EEPROM上读写超过1字节的变量倒是很合适
typedef unsigned long uint32; /* Unsigned 32 bit value */
typedef unsigned int uint16; /* Unsigned 16 bit value */
typedef unsigned char uint8; /* Unsigned 8 bit value */
typedef union
{
uint16 Data; //16位变量
struct {
uint8 LOW; //低8位
uint8 HIGH; //高8位
}Data_Buff;
}EEPROM_TypeDef;
//定义变量
EEPROM_TypeDef EEPROM;
//超过8bit的变量,存eeprom时,如果用共用体的话就可以直接存入,而不需要进行转换
write_eeprom(ADDR_DATA_HIGH,EEPROM.Data_Buff.HIGH);//存变量高8位
write_eeprom(ADDR_DATA_LOW,EEPROM.Data_Buff.LOW); //存变量低8位
//读取也一样方便,只要从eeprom读取出高低8位的数据,不进行合并也能得到16位的变量
EEPROM.Data_Buff.HIGH=read_eeprom(ADDR_DATA_HIGH);//存变量高8位
EEPROM.Data_Buff.LOW =read_eeprom(ADDR_DATA_LOW); //存变量低8位
3.数码管扫描上倒是也挺好用的。
#define SEG_COM_SIZE 4
#define EnCom(port) port=0
#define DisCom(port) port=1
#define EnSeg(port) port=1
#define DisSeg(port) port=0
typedef union
{
uint8 Buff;
struct {
unsigned char BIT0 :1;
unsigned char BIT1 :1;
unsigned char BIT2 :1;
unsigned char BIT3 :1;
unsigned char BIT4 :1;
unsigned char BIT5 :1;
unsigned char BIT6 :1;
unsigned char BIT7 :1;
} BIT;
}Data_TypeDef;
typedef struct {
uint8 ComCnt; //数码管公共端计数
uint8 Buff[SEG_COM_SIZE]; //存数码管要显示的数据
Data_TypeDef Data; //显示数据,每一位代表数码管的一个段
}SegDisplay_TypeDef;
SegDisplay_TypeDef SegDisp;
void SEG_Display(void)
{
//---关闭所有段位 进行消隐
//关闭段的映射io口
DisSeg(P_SEG_A);
DisSeg(P_SEG_B);
DisSeg(P_SEG_C);
DisSeg(P_SEG_D);
DisSeg(P_SEG_E);
DisSeg(P_SEG_F);
DisSeg(P_SEG_G);
DisSeg(P_SEG_H);
//关闭位的映射io口
DisCom(P_SEG_COM1);
DisCom(P_SEG_COM2);
DisCom(P_SEG_COM3);
DisCom(P_SEG_COM4);
//先存储要显示的数据,这样对应的位也会得到数据
SegDisp.Data.Buff=SegDisp.Buff[SegDisp.ComCnt];
//数码管段 显示
P_SEG_A=SegDisp.Data.BIT.BIT0;
P_SEG_B=SegDisp.Data.BIT.BIT1;
P_SEG_C=SegDisp.Data.BIT.BIT2;
P_SEG_D=SegDisp.Data.BIT.BIT3;
P_SEG_E=SegDisp.Data.BIT.BIT4;
P_SEG_F=SegDisp.Data.BIT.BIT5;
P_SEG_G=SegDisp.Data.BIT.BIT6;
P_SEG_H=SegDisp.Data.BIT.BIT7;
/*开启 相应的位*/
switch(SegDisp.ComCnt)
{
case 0:EnCom(P_SEG_COM1); break;
case 0:EnCom(P_SEG_COM2); break;
case 0:EnCom(P_SEG_COM3); break;
case 0:EnCom(P_SEG_COM4); break;
}
//数码管 位选改变
if(++SegDisp.ComCnt>=SEG_COM_SIZE) SegDisp.ComCnt=0;
}