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.


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.

Notify of
Inline Feedbacks
View all comments