【问题标题】:C - How do I receive a bit from a bit field as a parameter in a function?C - 如何从位字段中接收位作为函数中的参数?
【发布时间】:2013-04-17 18:22:28
【问题描述】:

我有一个这样定义的位字段(它来自微控制器库,所以看起来有点不同):

typedef union {
    byte Byte;
    struct {
        byte PTAD0       :1;
        byte PTAD1       :1;                                       
        byte PTAD2       :1;
        byte PTAD3       :1;
        byte PTAD4       :1;
        byte PTAD5       :1;
        byte             :1;
        byte             :1;
    } Bits;
} PTADSTR;
extern volatile PTADSTR _PTAD @0x00000000;
#define PTAD                            _PTAD.Byte
#define PTAD_PTAD0                      _PTAD.Bits.PTAD0
#define PTAD_PTAD1                      _PTAD.Bits.PTAD1
#define PTAD_PTAD2                      _PTAD.Bits.PTAD2
#define PTAD_PTAD3                      _PTAD.Bits.PTAD3
#define PTAD_PTAD4                      _PTAD.Bits.PTAD4
#define PTAD_PTAD5                      _PTAD.Bits.PTAD5

所以。假设我想要一个设置一点的函数,像这样:

void setbit(bit Bit) {
     Bit = 1;
}

当然,“位”声明不起作用。我想要一个我可以使用的声明

setbit(PTAD_PTAD5)

它会设置这个位。我可以的

void setbit(byte Byte, byte number) {
     Byte |= 1<<(number);
}

然后发送

setbit(PTAD,5);

效果很好,但是……这不是我想要的,因为我想做一些像 Arduino 的库之类的东西。任何人都知道如何以我喜欢的方式做到这一点?

【问题讨论】:

    标签: c arduino microcontroller bit bit-fields


    【解决方案1】:
    1. C 是一种按值传递的语言,所以即使你可以这样做:

      void setbit(bit Bit) {
           Bit = 1;
      }
      

      这将是一个无操作。

    2. 你可以用类似函数的宏来做你想做的事:

      #define setbit(x) do { (x) = 1; } while(0)
      

      如果你用PTAD_PTAD5 调用这个宏,它应该会像你期望的那样工作。

    【讨论】:

    • 是的,这是我第一次这样做。不幸的是,当涉及到嵌入式系统时,这种宏的使用是有限的。但是,一个好主意!
    【解决方案2】:

    因为您可以单独访问位域中的位,所以设置位非常容易:

    _PTAD_PTAD5 = 1;
    

    感谢#define _PTAD_PTAD5,评估结果为

    _PTAD.Bits.PTAD5 = 1;
    

    请注意,由于 C 是一种按值传递的语言,

    void setBit(bit Bit){
        Bit = 1;
    }
    

    不要做你所期望的。相反,它将(函数)局部变量 Bit 设置为 1,而您发送给它的变量保持不变。

    通常你会在函数中使用指向要更改的变量的指针,但因为你不能在位域中获取位的地址,所以在这种情况下你不能这样做。

    【讨论】:

      【解决方案3】:

      在 C 中,我不相信可以将位域作为数组访问。一种想法是传入枚举类型或常量,并将其值转换为 8 个不同的集合函数。不是最干净的方法,但我相信它会起作用。

      
      #define PTAD5  5
      ...
      
      void setbit(PTADSTR byte, int bit)
      {
          switch(bit)
          {
              ...
              case PTAD5  : byte.PTAD5 = 1; break;
              default: ASSERT_ALWAYS(); break;
          }
      }
      

      【讨论】:

        【解决方案4】:

        这个怎么样? 使用 static const 限定符应该确保内存开销大约为零

        typedef struct
        {
            uint8_t* reg;
            uint8_t bitnum;
        }bit;
        
        void setbit(bit b)
        {
            *b.reg |= (1 << b.bitnum);
        }
        
        void clrbit(bit b)
        {
            *b.reg &= ~(1 << b.bitnum);
        }
        
        static const bit PTAD_PTAD0 = {&PTAD, 0};
        static const bit PTAD_PTAD1 = {&PTAD, 1};
        static const bit PTAD_PTAD2 = {&PTAD, 2};
        static const bit PTAD_PTAD3 = {&PTAD, 3};
        static const bit PTAD_PTAD4 = {&PTAD, 4};
        static const bit PTAD_PTAD5 = {&PTAD, 5};
        static const bit PTAD_PTAD6 = {&PTAD, 6};
        static const bit PTAD_PTAD7 = {&PTAD, 7};
        
        int main()
        {
            printf("PTAD: %02X\n", PTAD);
            setbit(PTAD_PTAD0);
            printf("PTAD: %02X\n", PTAD);
            clrbit(PTAD_PTAD0);
            printf("PTAD: %02X\n", PTAD);
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-03-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-08
          • 1970-01-01
          • 2013-05-03
          相关资源
          最近更新 更多