Skip to main content
Associate III
January 9, 2024
Question

STM32F411 - common short questions ...

  • January 9, 2024
  • 35 replies
  • 7577 views

Good Evening Ladies and Gentlemen,

 

A short introducing purpose of mine:

 

int main(void)
{
RCC->AHB1ENR |= 0xFC; // ---> Here I would like to open the Port clock
RCC->APB1ENR |= 0xFC; // ---> Here I would like to open the USART2 clock - in this context not relevant

GPIOA->MODER |= 0x55555555; // ---> Here I define Port A as output
GPIOC->MODER |= 0x55555555; // ---> Here I define Port C as output

GPIOA->ODR |= (1<<2); // ---> Here I would like to set PA2 "high"

GPIOC->ODR |= (1<<13); // ---> Here I would like to set the onboard LED (PC13) "high"

while(1) {
GPIOA->ODR |= (1<<0); // Here I would like to "toggle" PA0 and PA6 
GPIOA->ODR |= (1<<6);
delayMs(50); // It only is a not relevant "delay" for this purpose

GPIOA->ODR &= ~(1<<0);
GPIOA->ODR &= ~(1<<6);
delayMs(50);
}
}

 

 

But something went wrong - it does not work - Do you have any suggestions especially regarding a simple "toggling"?

It should be a pre work for a stepper motor controlling.

 

Best regards

~TIMBO~

This topic has been closed for replies.

35 replies

waclawek.jan
Super User
January 11, 2024

> when I set A6 - it is the 5th entry of the mode register, therefore pin 10

I don't know what is A6 and pin 10.

Pins in ports are numbered from 0 (i.e. PA0, PA1, ... PA6). In GPIOA_MODER, the bitfield for PA6 are bits 12 and 13.

JW

 

 

timbo2023Author
Associate III
January 11, 2024

Attached the output situation -

my aim is only to toggle PA0 - and to set the other ones.

 

It sounds easy, the reality looks in another way...

But PC13 is glowing now ... thank you for this discussion input.

 

Back to PA0, I would like to toggle this output Pin for a stepper motor control.

 

 

TDK
January 11, 2024

This initializes as output and toggles PA0:

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
GPIOA->MODER &= ~(0b11 << 0);
GPIOA->MODER |= 0b01 << 0;
while (1) {
 GPIOA->BSRR = 1 << 0;
 HAL_Delay(50);
 GPIOA->BSRR = 1 << 16;
 HAL_Delay(50);
}

 

"If you feel a post has answered your question, please click ""Accept as Solution""."
timbo2023Author
Associate III
January 11, 2024

Is it not possible to toggle the ODR register?

 

 

TDK
January 11, 2024

Sure it's possible. Using BSRR avoids RMW access.

"If you feel a post has answered your question, please click ""Accept as Solution""."
waclawek.jan
Super User
January 11, 2024

RMW=Read-Modify-Write, for example

 

GPIOA->ODR |= (1<<0);

 

means "read ODR, perform OR with (1<<9) (i.e. modify), write result to ODR".

Why does it matter? Because it makes time for an interrupt to kick in between read and write, and if that interrupt modifies the same register, then returns, and the subsequent write destroys what the interrupt wrote.

JW

timbo2023Author
Associate III
January 11, 2024

Excuse me, I do not understand it.

 

waclawek.jan
Super User
January 11, 2024

RMW is an abbreviation (acronym) from Read-Modify-Write.

For example, if you write

GPIOA->ODR |= (1<<0);

that is a Read-Modify-Write operation, because:

- first, the processor reads in content of GPIOA->ODR register into some of its internal working registers

- then the processor performs the bitwise-OR operation with (1 << 0), that's the modify part

- and finally, processor writes from internal register into GPIOA->ODR the modified value

JW

timbo2023Author
Associate III
January 11, 2024

And that is only possible with a BSRR register?

 

timbo2023Author
Associate III
January 11, 2024

In spite of it - I would like to set A2 and A6 as "high" - and toggle with the ODR register A0.

 

Could you write shortly the mode register setting, too?

 

 

waclawek.jan
Super User
January 12, 2024

Don't use "A0" etc. It's PA0, PA2 and PA6. "A0" may cause confusion with Arduino-connector signal marking.

For PA0 to be set as output, you have to set bits 0 and 1 of GPIOA_MODER to 0b01.

For PA2 to be set as output, you have to set bits 4 and 5 of GPIOA_MODER to 0b01.

For PA6 to be set as output, you have to set bits 12 and 13 of GPIOA_MODER to 0b01.

You may see a pattern and write macros/functions accordingly.

I recommend to try it without writing any program (maybe an infinite loop), by directly writing to registers in the debugger.

Then, to set pin PA0 high, write 1 into bit 0 of GPIOA_BSRR. This has to be a direct write, not a RMW with OR:

GPIOA->BSRR = (1 << 0);

To set pin PA2 high, write 1 into bit 2 of GPIOA_BSRR:

GPIOA->BSRR = (1 << 2);

To set pin PA6 high, write 1 into bit 6 of GPIOA_BSRR:

GPIOA->BSRR = (1 << 6);

To set pin PA0 to low, write 1 into bit 16 of GPIOA_BSRR:

GPIOA->BSRR = (1 << (0 + 16));

To set pin PA2 to low, write 1 into bit 18 of GPIOA_BSRR:

GPIOA->BSRR = (1 << (2 + 16));

To set pin PA6 to low, write 1 into bit 22 of GPIOA_BSRR:

GPIOA->BSRR = (1 << (6 + 16));

You may have spotted a pattern here, too; again, try to write a macro or a function.

You may want to read this intro.

JW

timbo2023Author
Associate III
January 12, 2024

 

RCC->AHB1ENR |= (1<<0)|(1<<2); // enable A and C port
RCC->APB1ENR |= (1<<17); // enable USART2

GPIOA->MODER |= (1<<0)|(1<<4)|(1<<12); // set A0, A2, A6 as output
GPIOC->MODER |= (1<<26); // set PC13 as output

GPIOA->BSRR = (1 << 2);
GPIOA->BSRR = (1 << 6);

GPIOC->BSRR = (1 << (13 + 16));

while (1)
{
	GPIOA->BSRR = (1 << 0);
	delayMs(50);

	GPIOA->BSRR = (1 << (0 + 16));
	delayMs(50);
}

 

Thank you for your answer.

 

Result:

PC13 is glowing

PA0 "toggled" - but the stepper motor does not drive... thank you in spite of it ...

timbo2023Author
Associate III
January 12, 2024

Perhaps for interested people, my trial-stand for controlling a stepper motor ...

 

But the stepper motor does not drive at the moment ...