【问题标题】:How to put a uint8_t in the middle of uint16_t without affecting other bits如何在不影响其他位的情况下将 uint8_t 放在 uint16_t 中间
【发布时间】:2017-12-10 12:40:25
【问题描述】:

我正在为使用 16 位 SPI 消息的 DAC 芯片编写 SPI 驱动程序……代表输出的值是从位 11 到位 4(一个 8 位 DAC)。我已经写了这个 MASK,但我不知道如何在不影响其他位的情况下更新数据:

#define MCP4901_SPI_MASK_DATA               0x0FF0
//So data mask in binary is 0000 1111 1111 0000

extern uint16_t mcpA;

static inline void mcpSetData(uint16_t* mcp, uint8_t value) {
    //????
   *mcp =| value & MCP4901_SPI_MASK_DATA; //NOT WORKING
}

【问题讨论】:

  • 为什么要写入 SPI 数据寄存器的一部分而不是全部?这没有任何意义。是否有某种复杂的“菊花链”硬件?
  • @Lundin 还有其他配置位(位 15-12),我可以将它们设置为单个位,我的问题只是将 8 位 DAC 值移动到位置 11 到 4。

标签: c embedded bit-manipulation bitwise-operators


【解决方案1】:

您对|& 这两个操作的使用是正确的,但是您没有按正确的顺序使用它们,并且您没有正确定位其中一个操作数。

这是正确的做法:

*mcp &= ~MCP4901_SPI_MASK_DATA; // Clear out the middle bits
*mcp |= ((uint16_t)value) << 4; // Put in the value in the middle

由于您正在写入硬件寄存器,因此应使用单次写入以避免可能的副作用:

*mcp = (*mcp & ~MCP4901_SPI_MASK_DATA) | (((uint16_t)value) << 4);

MCP4901_SPI_MASK_DATA 被反转以清除0x0FF0 之外的位。或者,您可以将掩码定义为 0xF00F,并删除 ~ 运算符。

8 位值左移 4 以将其置于 16 位的中间,然后将其“或”到数字中。

Demo.

【讨论】:

  • 我会非常小心地连续多次写入 SPI 数据寄存器。写入或读取可能会产生副作用,例如清除标志或发送数据。取决于具体的硬件。
  • @Lundin 你是对的,我完全错过了 OP 正在写入硬件寄存器的事实。谢谢!
  • @Lundin 感谢您提出讨论。我使用 mcpSetData() 函数只是为了更新 U16 变量的内容...其他位和设置通过其他函数完成。当所需数据准备就绪时,我使用单个命令(来自 STM32 的 HAL_SpiTransmit)将其推送到 SPI。它现在工作正常:)
猜你喜欢
  • 1970-01-01
  • 2020-01-14
  • 1970-01-01
  • 1970-01-01
  • 2018-05-09
  • 2012-05-18
  • 1970-01-01
  • 1970-01-01
  • 2016-04-18
相关资源
最近更新 更多