【发布时间】:2019-04-26 14:19:25
【问题描述】:
拍摄宏:
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 位宽度的位操作。
有没有更好的办法?
从长远来看,是否有更好的方法确实是一个悬而未决的问题。我正在寻找一种方法,可以减少逻辑运算和位移运算的数量,同时是一个简单的单行语句。
答案是否定的。
您必须进行重置/设置以确保您正在写入的位字段具有所需的值。
收到的答案可能会更好(根据意见/偏好/哲学/实践),因为它们不需要宏并且具有参数检查。在 cmets 和响应中也指出了这种风格的坑。
【问题讨论】:
-
首先,我会在宏扩展中将
mode和port括在括号中。 -
mode和port通常是常量吗? -
已经过度使用了括号,并且有额外的括号包围模式和端口实际上会降低可读性。
-
模式和端口是常量。我目前正在使用枚举,但我不明白为什么如果你想做一个连续的端口范围就不能使用循环。即模式 2 的端口 9-13。
-
稍微降低可读性(仅在宏定义中)比找出作为带有运算符的表达式的参数为什么会中断更好。