取宏:
GPIOxMODE(gpio,mode,port) ( GPIO##gpio->MODER = ((GPIO##gpio->MODER & ~((uint32_t)GPIO2BITMASK << (port*2))) | (mode << (port * 2))) )
假设寄存器的复位值为0xFFFF.FFFF,我想设置一个2位宽为任意值。这是为 STM32 编写的 每个端口有 15 个引脚的 MCU。 GPIO2BITMASK 定义为 0x3。有没有更好的方法来清除和设置任意位置的随机 2 位 32 位宽寄存器。
端口 0 - 15 的有效范围
模式 0 - 3 的有效范围
我想出的方法是对掩码进行位移,将其反转,将其与现有寄存器值进行逻辑“与”,将结果与位移后的新值进行逻辑“或”。
我希望结合掩码和新值来减少逻辑运算位移位操作的数量。目标还在于使过程足够通用,以便我可以用于 1、2、3 或 4 位宽的位操作。
有没有更好的办法?
从长远来看,是否有更好的方法确实是一个悬而未决的问题。我正在寻找一种方法,它可以减少逻辑操作和位移操作的数量,同时是一个简单的单行语句。
答案是否定的。
您必须重置/设置以确保您正在写入的位字段具有所需的值。
收到的答案可能会更好(在意见/偏好/哲学/实践方面),因为它们不需要宏并且具有参数检查。在评论和回复中也指出了这种风格的陷阱。
最佳答案
由于多种原因,应避免将这种宏作为牌匾:
- 它们不可调试
- 很难发现他们容易出错
还有很多其他原因
您可以使用内联函数存档相同的结果。生成的代码将同样有效
static inline __attribute__((always_inline)) void GPIOMODE(GPIO_TypeDef *gpio, unsigned mode, unsigned pin)
{
gpio -> MODER &= ~(GPIO_MODER_MODE0_Msk << (pin * 2));
gpio -> MODER |= mode << (pin * 2);
}
但是如果你喜欢宏
#define GPIOxMODE(gpio,mode,port) {volatile uint32_t *mdr = &GPIO##gpio->MODER; *mdr &= ~(GPIO_MODER_MODE0_Msk << (port*2)); *mdr |= mode << (port * 2);}
I am looking to combine the mask and new value to reduce the number of logical operations bit shift operations.
你不能。您需要重置然后设置这些位。
关于c - 有没有更好的方法来定义用于进行位操作的预处理器宏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55869586/