0

メモリにマップされた 2 つのアドレスがあるとします。

#define MY_REGISTER_1 (*(volatile uint8_t *)(0x1B))
#define MY_REGISTER_2 (*(volatile uint8_t *)(0x18))

次のように、1 つのレジスタにビットを設定する関数を作成したい:

set_bit_low(MY_REGISTER_1, 3);

私の関数を以下のように宣言するのは正しいですか?

void set_bit_low(uint8_t, uint8_t);
4

5 に答える 5

2

あなたの定義から始めましょう:

#define MY_REGISTER_1 (*(volatile uint8_t *)(0x1B))

address のオクテットを逆参照するため、メモリ マップド レジスタの位置ではなく内容0x1bを表します。レジスタの場所を含むマクロを用意することをお勧めします。

#define REGISTER_1 ((volatile uint8_t *) (0x1B)) /* Substitute _1 for some meaningful name */

これは自由に逆参照でき、次のように関数を宣言できます。

void set_bit_low(volatile uint8_t *register, uint8_t bitpos);

/* Use like this: */
set_bit_low(REGISTER_1, 3);
于 2013-09-24T13:21:46.757 に答える
1

関数を宣言する正しい方法は次のとおりです。

void set_bit_low(uint8_t *, uint8_t);
于 2013-09-24T13:21:46.603 に答える
0

これ:

#define MY_REGISTER_1 (*(volatile uint8_t *)(0x1B))

( memマップされた) レジスタの値のコピーを生成します。したがって、この:

set_bit_low(MY_REGISTER_1, 3);

そのコピーを に渡しますset_bit_low()その後、コピー内のビットを設定できます(関数に対してローカルになります)。registerに値のビットを設定する場合は、アドレス自体を渡す必要があります。

#define MY_REGISTER_1_ADDR 0x1b

わかる?

于 2013-09-24T13:20:54.557 に答える
0

MY_REGISTER_1定義した方法を関数に渡すと、そのコピーが送信されるという多くの回答が既に述べています。ただし、マイクロコントローラーでよく使用される実際のソリューションは、他の回答が示唆するものとは異なります。

通常、レジスタ定義したとおりに定義されます。つまり、

#define MY_REGISTER_1 (*(volatile uint8_t *)(0x1B))
#define MY_REGISTER_2 (*(volatile uint8_t *)(0x18))

大丈夫です。ただし、関数によって変更されることが予想される場合は、それらを関数に渡さないように注意する必要があります。このようなレジスタのビット操作を実行する最もクリーンな方法は、マクロを使用することです。例えば:

#define SET_BIT_LOW(reg, n) (reg) &= (uint8_t)~(1 << (n))
#define SET_BIT_HIGH(reg, n) (reg) |= (uint8_t)(1 << (n))

これにより、実際のレジスタが正しく操作されるだけでなく、関数呼び出しを回避できるという追加の利点もあります。これらが関数である場合nは不明であるため、(比較的) コストのかかる関数呼び出しと同様に、いずれかの方法でシフト操作と非操作を実行する必要があります。nマクロを使用すると、コンパイラは、 が定数である場合に右側の式を既に計算し、その行を 1 つまたは 2 つの命令で置き換えることができます。

于 2013-09-24T13:30:27.950 に答える