C语言位域结构体

一、背景

在单片机开发中,经常会用到状态位。对于51单片机可以通过sbit的方式去定义一个位变量,但是对于16位或32位的单片机来说往往不提供位变量的定义,此时可以使用位域结构体的方式去定义位变量,避免空间的浪费,也能将具有类似含义的标志位放到一起管理。

目前对位操作,用的比较多的方式是“|<<"、">>"、"|="、"&=",对相应的位进行与、或运算得到相应的值,并不能一步到位。

#define SET_BIT(REG, BIT)     ((REG) |= (BIT))

#define CLEAR_BIT(REG, BIT)   ((REG) &= ~(BIT))

#define READ_BIT(REG, BIT)    ((REG) & (BIT))

然后位域结构体刚刚满足直接赋值操作。

二、例子

2.1

代码如下:

#include "stdafx.h"
#define uint8_t unsigned char 
typedef struct
{
    uint8_t bit0:1;     //bit0
    uint8_t bit1:1;     //bit1
    uint8_t bit2:1;     //bit2
    uint8_t bit3:1;     //bit3
    uint8_t bit4:1;     //bit4
    uint8_t bit5:1;     //bit5
    uint8_t bit6:1;     //bit6
    uint8_t bit7:1;     //bit7
}StateTypedef;       //定义一个位域结构体

typedef union 
{
    uint8_t        u8Sta;
    StateTypedef   Bit;
}ByteUnionTypedef;   //将位域结构体和一个8位的变量组成一个共用体,方便整体赋值和取值


int _tmain(int argc, _TCHAR* argv[])
{

	ByteUnionTypedef GlobalByte;

	GlobalByte.u8Sta = 0;        //对8个bit位进行清零

	GlobalByte.Bit.bit2 = 1;     // 0000 0100
	GlobalByte.Bit.bit0 = 1;     // 0000 0101

	printf_s("共用体占用字节数=%d\n val= %d",sizeof(GlobalByte),GlobalByte.u8Sta);

	getchar();
	return 0;
}

输出:

共用体占用字节数=1

val= 5

当需要操作一个字节中第二位(bit1)时,

GlobalByte.Bit.bit2 = 1;或者 if(GlobalByte.Bit.bit2 == 0){ }即可;

为什么要用一个共用体来放置位域结构体和一个8bit的变量(GlobalByte.u8Sta)呢?

答案很简单,如果还需要对位域结构体进行整体赋值,取值操作时,可以通过GlobalByte.u8Sta对8个bit位一次操做完成。

GlobalByte.u8Sta = 0x0f;

等效于 GlobalByte.Bit.bit0 = 1;

GlobalByte.Bit.bit1 = 1;

GlobalByte.Bit.bit2 = 1;

GlobalByte.Bit.bit3 = 1;

GlobalByte.Bit.bit4 = 0;

GlobalByte.Bit.bit5 = 0;

GlobalByte.Bit.bit6 = 0;

GlobalByte.Bit.bit7 = 0;

 2.2

如果不需要整体操作,那么如下操作,也可以实现位变量的独立使用。

#define uint8_t unsigned char 
typedef struct
{
    uint8_t bit0:1;     //bit0
    uint8_t bit1:1;     //bit1
    uint8_t bit2:1;     //bit2
    uint8_t bit3:1;     //bit3
    uint8_t bit4:1;     //bit4
    uint8_t bit5:1;     //bit5
    uint8_t bit6:1;     //bit6
    uint8_t bit7:1;     //bit7
}StateTypedef;       //定义一个位域结构体

int _tmain(int argc, _TCHAR* argv[])
{
    StateTypedef State;

	State.bit0 = 0;  //依次清零
	State.bit1 = 0;
	State.bit2 = 0;
	State.bit3 = 0;
	State.bit4 = 0;
	State.bit5 = 0;
	State.bit6 = 0;
	State.bit7 = 0;

	State.bit2 = 1;     // 0000 0100         赋值操作


    if (State.bit2 == 1)   //使用
	{
	   printf_s("位域结构体占用字节数=%d\n ",sizeof(State));
	   printf_s("State = 0x%02X\n",State);
    }
	getchar();
	return 0;
}

输出:

位域结构体占用字节数=1

State = 0x04

2.3

同理,32位数据的位处理,如下:

定义:

typedef struct
{
    uint8_t b0 :1;
    uint8_t b1 :1;
    uint8_t b2 :1;
    uint8_t b3 :1;
    uint8_t b4 :1;
    uint8_t b5 :1;
    uint8_t b6 :1;
    uint8_t b7 :1;
    uint8_t b8 :1;
    uint8_t b9 :1;
    uint8_t b10:1;
    uint8_t b11:1;
    uint8_t b12:1;
    uint8_t b13:1;
    uint8_t b14:1;
    uint8_t b15:1;
    uint8_t b16:1;
    uint8_t b17:1;
    uint8_t b18:1;
    uint8_t b19:1;
    uint8_t b20:1;
    uint8_t b21:1;
    uint8_t b22:1;
    uint8_t b23:1;
    uint8_t b24:1;
    uint8_t b25:1;
    uint8_t b26:1;
    uint8_t b27:1;
    uint8_t b28:1;
    uint8_t b29:1;
    uint8_t b30:1;
    uint8_t b31:1;
}Bit_t;

#define ToBit(x)  ((Bit_t *)(&(x)))

具体操作

uint32_t Alarm;

ToBit(Alarm)->b0 = 1; //第0位赋值1
ToBit(Alarm)->b31 = 1;//第31位赋值1

2.4

同理,也可以对多字节书进行单字节操作。如下:

定义

typedef struct
{
    uint8_t B0;
    uint8_t B1;
    uint8_t B2;
    uint8_t B3;
    uint8_t B4;
    uint8_t B5;
    uint8_t B6;
    uint8_t B7;
    uint8_t B8;
}Byte_t;

#define ToByte(x)  ((Byte_t *)(&(x)))

具体操作

uint32_t Alarm;

ToByte(Alarm)->B0 = 0x11; //第1个字节
ToByte(Alarm)->B3 = 0xaa;//第4个字节

参考网友:

1、https://zhuanlan.zhihu.com/p/521549781

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值