STM32 GPIO OUTPUT Config using REGISTERS
In the previous Tutorial of this series, we covered how to setup the clock using Registers. Now for the GPIO configuration, I will cover all the 4 configurations i.e INPUT Mode, OUTPUT Mode, ANALOG Mode and Alternate Function Mode.
In this tutorial we will start with the OUTPUT configuration.
OUTPUT MODE
Let’s start with the simplest, and the most used one i.e the output mode. I will be using Pin PA5 as the output pin. Following are the steps required to configure the pin as the output Pin
/************** STEPS TO FOLLOW *****************
1. Enable GPIOA clock
2. Set the PIN PA5 as output
3. Configure the output mode i.e state, speed, and pull
************************************************/
1. Enable GPIOA clock
The GPIO clock can be enabled in the RCC_AHB1ENR Register
As you can see above, the 0th bit of RCC_AHB1ENR Register enables the clock for the GPIOA. That’s why we need to write a 1 in the 0th position
RCC->AHB1ENR |= (1<<0); // Enable the GPIOA clock
2. Set the PIN PA5 as output
To configure the pin as output, we will modify the GPIOx_MODER Register. This register is responsible for configuring different modes for the GPIO and in this case, we will configure it as the output mode
Since I am using pin PA5, I need to modify the pins 10 and 11. This basically works like, if the PIN is ‘y‘, the we need to configure the bits ‘2y’ and ‘2y+1’
Also, in order to set the pin as output, we need to set the bits (11:10) as 0:1. This means that we need to write a ‘1’ in the 10th position
GPIOA->MODER |= (1<<10); // pin PA5(bits 11:10) as Output (01)
3. Configure the output mode i.e Output type, speed, and pull
The output type can be configured in the GPIOx_OTYPER Register.
In the simplest words, the difference between the Push-Pull and open Drain can be understood as follows
If you choose open drain, then the output pin can either be LOW (Gnd) or it can be floating, while if you choose Push-Pull, the the output pin can be HIGH or LOW
Since I want to blink the LED on pin PA5, i will choose the push-pull type output, and to do so, I need to write a ‘0‘ in the 5th position
GPIOA->OTYPER &= ~(1<<5); // bit 5=0 --> Output push pull
Next, The output speed can be configured in the GPIOx_OSPEEDR Register
Here you can select different Speeds for the Output Pin, as per your requirement. GPIO speed controls the rate at which a signal can change between low/high values (the “rise time” and “fall time”).
I want the speed not too high and not too low, so I will choose the Fast speed. To do so, I need to write 1:0 to bits (11:10)
GPIOA->OSPEEDR |= (1<<11); // Pin PA5 (bits 11:10) as Fast Speed (1:0)
Now the final step is to configure the pull-up/pull-down (GPIOx_PUPDR) register.
Here we can Pull-up the pin to Vcc or Pull-down to ground, as per the requirement. Since I am using the pin to blink LED, i will not use the Pull-up or Pull-down. I will set the bits (11:10) as 0
GPIOA->PUPDR &= ~((1<<10) | (1<<11)); // Pin PA5 (bits 11:10) are 0:0 --> no pull up or pulldown
This completes the configuration for the output mode. Now we will see how to set or reset the pin so that we can toggle the LED attached to it
How to Set/Reset the Pin
Using BSRR
To set or reset an individual pin, we need to modify the GPIOx_BSRR Register
BSRR is a 32 bit Register. The lower 16 bits (bit 0 – bit 15) are responsible to set a bit, and the higher 16 bits (bit 16 – bit 31) are responsible to reset a bit
As I have connected the LED to PA5, in order to set it (turn the LED ON), I will write a 1 to bit 5
GPIOA->BSRR |= (1<<5); // Set the Pin PA5
And to reset the pin PA5 (turn the LED OFF), I will write a 1 to the bit 21
GPIOA->BSRR |= (1<<21); // Reset the Pin PA5
Using ODR
Output Data Register (ODR) can also be used to Set/Reset an individual Pin or the entire Port.
In order to Set a pin, we can directly write a ‘1’ to the respective bit, and in order to Reset it, write a ‘0’ in the respective bit
GPIOA->ODR |= 1<<5; // Set the Pin PA5
GPIOA->ODR &= ~(1<<5); // Reset the Pin PA5
To set the entire PORT HIGH, we can write 0xFFF to the ODR
GPIOA->ODR = 0xFFF; // Set the PORTA HIGH
GPIOA->ODR = 0x00; // Reset the PORTA
This will toggle all the Pins of PORTA (PA0 – PA15).
The main CODE
void Delay (uint32_t time)
{
while (time--);
}
int main (void)
{
SysClockConfig ();
GPIOConfig ();
while (1)
{
GPIOA->BSRR |= (1<<5); // Set the Pin PA5
// GPIOA->ODR = 1<<5;
Delay (10000000); // random delay
GPIOA->BSRR |= (1<<5) <<16; // Clear the Pin PA5
// GPIOA->ODR &= ~(1<<5);
Delay (10000000); // random delay
}
}
The above code will toggle the LED. The delay is just a random delay for now. Once we cover the timer, we can generate precise delay.