Skip to content

Instantly share code, notes, and snippets.

@iwalpola
Last active October 17, 2024 06:01
Show Gist options
  • Save iwalpola/6c36c9573fd322a268ce890a118571ca to your computer and use it in GitHub Desktop.
Save iwalpola/6c36c9573fd322a268ce890a118571ca to your computer and use it in GitHub Desktop.
STM32 GPIO registers cheatsheet

STM32duino GPIO Registers and programming

Sources:

http://embedded-lab.com/blog/stm32-gpio-ports-insights/
http://hertaville.com/stm32f0-gpio-tutorial-part-1.html

The libmaple libraries, on which STM32duino is based, provides access to registers by the syntax:

GPIOA->regs->REG

where REG can be one of the following:

CRH and CRL

CRH is used to set type/and or speed of pins 8-15 of the port CRL is used to set type/and or speed of pins 0-7 of the port Accessed as a 32 bit word, with 4 bits representing the state of each pin. Out of these 4 bits, the low 2 bits are MODE, and high 2 bits are CNF.

alt text

The 4 bits for each pin can be set to:
0b0011 (binary) or 0x3 (HEX) - Corresponds to setting pin as output, same as pinMode()
0b1000 or 0x8 - Corresponds to setting pin as input, same as pinMode()

Say I want to set PORTA pins 0, 3 and 4 to OUTPUT and 1, 6, 7 to INPUT, and leave pins 2 and 5 in their original state. The code is:

PORTA->regs->CRL = (PORTA->regs->CRL & 0x00F00F00) | 0x88000080 |0x00033003;
//0x00F00F00 is bitmask to retain value of pins 2 and 5 in original state
//0x88000080 is bitmask to set inputs
//0x00033003 is bitmask to set outputs

IDR - Input Data Register

Used to read input of entire 16 pins of port at once. Accessed as a 32 bit word whose lower 16 bits represent each pin. The pins being read must be set to INPUT mode by using CRL/CRH or pinMode() before using this.

Say I want to read pins A2. The code is:

bool result = GPIOA->regs->IDR & 0x0004; //returns true if A2 is HIGH
//0x0004 is 0b0000000000000100

ODR - Output Data Register

Used to write output to entire 16 pins of port at once. Accessed and written as a 32 bit word whose lower 16 bits represent each pin. The pins being read must be set to OUTPUT mode by using CRL/CRH or pinMode() before using this.

Say I want to set pins A2, A12 and A13, and reset (clear) all other pins in the 16 pin bus. The code is:

GPIOA->regs->ODR = 0b0011000000000100; //note,  binary

Now if I want to set and clear A2, A12 and A13 without altering other pins, the code is:

//Set A2, A12, A13 (HIGH)
GPIOA->regs->ODR |= 0b0011000000000100;
//Clear A2, A12, A13 (LOW)
GPIOA->regs->ODR &= ~(0b0011000000000100);

but notice how, if we want to touch only some pins, we have to READ, MASK and WRITE. That's why there is BRR and BSRR

BRR - Bit Reset Register

32 bit word. Lower 16 bits have 1's where bits are to be set to "LOW". Upper 16 bits have 1's where bits are to be set "HIGH". 0's mean ignore

Now, to set and clear A2, A12, A13 while preserving the state of all other pins in the port, the code is:

//Set A2, A12, A13 (HIGH)
GPIOA->regs->BRR = 0b0011000000000100 << 16; //move to upper 16 bits
//Clear A2, A12, A13 (LOW)
GPIOA->regs->BRR = 0b0011000000000100;

BSRR - Bit Set Reset Register

BSRR is like the complement of BRR. It's also a 32 bit word. Lower 16 bits have 1's where bits are to be set to "HIGH". Upper 16 bits have 1's where bits are to be set "LOW". 0's mean ignore

In this case, to set and clear A2, A12, A13 while preserving the state of all other pins in the port, the code is:

//Set A2, A12, A13 (HIGH)
GPIOA->regs->BSRR = 0b0011000000000100;
//Clear A2, A12, A13 (LOW)
GPIOA->regs->BSRR = 0b0011000000000100 << 16; //move to upper 16 bits

Combination of BRR and BSRR

Since BRR and BSRR are opposite of each other, you can use both if you don't want to do the bit shift left operation .

In this case, to set and clear A2, A12, A13 while preserving the state of all other pins in the port, the code is:

//Set A2, A12, A13 (HIGH)
GPIOA->regs->BSRR = 0b0011000000000100; //lower 16 bits
//Clear A2, A12, A13 (LOW)
GPIOA->regs->BRR = 0b0011000000000100; //lower 16 bits
@Shubuo
Copy link

Shubuo commented Feb 14, 2017

Thanks...

@ofausto
Copy link

ofausto commented May 10, 2017

Very enlightening, thank you!

@Omcsesz
Copy link

Omcsesz commented Jan 21, 2018

What header should I use for accessing GPIOA_CRL, ...?

@Joebeazelman
Copy link

How do I read and write to a single, active low pin with an external pull up? Do I have to switch modes for ever read and write?

@yunjaeGong
Copy link

Cleared up all my questions and frustration. You are such a lifesaver thanks.

@karanjamutahi
Copy link

Lifesaver. Thank You !!!!

@liman324
Copy link

Я два дня искал эту информацию, статья мне очень помогла! Спасибо за труд!

@Fernprlz
Copy link

Fernprlz commented Apr 3, 2020

Second link leads to porn datesites FYI

@iwalpola
Copy link
Author

iwalpola commented Apr 3, 2020

@Fernprlz I have contacted the website owner

@majava3000
Copy link

majava3000 commented Oct 4, 2020

Hello and thanks for this resource. I did some historical spelunking across all of STM32 history (starting from F101/103 and ending up with the new L5s) and the BRR register is always, in all STM32s, reserved in the highest 16 bits.

So, this sequence:
SBRR = x
...
BRR = x

will only work if pin is driven high when its set in SBRR. other way around it cannot work according to any technical documentation.

In the newer reference manuals, ST doesn't really mention BRR anymore, other than in the register map and register documentation. Perhaps it was a design snafu and they'd just prefer if people only used SBRR (IDK).

--

Further poking around revealed that BRR has been removed in some STM32 families. All of F3 have BRR, most (but not all) F7 have BRR, none of F4 family have BRR (not listed in refman register map, nor included in official SVD files).

@nopbxlr
Copy link

nopbxlr commented Nov 17, 2020

typedef struct
{
  __IO uint32_t MODER;        /*!< GPIO port mode register,               Address offset: 0x00      */
  __IO uint32_t OTYPER;       /*!< GPIO port output type register,        Address offset: 0x04      */
  __IO uint32_t OSPEEDR;      /*!< GPIO port output speed register,       Address offset: 0x08      */
  __IO uint32_t PUPDR;        /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C      */
  __IO uint32_t IDR;          /*!< GPIO port input data register,         Address offset: 0x10      */
  __IO uint32_t ODR;          /*!< GPIO port output data register,        Address offset: 0x14      */
  __IO uint32_t BSRR;         /*!< GPIO port bit set/reset register,      Address offset: 0x1A */
  __IO uint32_t LCKR;         /*!< GPIO port configuration lock register, Address offset: 0x1C      */
  __IO uint32_t AFR[2];       /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */
  __IO uint32_t BRR;          /*!< GPIO bit reset register,               Address offset: 0x28 */
}GPIO_TypeDef;

@Kongduino
Copy link

The hertaville domain seems to have gone dark. Here are Wayback Machine links to Part 1 and Part 2.

@nourhen369
Copy link

thank you !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment