假设我在内存中映射了两个地址:
#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);
答案 0 :(得分:2)
让我们从您的定义开始:
#define MY_REGISTER_1 (*(volatile uint8_t *)(0x1B))
取消引用地址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);
答案 1 :(得分:1)
以下应该是声明你的功能的正确方法:
void set_bit_low(uint8_t *, uint8_t);
答案 2 :(得分: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.
}
答案 3 :(得分:0)
此:
#define MY_REGISTER_1 (*(volatile uint8_t *)(0x1B))
在(mem映射)寄存器中产生值的副本。所以这个:
set_bit_low(MY_REGISTER_1, 3);
将该副本传递给set_bit_low()
。然后,您可以在副本中设置位(这将是函数的本地位)。如果要在寄存器中设置值的位,则必须传递地址本身:
#define MY_REGISTER_1_ADDR 0x1b
有意义吗?
答案 4 :(得分: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条指令替换该行。