C语言Bit位定义

C语言Bit定义注意点:

首先看一个C位域使用的官方例子(摘自MC9S12XS128.h):

/*** ATD0CTL23 - ATD 0 Control Register 23; 0x000002C2 ***/
typedef union {
  word Word;
   /* Overlapped registers: */
  struct {
    /*** ATD0CTL2 - ATD 0 Control Register 2; 0x000002C2 ***/
    union {
      byte Byte;
      struct {
        byte ACMPIE      :1;                                       /* ATD Compare Interrupt Enable */
        byte ASCIE       :1;                                       /* ATD Sequence Complete Interrupt Enable */
        byte ETRIGE      :1;                                       /* External Trigger Mode enable */
        byte ETRIGP      :1;                                       /* External Trigger Polarity */
        byte ETRIGLE     :1;                                       /* External Trigger Level/Edge control */
        byte ICLKSTP     :1;                                       /* Internal Clock in Stop Mode Bit */
        byte AFFC        :1;                                       /* ATD Fast Conversion Complete Flag Clear */
        byte             :1; 
      } Bits;
    } ATD0CTL2STR;
    #define ATD0CTL2                    _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Byte
    #define ATD0CTL2_ACMPIE             _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ACMPIE
    #define ATD0CTL2_ASCIE              _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ASCIE
    #define ATD0CTL2_ETRIGE             _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ETRIGE
    #define ATD0CTL2_ETRIGP             _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ETRIGP
    #define ATD0CTL2_ETRIGLE            _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ETRIGLE
    #define ATD0CTL2_ICLKSTP            _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ICLKSTP
    #define ATD0CTL2_AFFC               _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.AFFC
    
    #define ATD0CTL2_ACMPIE_MASK        1U
    #define ATD0CTL2_ASCIE_MASK         2U
    #define ATD0CTL2_ETRIGE_MASK        4U
    #define ATD0CTL2_ETRIGP_MASK        8U
    #define ATD0CTL2_ETRIGLE_MASK       16U
    #define ATD0CTL2_ICLKSTP_MASK       32U
    #define ATD0CTL2_AFFC_MASK          64U
    /*** ATD0CTL3 - ATD 0 Control Register 3; 0x000002C3 ***/
    union {
      byte Byte;
      struct {
        byte FRZ0        :1;                                       /* Background Debug Freeze Enable Bit 0 */
        byte FRZ1        :1;                                       /* Background Debug Freeze Enable Bit 1 */
        byte FIFO        :1;                                       /* Result Register FIFO Mode */
        byte S1C         :1;                                       /* Conversion Sequence Length 1 */
        byte S2C         :1;                                       /* Conversion Sequence Length 2 */
        byte S4C         :1;                                       /* Conversion Sequence Length 4 */
        byte S8C         :1;                                       /* Conversion Sequence Length 8 */
        byte DJM         :1;                                       /* Result Register Data Justification */
      } Bits;
      struct {
        byte grpFRZ :2;
        byte     :1;
        byte     :1;
        byte     :1;
        byte     :1;
        byte     :1;
        byte     :1;
      } MergedBits;
    } ATD0CTL3STR;
    #define ATD0CTL3                    _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Byte
    #define ATD0CTL3_FRZ0               _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.FRZ0
    #define ATD0CTL3_FRZ1               _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.FRZ1
    #define ATD0CTL3_FIFO               _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.FIFO
    #define ATD0CTL3_S1C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S1C
    #define ATD0CTL3_S2C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S2C
    #define ATD0CTL3_S4C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S4C
    #define ATD0CTL3_S8C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S8C
    #define ATD0CTL3_DJM                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.DJM
    #define ATD0CTL3_FRZ                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.MergedBits.grpFRZ
    
    #define ATD0CTL3_FRZ0_MASK          1U
    #define ATD0CTL3_FRZ1_MASK          2U
    #define ATD0CTL3_FIFO_MASK          4U
    #define ATD0CTL3_S1C_MASK           8U
    #define ATD0CTL3_S2C_MASK           16U
    #define ATD0CTL3_S4C_MASK           32U
    #define ATD0CTL3_S8C_MASK           64U
    #define ATD0CTL3_DJM_MASK           128U
    #define ATD0CTL3_FRZ_MASK           3U
    #define ATD0CTL3_FRZ_BITNUM         0U
    
  } Overlap_STR;</p><p>  struct {
    word FRZ0        :1;                                       /* Background Debug Freeze Enable Bit 0 */
    word FRZ1        :1;                                       /* Background Debug Freeze Enable Bit 1 */
    word FIFO        :1;                                       /* Result Register FIFO Mode */
    word S1C         :1;                                       /* Conversion Sequence Length 1 */
    word S2C         :1;                                       /* Conversion Sequence Length 2 */
    word S4C         :1;                                       /* Conversion Sequence Length 4 */
    word S8C         :1;                                       /* Conversion Sequence Length 8 */
    word DJM         :1;                                       /* Result Register Data Justification */
    word ACMPIE      :1;                                       /* ATD Compare Interrupt Enable */
    word ASCIE       :1;                                       /* ATD Sequence Complete Interrupt Enable */
    word ETRIGE      :1;                                       /* External Trigger Mode enable */
    word ETRIGP      :1;                                       /* External Trigger Polarity */
    word ETRIGLE     :1;                                       /* External Trigger Level/Edge control */
    word ICLKSTP     :1;                                       /* Internal Clock in Stop Mode Bit */
    word AFFC        :1;                                       /* ATD Fast Conversion Complete Flag Clear */
    word             :1; 
  } Bits;
  struct {
    word grpFRZ  :2;
    word         :1;
    word         :1;
    word         :1;
    word         :1;
    word         :1;
    word         :1;
    word         :1;
    word         :1;
    word         :1;
    word         :1;
    word         :1;
    word         :1;
    word         :1;
    word         :1;
  } MergedBits;
} ATD0CTL23STR;
extern volatile ATD0CTL23STR _ATD0CTL23 @(REG_BASE + 0x000002C2UL);
#define ATD0CTL23                       _ATD0CTL23.Word
#define ATD0CTL23_FRZ0                  _ATD0CTL23.Bits.FRZ0
#define ATD0CTL23_FRZ1                  _ATD0CTL23.Bits.FRZ1
#define ATD0CTL23_FIFO                  _ATD0CTL23.Bits.FIFO
#define ATD0CTL23_S1C                   _ATD0CTL23.Bits.S1C
#define ATD0CTL23_S2C                   _ATD0CTL23.Bits.S2C
#define ATD0CTL23_S4C                   _ATD0CTL23.Bits.S4C
#define ATD0CTL23_S8C                   _ATD0CTL23.Bits.S8C
#define ATD0CTL23_DJM                   _ATD0CTL23.Bits.DJM
#define ATD0CTL23_ACMPIE                _ATD0CTL23.Bits.ACMPIE
#define ATD0CTL23_ASCIE                 _ATD0CTL23.Bits.ASCIE
#define ATD0CTL23_ETRIGE                _ATD0CTL23.Bits.ETRIGE
#define ATD0CTL23_ETRIGP                _ATD0CTL23.Bits.ETRIGP
#define ATD0CTL23_ETRIGLE               _ATD0CTL23.Bits.ETRIGLE
#define ATD0CTL23_ICLKSTP               _ATD0CTL23.Bits.ICLKSTP
#define ATD0CTL23_AFFC                  _ATD0CTL23.Bits.AFFC
#define ATD0CTL23_FRZ                   _ATD0CTL23.MergedBits.grpFRZ</p><p>#define ATD0CTL23_FRZ0_MASK             1U
#define ATD0CTL23_FRZ1_MASK             2U
#define ATD0CTL23_FIFO_MASK             4U
#define ATD0CTL23_S1C_MASK              8U
#define ATD0CTL23_S2C_MASK              16U
#define ATD0CTL23_S4C_MASK              32U
#define ATD0CTL23_S8C_MASK              64U
#define ATD0CTL23_DJM_MASK              128U
#define ATD0CTL23_ACMPIE_MASK           256U
#define ATD0CTL23_ASCIE_MASK            512U
#define ATD0CTL23_ETRIGE_MASK           1024U
#define ATD0CTL23_ETRIGP_MASK           2048U
#define ATD0CTL23_ETRIGLE_MASK          4096U
#define ATD0CTL23_ICLKSTP_MASK          8192U
#define ATD0CTL23_AFFC_MASK             16384U
#define ATD0CTL23_FRZ_MASK              3U
#define ATD0CTL23_FRZ_BITNUM            0U

 

1、位域的分配

位域定义时的位地址分配并不是我们想象的那样依次按从上而下,从低位到高位的顺序排列起来的。他在分配时根据当前占用的位域和下一个位域能否合并为一个字节,来

判断是否将当前位域独立为一个字节,如果不注意这一点,很有可能位域分配时会存在只有几个位就占用了一个字节的情况。比如:

struct{
 union{
    struct{
     unsigned  char bit0:4;
     unsigned  char bit1:1;
     unsigned  char bit2:3;
     unsigned  char bit4:4;
     unsinged  char bit5:6;
     unsigned  char bit6:6;
     
   }bitdata;
  unsigned char data[3];
 }example_unn;
}example_stt;

本来我们以为:4+1+3+4+6+6=24个bit占3个字节;

而实际上位域并没有我们想象的那么灵活:

struct{
 union{
    struct{
     //byte1: 4+1+3=8(正好8位)
     unsigned  char bit0:4;
     unsigned  char bit1:1;
     unsigned  char bit2:3; 
     //byte2:因为4+6>8,bit4所以单独占一个字节
     unsigned  char bit4:4;
     //byte3:同上bit5单独占一个一节(6+6>8)
     unsinged  char bit5:6;
     //byte4:最后bit6再单独占一个字节
     unsigned  char bit6:6;
     
   }bitdata;
  unsigned char data[4];//所以一共占用了4个字节
 }example_unn;
}example_stt;

C语言位域定义并不是太好用,当我们根据实际使用情况需要将内存那么分配时,位域将会失去他的便捷性,如上我们无法将bit4和bit5的低4位合并起来访问,实际操作

我们还是要自己移位赋值,所以在制定协议时最好不要做跨字节的连续位定义。

2、位定位定义中的无名位域

无名位域可以用来填充使用,但无法访问。

对于1中的情况,我们可以加入无名位域使其看起来更直观的表示其位域地址分配的情况:

struct{
 union{
    struct{
     //byte1: 4+1+3=8(正好8位)
     unsigned  char bit0:4;
     unsigned  char bit1:1;
     unsigned  char bit2:3; 
     //byte2:因为4+6>8,bit4所以单独占一个字节
     unsigned  char bit4:4;
     unsigned char :4;//无名位域,占位用,这样你一下就可以看出,bit4单独占一个字节!
     //byte3:同上bit5单独占一个一节(6+6>8)
     unsigned  char bit5:6;
     unsigned char :2;
     //byte4:最后bit6再单独占一个字节
     unsigned  char bit6:6;
     unsigned char :2;
   }bitdata;
  unsigned char data[4];//所以一共占用了4个字节
 }example_unn;
}example_stt;

还有一种特殊情况 unsigned  char:0 ,其中无名位域定义为0个位,就是说此处占一个字节位置。 

 

参考文档:

1、C语言中结构体的位域(bit-fields  )

 

posted @ 2016-11-02 22:51  Hello+World!  阅读(9190)  评论(0编辑  收藏  举报