Search code examples
stm32gpio

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


I have set an 8-bit bus on (PD0:PD7) on the stm32 MCU to send addresses to another chip (0:255). I am interested if a function like below would work for fast change in addresses. I could not find an example directly showing register to be equal to integer so I want to confirm it would work. I need a function to which I will give an integer value for the address (0:255) and it will set the 8 pins of the bus with this value:

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
}

If this solution works, I am curious also if I change the bus to ports PD5:PD12 would my function work as:

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
}

Thank you!


Solution

  • Yes, both should work. However, a more recognisable but equivalent formulation would be:

    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
    }
    

    But, there is an even faster way. BSRR is a 32bit register than can both set and reset. You can combine the two write accesses into one:

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

    Happy bit-fiddling!