STM32F4 Basics: GPIOs

June 28, 2012

These STM32F4 Basics posts aren't really tutorials so much as they are slightly-organized notes with short and contrived examples. Many aspects and nuances are ignored. Look through the documentation and headers referenced throughout this post to fill in the gaps. The RCC and GPIO chapters in RM0090 would be a good place to start.

Working with registers means there will be lots of bitwise operations. Here's a cheat-sheet:
register |= (1 << bitNumber); // set a bit register &= ~(1 << bitNumber); // clear a bit register ^= (1 << bitNumber); // toggle a bit register & (1 << bitNumber) // check a bit: == 0 if bit was a zero, != 0 if bit was a one

The STM32F407VGT6 has 100 pins, and 80 of them can be used as general-purpose inputs or outputs. The GPIO pins are arranged into 5 channels (a, b, c, d, and e), with 16 pins each. Each channel has a separate clock on the AHB1 bus which must be enabled to use those pins.

Each pin has several qualities that are defined by setting bits in their corresponding registers:

The reset (default) values for most pins are: input, push-pull, 2MHz, no pull-up/down, AF0. See RM0090 6.4.11 (p.153) for the few exceptions. Good coding practice would involve resetting the GPIO channel if subsequent code expects the reset values.

Note: Analog pins are not 5V tolerant.

Each pin can be used with one of the 15 possible alternate functions shown in RM0090 Figure 14 (p.141):

Any specific pin can only be used with certain alternate functions. See DM00037051 Table 8 (p.58) for a chart detailing what each pin can do. With the Discovery board some of the pins are already used by the on-board components, see UM1472 Table 5 (p.20) for details.

Read or write to each pin with the IO registers:

Examples:

// Illuminate the four LEDs around the accelerometer (D12, D13, D14, D15) #include "stm32f4xx.h" int main() { RCC->AHB1RSTR |= RCC_AHB1RSTR_GPIODRST; // Reset GPIOD to ensure reset values exist RCC->AHB1RSTR = 0; // Exit reset state RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // Enable GPIOD clock GPIOD->MODER |= GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_0 | // Enable output mode for D12-D15 GPIO_MODER_MODER14_0 | GPIO_MODER_MODER15_0; GPIOD->BSRRL = GPIO_BSRR_BS_12 | GPIO_BSRR_BS_13 | // Set D12-D15 high GPIO_BSRR_BS_14 | GPIO_BSRR_BS_15; } // Illuminate the red LED (D14) while the blue pushbutton is held down (while A0 is high) #include "stm32f4xx.h" int main() { RCC->AHB1RSTR |= RCC_AHB1RSTR_GPIOARST | RCC_AHB1RSTR_GPIODRST; // Reset GPIOA and GPIOD RCC->AHB1RSTR = 0; // Exit reset state RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIODEN; // Enable GPIOA and GPIOD clocks GPIOD->MODER |= GPIO_MODER_MODER14_0; // Enable output mode for D14 while(1) { if(GPIOA->IDR & GPIO_IDR_IDR_0 != 0) // If A0 is high GPIOD->BSRRL = GPIO_BSRR_BS_14; // Set D14 high else GPIOD->BSRRH = GPIO_BSRR_BS_14; // Set D14 low } }

The analog and alternate-function modes will be covered in later posts.