我的解决方案是否适用于使用 BSRR 和 BRR 的 8 位总线寻址?

Would my solution work for 8-bit bus addressing using BSRR and BRR?

我在stm32单片机的(PD0:PD7)上设置了一个8位总线,用于向另一个芯片(0:255)发送地址。如果像下面这样的功能可以用于快速更改地址,我很感兴趣。我找不到直接显示寄存器等于整数的示例,所以我想确认它是否有效。我需要一个函数,我将为地址 (0:255) 提供一个整数值,它将使用该值设置总线的 8 个引脚:

void chipbus(uint16_t bus8){
   GPIOD->regs->BSRR = bus8;      // set all the '1' in bus8 to high
   GPIOD->regs->BRR = 255-bus8;   // 255-bus8 inverts the 8 bits
                                  // BRR to set the new '1' to low
}

如果这个解决方案有效,我也很好奇如果我将总线更改为端口 PD5:PD12,我的功能是否会像:

void chipbus(uint16_t bus8){
   GPIOD->regs->BSRR = bus8*32;      // set all '1' in bus8 to high
                                     // multiply by 32 to shift 5 bits/pins
   GPIOD->regs->BRR = (255-bus8)*32; // 255-bus8 inverts the 8 bits
                                     // BRR to set the new '1' to low
}

谢谢!

我不推荐使用这种方法。作为两个单独的步骤写入 BSRR 和 BRR 意味着总线将过渡到一个意外的状态,其中一些位仍然设置为以前的值。

相反,请考虑直接写入 GPIO 输出数据寄存器 (ODR)。如果您需要保留端口中高位的原始值,您可以在 CPU 端这样做:

GPIOD->regs->ODR = (GPIOD->regs->ODR & 0xff00) | (bus8 & 0x00ff);

是的,两者都应该有效。然而,一个更容易识别但等效的公式是:

void chipbus(uint16_t bus8) {
  GPIOD->regs->BSRR = bus8; // set all the '1' in bus8 to high
  GPIOD->regs->BRR = (~bus8) & 0xFF; // inverts the 8 bits // BRR to set the new '1' to low
}

void chipbus(uint16_t bus8) {
  GPIOD->regs->BSRR = bus8<<5; // set all '1' in bus8 to high, shift 5 bits
  GPIOD->regs->BRR = ((~bus8)&0xFF)<<5; // inverts the 8 bits
}

但是,还有一种更快的方法。 BSRR 是一个 32 位寄存器,既可以置位也可以复位。您可以将两个写访问合并为一个:

void chipbus(uint16_t bus8) {
  GPIOD->regs->BSRR =
    (bus8<<5) | (((~bus8) & 0xFF) << (16+5));
}

快乐bit-fiddling!

是的,它绝对有效。但是,正如其他人指出的那样,建议在单个操作中设置输出。

利用完整的 32 位 BSRR 寄存器,无需反转数据位即可完成:

GPIOD->regs->BSRR = bus8 | (0xFF << 16);

GPIOD->regs->BSRR = (bus8 << 5) | (0xFF << (16 + 5));

因为 BSRR 具有在单个写入操作中设置某些位并重置其他一些位的功能,并且当特定引脚的设置位和重置位都被设置时,输出变为 1.