0

假设我在内存中映射了两个地址:

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

我想创建一个在一个寄存器中设置位的函数,如下所示:

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 回答
1

不,您想更改内存位置的内容。因此,您必须将其作为指针传递。

函数头应该喜欢

void set_bit_low(uint8_t *, uint8_t);

该功能应该喜欢

void set_bit_low(uint8_t *my_reg, uint8_t bit_location)
{
   // do your bit manupulation here by assigning to *my_reg.
}
于 2013-09-24T13:23:43.247 回答
0

这个:

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

产生(内存映射)寄存器中值的副本。所以这:

set_bit_low(MY_REGISTER_1, 3);

将该副本传递给set_bit_low(). 然后,您可以设置副本中的位(这将是函数的本地)。如果要在寄存器中设置值的位,则必须传递地址本身:

#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则将是未知的,因此必须以任何一种方式以及(相对)昂贵的函数调用来完成 shift 和 not 操作。使用宏,编译器已经可以计算出右边的表达式 ifn是一个常数,并用 1 或 2 条指令替换该行。

于 2013-09-24T13:30:27.950 回答