查看原文
其他

联合体用的多吗?

ZhengNL 嵌入式大杂烩 2021-01-31



大家好,我是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
}

简介明了了很多。关于位域的介绍可阅读往期笔记:【C语言笔记】位域

猜你喜欢

goto用的多吗?

例说嵌入式实用知识之JSON数据


关于联合体的使用,大家还有什么经典例子可以分享吗?欢迎留言补充~

=========留言区========

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存