联合体用的多吗?
大家好,我是ZhengN
。本次给分享联合体的一些知识。
联合体/共用体的使用
C语言中,联合体/共用体可以实现同一个内存空间中存储不同的数据类型(不是同时存储)。利用这个特性可以在一些情况下给我们提供便利。
比如验证大小端有很多种方法,使用联合体也可以:
#include <stdio.h>
union test
{
int a;
char b;
}test_u;
int main(void)
{
test_u.a = 0x12345678;
if (0x78 == test_u.b)
{
printf("Little endian\n");
}
else
{
printf("Big endian\n");
}
return 0;
}
再比如前两天群里有朋友问:在寄存器操作上,位域看起来似乎挺合适,但为什么库代码都基本没有使用呢?
其实TI的库中有使用,是结合共用体来使用的:
所有的寄存器被封装成联合体类型的,联合体里边的成员是一个32bit
的整数及一个结构体,该结构体以位域的形式体现。这样就可以达到直接操控寄存器的某些位了。
比如,我们要设置PA0
引脚的GPAQSEL1
寄存器的[1:0]
两位都为1,则我们只操控两个bit
就可以很方便的这么设置:
GpioCtrlRegs.GPAQSEL1.bit.GPIO0 = 3
或者直接操控整个寄存器:
GpioCtrlRegs.GPAQSEL1.all |=0x03
再比如当系统中有很多用于描述同一功能的状态变量时,传统做法可能是:
volatile uint16 iuvp = 0; // 输入欠压
volatile uint16 iovp = 0; // 输入过压
volatile uint16 iocp = 0; // 输入过流
volatile uint16 motp = 0; // 功率模块过温
volatile uint16 oovp = 0; // 输出过流
/* 判断异常及处理 */
if ((iuvp != 0) ||
(iovp != 0) ||
(iocp != 0) ||
(motp != 0) ||
(oovp != 0)
)
{
// do something
}
当我们在做状态判断时,这样写下来就感觉很冗余。
换种方式:可以把这些状态变量规整到一个联合体中,用位域来描述。(以下这段代码来自:https://blog.csdn.net/weixin_44474431/article/details/102795568)
typedef union SYSTEM_FAULT{
uint16 all;
struct {
uint16 iuvp: 1; // 输入欠压
uint16 iovp: 1; // 输入过压
uint16 iocp: 1; // 输入过流
uint16 motp: 1; // 功率模块过温
uint16 oovp: 1; // 输出过流
uint16 oocp: 1; // 输出过流
uint16 oopp: 1; // 过功率故障
uint16 excu: 1; // 电流采样零漂过大
uint16 cotp: 1; // CPU过温
uint16 ilrv: 1; // 输入极性错误
}bit;
}SYSTEM_FAULT_STRUCT;
然后状态判断可以这么做:
volatile SYSTEM_FAULT_STRUCT gPSM_FAULT;
if(gPSM_FAULT.all != 0)
{
// do something
}