GPIO is one of the most easy peripheral to understand in a microcontroller.
But of course it demands a bit of practice to handle it with ease.
That's the purpose of this STM32F303-Discovery board tutorial.
We are going to blink 4 LEDS in order to get how the basics work.
Retrieve this example with full code on my GitHub:
https://github.com/badprog/badprog-stm32f303vct6-blinking-led
In the STM32F303VCT6, there are of course some GPIOs.
These GPIOs are made of several different registers.
In order to use the corresponding configuration, we can use the STM32 libraries to set the GPIO_InitTypeDef structure.
This structure is made of 5 elements:
To set it, it's necessary to pass the adress of this structure to the following function:
There are 2 ways of using MCU, libraries and modification by hand.
To have a LED switched on, there are essentiel steps.
This is done with the following function:
Of course, in this step, we have to enable the clock of each port we want to use in the program.
There is a function for that:
To be simple, this function calls:
This enable de RCC->AHBENR register with the value RCC_AHBENR_GPIOEEN (0x00200000).
All that to change the bit 21 of RCC->AHBENR from 0 to 1.
For example, each LED has its own pin.
Onto this board we have:
Each pin can be used by many peripherals.
For example, on the pin PE15 (Port E and pin 15), there are:
So to use the PE15 as a GPIO_Output to blink a LED.
If we wanted to use the ADC4 on this pin, we would have set this PE15 as alternate function through the GPIOx_MODER register.
Indeed, the GPIOx_MODER register is used to configure the I/O mode, like:
So for ADC, it'll be the Analog mode.
Indeed, each I/O pin has a multiplexer that allows only one peripheral alternate function to be used at a time.
It means that once a pin has been set, if you want to use it as another peripheral, it's necessary to set it again with the corresponding alternate function.
The GPIOx_AFRL and GPIOx_AFRH are also the famous registers to select the appropriate peripherals and have to be modified consequently.
#include "stm32f3xx_hal.h" void SystemClock_Config(void); /** * LED_4 = GPIO_E_PIN_8 (top left - Blue) * LED_3 = GPIO_E_PIN_9 (top - Red) * LED_5 = GPIO_E_PIN_10 (top right - Orange) * LED_7 = GPIO_E_PIN_11 (right - Green) * * LED_9 = GPIO_E_PIN_12 (bottom right - Blue) * LED_10 = GPIO_E_PIN_13 (bottom - Red) * LED_8 = GPIO_E_PIN_14 (bottom left - Orange) * LED_6 = GPIO_E_PIN_15 (left - Green) * */ #define MY_PINS GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 /** * GPIO * * The Alternate element allows to set the GPIO as an alternate function, * for example GPIO_AF10_TIM17 or GPIO_AF4_I2C1 to set this GPIO as a timer pin * or an I2C pin. * In this configuration, the mode has to be set as GPIO_MODE_AF_xx. * But in this example, we won't change anything, because we just want to blink * some LEDs. */ void badprog_gpio() { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOE_CLK_ENABLE() ; GPIO_InitStruct.Alternate = 0; // GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pin = MY_PINS; // set all pins needed GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); } /** * Main, the famous one! */ int main(void) { HAL_Init(); SystemClock_Config(); badprog_gpio(); while (1) { GPIOE->ODR ^= MY_PINS; // let's blink HAL_Delay(1000); } } /** System Clock Configuration */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = 16; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12; HAL_RCC_OscConfig(&RCC_OscInitStruct); RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1); HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); /* SysTick_IRQn interrupt configuration */ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); }
You are now able to understand a bit more than earlier about GPIO and especially with the STM32F3 microcontroller.
Retrieve exhaustive explanation in the reference manual RM0316 from page 228 to 247:
http://www.keil.com/dd/docs/datashts/st/stm32f3xx/dm00043574.pdf
Good job, you know more now!
Comments
Mandy (not verified)
Sunday, May 15, 2022 - 11:43pm
Permalink
Thank you very much! this is
Thank you very much! this is the best explanation i've ever seen!
Add new comment