3

我正在努力想出一种干净的方法来重新定义一些寄存器位域,以便在我正在使用的芯片上使用。

例如,这是 CAN 配置寄存器之一的定义:

extern volatile near unsigned char       BRGCON1;
extern volatile near struct {
  unsigned BRP0:1;
  unsigned BRP1:1;
  unsigned BRP2:1;
  unsigned BRP3:1;
  unsigned BRP4:1;
  unsigned BRP5:1;
  unsigned SJW0:1;
  unsigned SJW1:1;
} BRGCON1bits;

这些定义都不是很有帮助,因为我需要像下面这样分配 BRP 和 SJW:

struct
{
    unsigned BRP:6;
    unsigned SJW:2;
} GoodBRGbits;

以下是我做过的两次尝试:

尝试#1:

union
{
    byte Value;
    struct
    {
        unsigned Prescaler:6;
        unsigned SynchronizedJumpWidth:2;
    };    
} BaudRateConfig1 = {NULL};
BaudRateConfig1.Prescaler = 5;
BRGCON1 = BaudRateConfig1.Value;

尝试#2:

static volatile near struct
{
    unsigned Prescaler:6;
    unsigned SynchronizedJumpWidth:2;
} *BaudRateConfig1 = (volatile near void*)&BRGCON1;
BaudRateConfig1->Prescaler = 5;

有没有“更清洁”的方法来完成我想做的事情?此外,我对尝试 #2 中近乎不稳定的演员感到有些恼火。是否有必要指定一个变量是近的?

4

2 回答 2

2

就个人而言,出于可移植性的原因,我尽量避免使用位域。相反,我倾向于使用位掩码,以便我可以明确控制使用哪些位。

例如(假设位顺序正确)...

#define BRP0  0x80
#define BRP1  0x40
#define BRP2  0x20
#define BRP3  0x10
#define BRP4  0x08
#define BRP5  0x04
#define SJW0  0x02
#define SJW1  0x01

然后可以适当地生成掩码并分配或读取或测试值。您可以为宏选择更好的名称。

希望这可以帮助。

于 2010-04-06T14:54:40.543 回答
1

我建议您不要将位域声明与硬件寄存器的地址混淆。

您的 union/struct 声明位域的排列方式,然后在声明指向此类结构的指针时指定寻址和访问限制。

// foo.h
// 声明结构体,声明指向 hw reg 的指针

结构 com_setup_t {
  未签名的 BRP:6;
  未签名的 SJW:2;
};

结构 com_setup_t *BaudRateConfig1 附近的外部易失性;

// foo.c
// 初始化指针

结构 com_setup_t *BaudRateConfig1 = 附近的易失性
(结构 com_setup_t * 附近易变)0xfff ...;

// 访问硬件注册
富(){
  ...
  波特率配置1->BRP = 3;
  ...
}

关于近/远,我假设默认值是近,除非指定远,除非您可以使用编译器开关将默认指针大小设置为远。

于 2010-04-06T14:54:41.510 回答