STM32 GPIO - EPFL-MICRO-315/TPs-Wiki GitHub Wiki
⚠ wiki page used in TP1
GPIO configuration
- In this example we configure pin 11 of port GPIOD, which is connected to LED7
- To be able to use the GPIOD peripheral we need to enable its clock
- All GPIOs are on the AHB1 bus
- 💡 You can find this information in the Reference Manual or in the datasheet in chapter Memory map
- Here, we enable GPIOD clock by setting GPIODEN bit in the AHB1ENR register, which is shown in the figure below
- The peripheral registers and bit masks are conveniently defined in stm32f407xx.h as shown in listing below
#define RCC_AHB1ENR_GPIODEN_Pos (3U) #define RCC_AHB1ENR_GPIODEN_Msk (0x1U << RCC_AHB1ENR_GPIODEN_Pos) /*!< 0x00000008 */ #define RCC_AHB1ENR_GPIODEN RCC_AHB1ENR_GPIODEN_Msk - Register access happens through C structures which are grouped by peripheral
- The RCC struct groups the Reset and clock control and contains the AHB1EN
typedef struct { __IO uint32_t CR; __IO uint32_t PLLCFGR; __IO uint32_t CFGR; __IO uint32_t CIR; __IO uint32_t AHB1RSTR; __IO uint32_t AHB2RSTR; __IO uint32_t AHB3RSTR; uint32_t RESERVED0; __IO uint32_t APB1RSTR; __IO uint32_t APB2RSTR; uint32_t RESERVED1[2]; __IO uint32_t AHB1ENR; __IO uint32_t AHB2ENR; __IO uint32_t AHB3ENR; uint32_t RESERVED2; __IO uint32_t APB1ENR; __IO uint32_t APB2ENR; uint32_t RESERVED3[2]; __IO uint32_t AHB1LPENR; __IO uint32_t AHB2LPENR; __IO uint32_t AHB3LPENR; uint32_t RESERVED4; __IO uint32_t APB1LPENR; __IO uint32_t APB2LPENR; uint32_t RESERVED5[2]; __IO uint32_t BDCR; __IO uint32_t CSR; uint32_t RESERVED6[2]; __IO uint32_t SSCGR; __IO uint32_t PLLI2SCFGR; } RCC_TypeDef; #define RCC ((RCC_TypeDef *) RCC_BASE) //Here RCC_BASE is just an address - Below is the code to enable the clock
// enable GPIOD clock RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
GPIO Peripheral
- A General-purpose I/O (GPIO) port has up to 16 I/O pins which can be configured individually
- The figure below shows the basic GPIO structure for one port bit
- Study the schema to get an understanding of the peripheral functions
- A GPIO pin has 4 configuration registers:
- MODER: Mode configuration (input, output, alternate function or analog)
- OTYPER: Output type (push-pull or open-drain)
- PUPDR: pull type (pull-up, pull-down or floating)
- OSPEEDR: output speed (4 levels)
⚠ WARNING ⚠
- If you configure the wrong GPIO as output you can damage the robot!
So double check that the configurations are correctly done before running your code - GPIOs managing the drivers of the motors (A3901) must be use with caution. Consult EPuck2 Motor for more details.
- Go through chapter 8.4 GPIO registers on page 283 of the Reference Manual to find out which bits to set to configure a GPIO pin as open-drain output
- Below is the code to configure LED7 - GPIOD 11 as an open-drain output
// LED7 - GPIOD 11 #define LED7_PORT GPIOD #define LED7_PIN 11 // Enable GPIOD peripheral clock RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // Output mode : MODERy = 01 LED7_PORT->MODER = (LED7_PORT->MODER & ~(3 << (LED7_PIN * 2))) | (1 << (LED7_PIN * 2)); // Output type open-drain : OTy = 1 LED7_PORT->OTYPER |= (1 << LED7_PIN); // Output data low : ODRy = 0 LED7_PORT->ODR &= ~(1 << LED7_PIN); // Floating, no pull-up/down : PUPDRy = 00 LED7_PORT->PUPDR &= ~(3 << (LED7_PIN * 2)); // Output highest speed : OSPEEDRy = 11 LED7_PORT->OSPEEDR |= (3 << (LED7_PIN * 2));
GPIO data access
- There are 3 registers to access the GPIO input and output data:
- GPIO->IDR Input data register: allows reading GPIO input state and
- GPIO->ODR Output data register: allows writing GPIO output state
- GPIO->BSRR Bit set/reset register
- To change the output state of a pin you have to read the register value, apply a bit mask and write it back to the register
- ⚠ This can be problematic because between read and write an interrupt can occur and the same register might be accessed form the interrupt service routine
- In this case the change from the interrupt will be overwritten by the write back of the base program
- 💡 To address this problem there is a third 32bit register, the BSRR, which is write-only
- It allows setting and resetting ODR bits by one write access
- Writing a one to the upper 16 bits will reset the corresponding bit in ODR to 0, while writing a one to the lower 16 bits will set the corresponding bit to 1