1、概述
在移植一些客户的代码到CDK的过程中发现,对于C51工程的一些代码,客户对于标志位通常倾向于用“bit”数据类型来定义,且标志位的数量根据客户应用代码的功能而异,如下图所示。而CDK中没有“bit”的数据类型,如果直接一个标志位定义为一个“char”类型又很浪费。下面介绍三种方法来管理大量全局标志位的方法
1.1、方法一:函数操作
-
实现思想:定义一个位数能够涵盖所有标志位的全局变量(32位或者64位),将标志位一一对应到该全局变量的每一个位,编写函数(获取标志位状态,标志位置1,标志清0,标志位翻转),从而实现对标志位的管理。
-
优点:由于函数实现代码及#define所占的内存区域是“text”区,所以该方式的特点是减少了"data"的内存空间的使用,增加了“text”的内存空间;
-
缺点:直观性上欠佳,需要通过函数名称来辨别对标志位的操作。
1.2、方法二:联合体结构体
-
实现思想:由于结构体可以实现“位域”操作,可以定义一个或几个可以涵盖所有标志位的结构体,所定义的位与标志位对应。
-
优点:联合体占用了相对较少的“data”内存空间,#define占用相对较少的“text”内存空间
-
缺点:直观性好,直接操作最终定义的标志位。
1.3、方法三:bool类型
-
实现思想:bool类型直接定义变量,一个bool变量占1个字节
-
优点:直观性较好,操作性好;
-
缺点:所占“data”内存空间较多;
2、举例说明
下面以下图的标志位为例,通过上面介绍的三种方法,来实现对标志位的管理。
2.1、方法一:函数操作
Step 1: 将所有位置编号
#define FgTestOk 0
#define FgFlash 1
#define Fg100ms 2
#define FgFlash100ms 3
#define FgFlash1s 4
#define FgClkRxOk 5
#define FgKey 6
#define Fg2500us 7
#define Fg10mS 8
#define Fg1s 9
#define FgWrong 10
#define FgBeep 11
#define FgWrongDone1 12
#define FgWrongDone2 13
#define FgTimer_Run 14
#define FgTx_TimerOff 15//
#define FgTx_TimerOn 16//
#define FgPwr 17//工作
#define FgDP 18//
#define FgRx_End 19//
#define FgTx_End 20//
#define FgRxDone 21//
#define FgTx_RTTemp 22//
#define FgTx_STTemp 23//
#define FgTx_ST_RT 24//
#define FgTx_Swi 25//
#define FgTx_Wrong 26//
#define FgWifi 27//
#define FgTx_ReSet 28//
#define FgTxGetClk 29
#define FgReSet_Dly 30//
#define FgLock 31//
#define FgTx_Lock 32//
#define FgTx_1Min 33//
#define FgTx_First 34//
#define FgTx_Test 35//
#define FgRx_TestOK 36//
#define FgProdTest 37//
#define Fg1m 38
#define FgCol 39
#define Fg10ms_Rm 40
#define FgKeyLx 41
#define FgPeiWangMode 42
#define FgRstToAp 43
#define FgRstToSmart 44
Step 2: 定义一个能涵盖所有标志位个数的数据类型的变量
/**定义一个64位的变量**/
U64_T FLAG
Step 3: 编写几个位操作的函数
/**获取标志位状态**/
U8_T FlagGetBit(U8_T index)
{
return ((Flag1>> index) & 1ul);
}
/**标志位置1**/
void FlagSetBit(U8_T index)
{
Flag1 = Flag1| (1ul << index);
}
/**标志位清0**/
void FlagClearBit(U8_T index)
{
Flag1 = Flag1& (~(1ul << index));
}
/**标志位翻转**/
void FlagReverseBit(U8_T index)
{
Flag1 = Flag1^ (1ul << index);
}
2.2、方法二:联合体,结构体
Step 1: 定义联合体结构体
typedef union FLAG
{
U16_T Flags; //统一管理所有标志位
struct //位域定义部分
{
U16_T B0:1;
U16_T B1:1;
U16_T B2:1;
U16_T B3:1;
U16_T B4:1;
U16_T B5:1;
U16_T B6:1;
U16_T B7:1;
U16_T B8:1;
U16_T B9:1;
U16_T B10:1;
U16_T B11:1;
U16_T B12:1;
U16_T B13:1;
U16_T B14:1;
U16_T B15:1;
}bit;
}Flag;
Step 2: 标志位跟结构体中的位域对应
Flag Flag1;
#define Fgall Flag1.Flags //对所有标志位进行操作
#define FgTestOk Flag1.bit.B0 //对标志0位进行操作
#define FgFlash Flag1.bit.B1 //对标志1位进行操作
#define Fg100ms Flag1.bit.B2 //对标志2位进行操作
#define FgFlash100ms Flag1.bit.B3 //对标志3位进行操作
#define FgFlash1s Flag1.bit.B4 //对标志4位进行操作
#define FgClkRxOk Flag1.bit.B5 //对标志5位进行操作
#define FgKey Flag1.bit.B6 //对标志6位进行操作
#define Fg2500us Flag1.bit.B7 //对标志7位进行操作
#define Fg10mS Flag1.bit.B8 //对标志8位进行操作
#define Fg1s Flag1.bit.B9 //对标志9位进行操作
#define FgWrong Flag1.bit.B10 //对标志10位进行操作
#define FgBeep Flag1.bit.B11 //对标志11位进行操作
#define FgWrongDone1 Flag1.bit.B12 //对标志12位进行操作
#define FgWrongDone2 Flag1.bit.B13 //对标志13位进行操作
#define FgTimer_Run Flag1.bit.B14 //对标志14位进行操作
#define FgTx_TimerOff Flag1.bit.B15 //对标志15位进行操作
2.3、方法三: bool类型
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
bool FgTestOk;
bool FgFlash ;
bool Fg100ms ;
bool FgFlash100ms;
bool FgFlash1s;
bool FgClkRxOk;
bool FgKey;
bool Fg2500us;
bool Fg10mS;
bool Fg1s;
bool FgWrong ;
bool FgBeep ;
bool FgWrongDone1 ;
bool FgWrongDone2 ;
bool FgTimer_Run ;
bool FgTx_TimerOff ;