一、背景
在单片机开发中,经常会用到状态位。对于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