【问题标题】:Using structure/union combinations使用结构/联合组合
【发布时间】:2020-08-28 03:19:20
【问题描述】:

我在 PIC18F87K90 微控制器中使用 c 编程。我在创建结构变量(其中包含联合)以更轻松地访问多个标志(大多数是 1 位标志,但有些是 2 位或 3 位)时遇到问题。

下面的代码运行良好。我使用模拟器检查每个成员的地址字节。联合内部结构的成员被分组在同一个地址字节中,我希望这是因为成员总共有 8 位,应该适合 1 字节。我还检查了以下地址: eeprom_flag.byte0, eeprom_flag.reset_time_byte... 等等,由于联合使用,它们在同一个地址。 我的问题是我想为 1 位标志之一设置两个可能的名称,即 eeprom_flag.output_time_bit。我想为它取另一个名字(但完全相同的变量位,相同的地址)。我尝试使用 union 来做到这一点(请参阅下面的注释行)。但是,这样做会破坏我的代码,使结构的成员不再位于相同的地址中。我的目标是按照上传的图片进行寻址。

typedef struct
{
    //buffer index 0
    union
    {
        struct
        {
            uint8_t reset_time_bit:1;
//            union
//            {
                uint8_t output_time_bit:1;      //shared address
//                uint8_t output2_time_bit:1;
//            };
            uint8_t count_mode_bit:3;
            uint8_t input_mode_bit:1;
            uint8_t count_speed_bit:2;
        };
        uint8_t byte0;
        uint8_t reset_time_byte;
        uint8_t output_time_byte;
        uint8_t output2_time_byte;
        uint8_t count_mode_byte;
        uint8_t input_mode_byte;
        uint8_t count_speed_byte;
    };
} eeprom_flag_t;
extern volatile eeprom_flag_t   eeprom_flag;

Expected mapping

【问题讨论】:

  • 联合的最小大小是一个字节。你无法实现你所追求的。使用包含位字段和其他名称之一的结构的联合是有一定意义的。为 8 位值设置 7 个(而不仅仅是 1 个)名称并没有什么明显的好处。
  • 也许:#define output2_time_bit output_time_bit
  • 感谢您的建议。关于不使用#define,#ifdef,#endif,使用output2_time_bit还是output_time_bit的决定将在我的微控制器初始化之后做出,所以它在技术上是在运行时,虽然只是在初始化。

标签: c pic pic18


【解决方案1】:

虽然我不明白您为什么要这样做,但以下内容可能会满足您的要求。

这个想法是您定义 2 个位域 (struct),它们以您喜欢的方式重叠 (union)。

union
{
    struct { uint8_t output_time_bit:1;} ;
    struct { uint8_t output2_time_bit:1;} ;
}

【讨论】:

    【解决方案2】:

    理论上,您想要的可能是可能的,但实际上,没有供应商编写过可以做到这一点的编译器。通常联合与字节边界对齐。在某些编译器上,它们与 2、4、8 或 16 字节边界对齐。

    您必须重新声明整个结构才能实现您想要的。不需要在结构中放置联合 - 联合可以直接在 typedef 中使用)。此外,如果您不命名内部结构,您可能无法查看调试器中的值。调试器对此很敏感——有时可以,有时不能。

    typedef union
    {
        struct
        {
            uint8_t reset_time_bit:1;
            uint8_t output_time_bit:1;      //shared address
            uint8_t count_mode_bit:3;
            uint8_t input_mode_bit:1;
            uint8_t count_speed_bit:2;
        } bits1;
        struct
        {
            uint8_t reset_time_bit:1;
            uint8_t output2_time_bit:1;
            uint8_t count_mode_bit:3;
            uint8_t input_mode_bit:1;
            uint8_t count_speed_bit:2;
        } bits2;
        uint8_t byte0;
        ...
    } eeprom_flag_t;
    

    或者,正如@Mike 建议的那样,只具有一个结构并#define 另一个结构的位域。

    通常编译器会生成更少的代码,如果 |和 & 被使用。除了 or-ing 和 and-ing 之外,使用位会产生大量的左移和右移。 查看生成的代码时,您很快就会感到非常困惑。

    【讨论】:

      猜你喜欢
      • 2013-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多