Access GPIO pin states with ODR and IDR in STM32 StdPeriph

Access GPIO pin states with ODR and IDR in STM32 StdPeriph

Hello everyone in this article we are going to talk about Output Data Register in STM32F4. Arm itself called this register as ODR. We will access the ODR of the related GPIO port pin states.

Now let's begin.

Firstly I want to talk about what ODR and IDR

ODR stands for Output Data Register

IDR stands for Input Data Register

ODR is one of GPIO registers which holds all output states of pins of a GPIO port. We can alter with 16bit binary value and we specify the pin values with this register.

IDR is one of the GPIO registers which holds the input states of pins of a GPIO port. We can read the entire pin status of a GPIO portwith IDR register.

I strongly recommend you to read the datasheet first. Below images you can see the ODR and IDR registers of the STM32F429/439.

STM32F429-39 ODR Register Datasheet

STM32F429-39 IDR Register Datasheet

In this article we are going to make examples with STM32F429ZI-NUCLEO board.
I will use the blue user button and red, Blue, Green leds to access these registers.

  • Blue User Button(B1) connected to PC13
  • Green Led(LD1) connected to PB0
  • Blue Led(LD2) connected to PB7
  • Red Led(LD3) connected to PB14

As you can see the last 16-bits of the both registers what we are in need. Now we are going to make examples to read and write these registers.

First we have to make required configurations of these GPIO ports. Below code block will make the required bus and pin configurations first. Ay you can see we set the LED pins as OUTPUT and Button pin as INPUT.

	GPIO_InitTypeDef GPIO_StructureLed;
	GPIO_InitTypeDef GPIO_StructureButton;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
	GPIO_StructureLed.GPIO_Mode = GPIO_Mode_OUT; 
	GPIO_StructureLed.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_7 | GPIO_Pin_14 ; 
	GPIO_StructureLed.GPIO_OType = GPIO_OType_PP; 
	GPIO_StructureLed.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOB, &GPIO_StructureLed);
	GPIO_StructureButton.GPIO_Mode = GPIO_Mode_IN;
	GPIO_StructureButton.GPIO_Pin = GPIO_Pin_13;
	GPIO_StructureButton.GPIO_OType = GPIO_OType_PP;
	GPIO_StructureButton.GPIO_PuPd = GPIO_PuPd_DOWN; 
	GPIO_StructureButton.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOC, &GPIO_StructureButton); 

Now First let's see the ODR and IDR registers in real time operations. With below code block we are going to activate the leds with the user button pressed and deactivate with releasing the button.

		if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13))
			GPIO_SetBits(GPIOB,GPIO_Pin_0 | GPIO_Pin_7 | GPIO_Pin_14 );
			GPIO_ResetBits(GPIOB,GPIO_Pin_0 | GPIO_Pin_7 | GPIO_Pin_14);

We are going to check the register values from debug screen. Below image shows the ODR and IDR registers of GPIOB and GPIOC ports when I pressed the button and released the button. STM32F429 GPIO Ports IDR and ODR Registers in Debug Mode

Lets exemine the registers:
I will only care about required bits of the registers. Other bits may be high for other purpose. I do not care them

GPIOB ODR register changed from 0x00000000 to 0x00004081 and first 16 bits is careless according to datasheet. So we care about last 16 bits.
0x4081 = 0b0100000010000001‬
As you can see above binary value 0. 7. and 14. bits are HIGH. This means related pins of the GPIOB port are HIGH.

GPIOC IDR register changed from 0x0000DF4F to 0x0000FF4F. Now according to datasheet first 16 bits are not important. We use last 16bits.
0xDF4F = 0b 1101 1111 0100 1111
0xFF4F = 0b ‭1111 1111 0100 1111‬
As you can see bit 13 changed from LOW to HIGH. This means this pin activated via button pressing.

We can also check the required pin is HIGH or LOW with bitwise operators in C. All we need to use masking the IDR value. We Are going to mask with a value which required bits are HIG and the remain is low.

Below code block you can see the method to accomodate this need. This function will return TRUE or FALSE according to result.

#include < stdbool.h > //We need this header for bool variable
bool checkMaskForIDR(uint16_t IDR_Value, uint16_t mask_input){
	return IDR_Value & mask_input;

We can also change the pin output status with directly ODR value. But in here we have to be carefull about do not disturbing the other bits. Because other pins may be in use for another purpuse. So we need to use masking. But if the other pins are not important we can change them too.

Below code block will set HIGH only PB0, PB7 and PB14 and rest of them will be LOW.

	if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13))
		GPIOB->ODR = 0x00004081;
		GPIOB->ODR = 0x00000000;

If you want to change only required pins we can use the OR bitwise operator. We will mask the required value with OR 0 and other values will not be affected.

Below code block will set HIGH only PB0, PB7 and PB14 and rest of them will be stay as they were.

	if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13))
		GPIOB->ODR |= 0x00004081;
		GPIOB->ODR |= 0x00000000;

You can check the Explanation of Operators in C article to get detailed information of operators in C.

That is all in this article.

Have a good accessing GPIO registers.

Burak Hamdi TUFAN.


Share this Post

Send with Whatsapp

Post a Comment

Success! Your comment sent to post. It will be showed after confirmation.
Error! There was an error sending your comment.


    There is no comment. Be the owner of first comment...