Bluepill port manipulation - need help understanding registers

Post here first, or if you can't find a relevant section!
Post Reply
jwiggams
Posts: 6
Joined: Mon Nov 23, 2020 8:31 pm

Bluepill port manipulation - need help understanding registers

Post by jwiggams »

Hey all,

Trying to work with these pins as quickly as possible, so I need to avoid pinMode and digitalWrite functions. I'm trying to set pins as input and output, but I can't make any sense of how people are using the CRL and CRH functions for it. Like I've seen where writing "GPIOA->CRL = 0x00033003;" somehow makes GPIOA pins 0, 3, and 4 as outputs...but how exactly does that work? 0x00033003 doesn't align with any of those pins in a binary sense...so I don't understand how it works.

If I'm trying to set pins GPIOA 8, 9, 10, 11 and 12 to OUTPUT, and then back to INPUT after a delay, how do I do this? I can't seem to find any examples of port manipulation on the stm32duino that make it clear how to work with these ports directly for faster control.

Any help would be greatly appreciated!
ozcar
Posts: 144
Joined: Wed Apr 29, 2020 9:07 pm
Answers: 5

Re: Bluepill port manipulation - need help understanding registers

Post by ozcar »

Starting point would be to look at section 9.2.1 in the reference manual (RM0008).

From that you would see that in CRL, there are four bits for each for each GPIO 0 to 7, so each hex digit of the value written to CRL sets the config and mode for one of those GPIO pins.

Code: Select all

GPIOA->CRL = 0x00033003; 
Take the low order hex '3' digit (= binary 0011) there, and you will see that does indeed set GPIOA, pin 0 for output. Well, more specifically it is MODE 11 = Output mode, max speed 50 MHz, and CNF 00 = General purpose output push-pull. Similarly, the other hex '3 ' digits in that value do the same for pins 3 and 4.

But watch out, that statement also changes the bits in CRL that control pins 1,2,5,6,and 7, and maybe in a way that you don't want.

For pins 8, 9, 10, 11 and 12, the controlling bits are in CRH.

Depending on just how fast you need to do this, you maybe don't have to go right down to writing directly to the registers.
jwiggams
Posts: 6
Joined: Mon Nov 23, 2020 8:31 pm

Re: Bluepill port manipulation - need help understanding registers

Post by jwiggams »

ozcar wrote: Tue Dec 29, 2020 12:20 am Starting point would be to look at section 9.2.1 in the reference manual (RM0008).

From that you would see that in CRL, there are four bits for each for each GPIO 0 to 7, so each hex digit of the value written to CRL sets the config and mode for one of those GPIO pins.

Code: Select all

GPIOA->CRL = 0x00033003; 
Take the low order hex '3' digit (= binary 0011) there, and you will see that does indeed set GPIOA, pin 0 for output. Well, more specifically it is MODE 11 = Output mode, max speed 50 MHz, and CNF 00 = General purpose output push-pull. Similarly, the other hex '3 ' digits in that value do the same for pins 3 and 4.

But watch out, that statement also changes the bits in CRL that control pins 1,2,5,6,and 7, and maybe in a way that you don't want.

For pins 8, 9, 10, 11 and 12, the controlling bits are in CRH.

Depending on just how fast you need to do this, you maybe don't have to go right down to writing directly to the registers.
Ahh...that makes a lot more sense! Having CRH and CRL being two different sets of 8 pins clears that up a lot.

From what I'm reading, doing "GPIOA->CRH = 0xFFF33333" would set the pins I want as outputs but leave the other pins on their existing state, correct?

For changing one pin, if I understand this correctly, I can use the BSRR register to change a pin value high or low by doing the following:

Code: Select all

GPIOA->BSRR = 0x0004; //set GPIOA pin 2 high
GPIOA->BSRR = 0x0004 << 16; //set GPIOA pin 2 low
Does that seem about right?
ozcar
Posts: 144
Joined: Wed Apr 29, 2020 9:07 pm
Answers: 5

Re: Bluepill port manipulation - need help understanding registers

Post by ozcar »

jwiggams wrote: Tue Dec 29, 2020 1:25 am
From what I'm reading, doing "GPIOA->CRH = 0xFFF33333" would set the pins I want as outputs but leave the other pins on their existing state, correct?
No, it would set the other pins for "Alternate function output Open-drain" (MODE and CNF both 11).
jwiggams wrote: Tue Dec 29, 2020 1:25 am
For changing one pin, if I understand this correctly, I can use the BSRR register to change a pin value high or low by doing the following:

Code: Select all

GPIOA->BSRR = 0x0004; //set GPIOA pin 2 high
GPIOA->BSRR = 0x0004 << 16; //set GPIOA pin 2 low
Does that seem about right?
That looks OK. Aside from the fact that there are labels like GPIO_BSRR_BS2 that you could use (there are also labels for the CRL and CRH bits).
Post Reply

Return to “General discussion”