Understanding the stm32f0 ' s GPIO
This was the first part of the GPIO tutorial for the stm32f0discovery.
The tutorial would include the following topics:
- Understanding the Structure of the GPIO registers on the STM32F0 microcontroller
- Understanding how to access the registers
- Setting and clearing output pins
The stm32f051 microcontroller on the Stm32f0discovery board
Have 5 general purpose Input/output (GPIO) ports named Port A, B, C, D and F.
Each of the ports can have a pins, and each port has associated with it the following set of registers:
- GPIO Port Mode Register (Gpiox_moder)
- GPIO Port Output Type register (gpiox_otyper)
- GPIO Port Output Speed Register (GPIOX_OSPEEDR)
- GPIO Port Pull-up/pull-down Register (GPIOX_PUPDR)
- GPIO Port Input data register (Gpiox _IDR)
- GPIO Port outp ut data Register (GPIOX_ODR)
- GPIO Port bit set/reset register (Gpiox _BSRR)
- GPIO Port Configuration Lock Register (GPIOX_LCKR)
- GPIO Alternate function Low register (GPI OX_AFRL)
- GPIO Alternate function High register (GPIOX_AFRH)
- GPIO Port bit Reset Register (GPIOX_BRR)
Where the ' x ' in each register name acronym represents the port i.e.
The gpiox_moder associated with Port A is called Gpioa_moder.
Let's take a closer look at each register:
GPIO Port Mode Register (Gpiox_moder)
This was a 32-bit register where each set of the consecutive bits represent the mode of a single I/O pin.
For example bits 0 and 1 of the Moder register associated with GPIOC (Gpioc_moder),
represent the mode of GPIO pin PC0 and bits of the same register represent the mode of the Gpio pin PC13.
These-bits can set to:
- ' xx ', input mode, which allows the GPIO pin to being used as an input pin,
- ' which ', output mode, allows the GPIO pin to being used as an output pin,
- ' One ', Analog mode, which allows the GPIO pin to being used as an Analog input pin and finally,
- ' Ten '-Alternate function mode which allow the GPIO pins to be used by peripherals such as the UART, SPI e.t.c.
It is important to note that if a pin ' s MODE is set to alternate function,
Any GPIO settings for this pin in the GPIO registers is overridden by the peripheral.
GPIO Port Output Type register (gpiox_otyper)
This was a 16-bit register where each bit denotes the ' type ' of a single pin in the register.
This register sets the type of output pins to either push-pull or open drain.
For example if PIN PC7 are configured as an output pin,
Clearing bit 7 (or leaving its state at zero) of the Otyper register associated with GPIOC (Gpioc_typer),
Would set the output type of the GPIO output pin PC7 to "push-pull".
-
GPIO Port Output Speed Register (GPIOX_OSPEEDR)
This is a 32-bit register, where each set of the represent, the speed of a single output pin.
For example bits 0 and 1 of the OSPEEDR register associated with Port C (GPIOC_OSPEEDR),
represent the speed setting of the output pin PC0 and bits and the same register
represent the speed setting of the output pin PC13. These-bits can set to:
- ' X0 ': 2MHz Low Speed
- ' Medium ': 10MHz speed
- ' One ': 50MHz High speed
Why are there a speed setting on I/O?
To save power.
On the 2MHz setting the GPIO would consume less current than on the 50MHz setting
I ' d Imagine but would has relatively longer rise/fall time specs.
The User Manual for the stm32f0 claims, the the the output pins fastest toggle speed is every the clock cycles.
Assuming a maximum operation speed of 48MHz, the fastest toggle speed for the GPIO in the stm32f0 is a
Which means the highest frequency square wave that can being produced by the GPIO is 12MHz.
Note:
A Quick look at the default startup code found in "SYSTEM_STM32F0XX.C"
Would identify that the microcontroller was indeed operating at a maximum speed of 48MHz at startup.
In a the future entry I'll demonstrate how the speed can be changed.
-
GPIO Port Pull-up/pull-down Register (GPIOX_PUPDR)
The GPIOX_PUPDR registers configures the internal pull-ups and Pull-down resistors on each I/O pin.
The internal Pull-up/down resistors can be configured on GPIO pins set as input or output
(Though I ' d imagine they ' d is more popular on input pins).
The Pullup/down resistors has a typical value of 40KOhms but can range from 30-50kohms.
Again each of the consecutive bits represent the internal pull-up/down resistor setting for each pin within a single port.
-
GPIO Port Input data register (Gpiox _IDR)
This is a 16-bit read-only register. Each bit represents the input value on a corresponding pin.
Reading a ' 0 ' in bit 8 of this GPIOC _IDR register indicates then the voltage on PC8 is 0V (GND).
While reading a ' 1 ' in bit 8 of this GPIOC _IDR register indicates that the voltage on PC8 is 3.3V (VDD)
GPIO Port Output Data register (GPIOX_ODR)
This is a 16-bit read/write register. Each bit represents the output value on a corresponding pin.
Writing a ' 0 ' in bit 8 of this GPIOC _ODR registers indicates that the voltage on PC8 are driven by the micro to 0V (GND).
While writing a ' 1 ' in bit 8 of this GPIOC _ODR register indicates that the voltage on PC8 are driven by the micro to 3.3V (VDD).
Writing to the ODR register are good if you want to write to the entire port.e.g.
GPIOC-0xf0fe
The above statement changes the state of every pin on the GPIOC peripheral from its previous (and now discarded) state,
To the one indicated by the statement; 0xf0fe (0b1111000011111110).
However if you want to set only a single pin;
Lets say PC8 without affecting the state of the rest of the pins on GPIOC,
You have to perform a read-modify-write (RMW) access.
To set pin PC8 independent of all and pins on GPIOC (RMW) your could use:
GPIOC, |= 0x00000100//(0b00000000000000000000000100000000)
To clear pin PC8 independent of all and pins on GPIOC (RMW) you could use:
GPIOC-&= ~(0x00000100//(0b00000000000000000000000100000000)
This works just fine, and you had to read the ODR Register,
or (|) OR and (&) (Modify) it with a mask
And then write it back to the ODR register.
This means in the assembly language level, at least three instructions
is used to set/clear an I/O which can significantly slow down toggling speed.
A better-would is to use the BSRR register and the BRR registers for setting and clearing pins.
They enable ' atomic ' access that allows the I/O pin to being clear/set in as short a time as possible.
GPIO Port bit set/reset register (Gpiox _BSRR)
Note:if both BSx and BRx are set, BSx have priority.
As mentioned in the preceding paragraph the BSRR register allows us to set/clear a particular pin (or groups of pins)
While preserving the state of the rest of the pins on a GPIO peripheral atomically
i.e. a fast as possible, without have to resort to the slower read-modify-write (RMW) accesses.
The least significant-bits is used to atomically set pin values to VDD
Whereas the most significant-bits is used to atomically clear pin values to GND.
So if I wanted to set PC8 independent of all and pins on GPIOC I could use:
GPIOC, 0x00000100; (0b00000000000000000000000100000000)
Or
GPIOC(1<<8);
To clear pin PC8 independent of all and pins on GPIOC you could use:
GPIOC, 0x01000000//(0b00000001000000000000000000000000)
Or
GPIOC(1<<);
Notice how in both scenarios a simple assignment operator ' = ' (atomic)
was used rather than a ' |= ' or an ' &= ' which denote RMW accesses.
Furthermore, note that to clear the pin value of PC8 to GND,
I had to set the 24th bit in the BSRR (8th bit of the most significant bits).
While-to-set the pin value of PC8 to VDD, I had to set the 8th bit in the BSRR.
The awkwardness of atomic clearing being mapped to the most significant 16-bits of the BSRR register
is compensated for by the inclusion of the BRR register.
The BRR register maps the most significant 16-bits of the BSRR register into itself.
So-to-clear pin PC8 independent of all and pins on GPIOC your could use:
GPIOC(1<<8);
Finally There is three more registers;
The GPIOX_AFRH, GPIOX_AFRL, and the Gpiox_lckr registers.
The first of the Allow GPIO pins to is used for alternate functions.
There is a really neat pin muxing mechanism This allows each GPIO to be mapped
to multiple alternate functions depending in how these, registers is set.
I'll spend more time to the AFRL/AFRH registers in the future entries.
The last Gpiox_lckr register can be used once GPIO
is configured to ' lock ' of the configuration so, it does not a change until the micro is reset.
I encourage you-look up these three registers in the user manual.
Understanding the stm32f0 ' s GPIO