c - 有没有更好的方法来定义用于进行位操作的预处理器宏?

标签 c embedded

取宏:

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 位宽的位操作。

有没有更好的办法?

从长远来看,是否有更好的方法确实是一个悬而未决的问题。我正在寻找一种方法,它可以减少逻辑操作和位移操作的数量,同时是一个简单的单行语句。

答案是否定的

必须重置/设置以确保您正在写入的位字段具有所需的值。

收到的答案可能会更好(在意见/偏好/哲学/实践方面),因为它们不需要宏并且具有参数检查。在评论和回复中也指出了这种风格的陷阱。

最佳答案

由于多种原因,应避免将这种宏作为牌匾:

  1. 它们不可调试
  2. 很难发现他们容易出错

还有很多其他原因

您可以使用内联函数存档相同的结果。生成的代码将同样有效

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/

相关文章:

c - 为什么这个变量值在退出函数后又恢复为默认值?

c - 有哪些工具可以建议潜在的重构

c - 如何反转一个char数组,然后将反转后的char数组存储到另一个数组中?

c - RTX 开发套件中的项目部署

c - sbss2/sdata2有什么意义?

c - 为什么我的 void 指针会更改程序中的值?

android - 自定义安卓

将子程序的地址转换为 void 指针

c - 指针用于存储地址,但是在像 char *ptr = "abc"这样的字符串中,那么如果打印 'ptr' 为什么会打印 abc 而不是地址

java - 从 JNI(Java native 接口(interface))访问 C 常量( header )