Electronic – GPIO Output Registers on the STM32

stm32

Hi I'm currently attempting to write a simple program using the STM32 Nucleo development board, based around the STM32F334R8. The application sets up the GPIO ports A and C and reads the state of the button. If the button is pressed, it turns on the LED. If not, it turns it off.

From ST's documentation (STM Nucleo 64) I've verified that the button is wired to Pin C13 and LED2 is wired to Pin A5.

From the datasheet, I've been reading through the registers for the GPIO (Long STM32F334 Datasheet) and see there are three that seem to be related to the output; ODR, BSRR, and BRR.

When implementing the application mentioned above, my first thought was to write the GPIO pin state for the output LED using ODR, like so:

SET_BIT(GPIOA->ODR, GPIO_ODR_5);
CLEAR_BIT(GPIOA->ODR, GPIO_ODR_5);

This did not appear to work. My button presses were detected, as I could verify this in the debugger by seeing it follow different paths. Here's my setup code for the GPIO:

// set one to input
CLEAR_BIT(GPIOC->MODER, GPIO_MODER_MODER13_0);
CLEAR_BIT(GPIOC->MODER, GPIO_MODER_MODER13_1);
// set another to output
SET_BIT(GPIOA->MODER, GPIO_MODER_MODER5_0);
CLEAR_BIT(GPIOA->MODER, GPIO_MODER_MODER5_1);
// set output to push-pull
CLEAR_BIT(GPIOA->OTYPER, GPIO_OTYPER_OT_5);
// set input with pull-up
SET_BIT(GPIOC->PUPDR, GPIO_PUPDR_PUPDR13_1);
CLEAR_BIT(GPIOC->PUPDR, GPIO_PUPDR_PUPDR13_0);

// enable GPIOA and GPIOC clock
SET_BIT(RCC->AHBENR, RCC_AHBENR_GPIOAEN);
SET_BIT(RCC->AHBENR, RCC_AHBENR_GPIOCEN);

I also saw a piece of example code that worked on my board that uses the BSRR and BRR bits, like so:

// set output high
SET_BIT(GPIOA->BSRR, GPIO_BSRR_BS_5);
// set output low
SET_BIT(GPIOA->BRR, GPIO_BRR_BR_5);

… But this didn't work.

I'm not sure I understand the difference between the three registers and their functions.

What are the use cases for each? Which one is suited to my application?

Best Answer

The most obvious problem I see in your code is that you're writing to the GPIO registers before enabling the clocks for the appropriate peripherals.

Peripherals won't respond correctly if their clocks haven't been enabled. Enable all peripheral clocks before you try to do anything with the peripherals.

That all being said: the differences between ODR and BSRR/BRR are minimal. If you only need to change one bit, though, a single write to BSRR (or BRR) is faster, and uses less code space, than a read/modify/write cycle on ODR. However, if you actually do want to set the state of the whole port at once, or if you need to check the current output state, ODR is the way to go.

Related Topic