3

使用しているチップで使用できるように、いくつかのレジスタ ビットフィールドを再定義するクリーンな方法を考え出すのに苦労しています。

たとえば、これは CAN 構成レジスタの 1 つが次のように定義されているものです。

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;

ここに私が行った2つの試みがあります:

試み #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;

私がやろうとしていることを達成するための「よりクリーンな」方法はありますか? また、Attempt #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

ビットフィールド宣言とハードウェア レジスタのアドレス指定を混同しないことをお勧めします。

ユニオン/構造体は、ビットフィールドの配置方法を宣言し、そのような構造体へのポインターを宣言するときにアドレス指定とアクセス制限を指定します。

// foo.h
// 構造体を宣言し、hw reg へのポインターを宣言します

構造体com_setup_t {
  署名されていない BRP:6;
  署名されていない SJW:2;
};

extern volatile near struct com_setup_t *BaudRateConfig1;

// foo.c
// ポインタを初期化

volatile near struct com_setup_t *BaudRateConfig1 =
(構造体 com_setup_t 付近の揮発性 *)0xfff...;

// ハードウェア reg にアクセス
フー() {
  ...
  BaudRateConfig1->BRP = 3;
  ...
}

Near/Far については、コンパイラ スイッチを使用してデフォルトのポインター サイズを far に設定できない限り、far が指定されていない限り、デフォルトは near であると想定します。

于 2010-04-06T14:54:41.510 に答える