我的解决方案是否适用于使用 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
.
我在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
.