Skip to main content
Associate III
January 9, 2024
Question

STM32F411 - common short questions ...

  • January 9, 2024
  • 15 replies
  • 7456 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~

15 replies

Uwe Bonnes
Chief
January 9, 2024

Do not use magic defines. GPIOA and USART2 clock enables are defined different!

 

#define RCC_AHB1ENR_GPIOAEN_Msk (0x1U << RCC_AHB1ENR_GPIOAEN_Pos) /*!< 0x00000001 */

#define RCC_APB1ENR_USART2EN_Msk (0x1U << RCC_APB1ENR_USART2EN_Pos) /*!< 0x00020000 */

timbo2023Author
Associate III
January 9, 2024

Firstly thank you for your input and your comment regarding a clock-definition at the code begin.

This I will consider.

In spite of it I am a little bit unsure using your possibilities for enable the clocks in a right (code-) way.

Is there a shorter form for code writing of enabling ports A, C und farer USART2-clock?

How I work with defines of clock addresses at the code begin?

 

Could you give there a more detailled example ...

TDK
January 9, 2024

Debug and step through, verify GPIO registers are getting updated as specified. The IDR value will reflect the current value being output. If ODR and IDR are changing, the pin is toggling, and the problem is elsewhere.

+1 about not using magic values. Use the CMSIS defines.

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;

is a lot more readable than

> RCC->AHB1ENR |= 0xFC;

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

But:

Is the approach in your eyes the same?

In look to my wished writing

Another way:

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

 

Is that quiet ok, too?

timbo2023Author
Associate III
January 9, 2024

And in addition - it would be supportive when you could comment the "toggling" shortly...

gbm
Lead III
January 9, 2024

The next problem reported by the author of this thread will be "MCU not found while trying to download the code".

Do NOT set PA13 & PA14 as GPIO outputs! They are used for SWD debug connection to ST-Link.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
timbo2023Author
Associate III
January 10, 2024

That's a very interesting information, gbm - i will check the reference manual regarding it.

Ho can I fix that in HEX-writing?

timbo2023Author
Associate III
January 10, 2024

Ich changed the mode register to

 

 

GPIOA->MODER |= (1<<0)|(1<<4)|(1<<8);

 

Could you check it?

timbo2023Author
Associate III
January 10, 2024

I changed the whole code and I set the pins individual now.

 

Could you check it, it does not work...

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

GPIOA->MODER |= (1<<0)|(1<<4)|(1<<8);
GPIOC->MODER |= (1<<26);

GPIOA->ODR |= (1<<2);
GPIOC->ODR |= (1<<13);

while(1) {

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

GPIOA->ODR &= ~(1<<0);
GPIOA->ODR &= ~(1<<5);
delayMs(50);
}
Danish1
Lead III
January 10, 2024
GPIOA->MODER |= (1<<0)|(1<<4)|(1<<8);

Are you aware that "|=" is a bitwise-or operation? It can only set bits.

The MODER bits are used in pairs. If we look at MODE0, bits 0 and 1, you are trying to get the value to 01 for General-purpose output mode. So setting bit 0 will work if and only if bit 1 is already zero.

You might see this code in many stm32 examples. That's because for many stm32 the MODER started out with all bits zero = digital-input, so that's fine.

The trouble is that newer stm32 such as stm32G start out with MODER with all bits 1; 11 = analog input. Setting bit 0 will make no difference - the pin will remain analog input.

To program MODE0 you need to do

GPIOA->MODER = (GPIOA->MODER & 0xfffffffc) | 0x00000001;

The reason ST made the change is because analog input consumes less power under certain circumstances.

Edit: It might be clearer if you do

GPIOA->MODER = (GPIOA->MODER & ~GPIO_MODER_MODE0_Msk) | GPIO_MODER_MODE0_0; 

timbo2023Author
Associate III
January 10, 2024

 

Sorry I do not understand your code writing style Danish1.

 

But interesting information regarding the stm32G types...

waclawek.jan
Super User
January 10, 2024
GPIOA->MODER |= (1<<0)|(1<<4)|(1<<8);

This is supposed to set PA0, PA2, PA4 to GPIO Out, right?

So then when you try to toggle PA0 and PA5 in the loop, PA0 should do so but not PA5 which is still set to default GPIO In.

JW

timbo2023Author
Associate III
January 10, 2024

I changed it to PA6 with the following code

 

GPIOA->MODER |= (1<<0)|(1<<4)|(1<<10);

 

Inspite of all, the LED on PC13 is not glowing.

 

But thanks for your discussion input...

gbm
Lead III
January 11, 2024

We keep trying to convince you that the way you want to write your program leads to mistakes - hard to find errors.

If you want to setup port pins without HAL (which is generally a very good idea), define some types and preprocessor constants and macros and use them in a smart way, so that you don't loose your time on checking if your magic numbers and cryptic expressions are correct.

With some smart definitions, you could write something like:

 

#define LED_PORT GPIOA
#define LED_BIT 5
#define LED_MSK (1u << LED_BIT)

// Nucleo64 LED output init
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEN(LED_PORT);
BF2F(LED_PORT->MODER, LED_BIT) = GPIO_MODER_OUT;

GPIO_Toggle(LED_PORT, LED_MSK);

 

Lets make it a puzzle: now write the definitions of RCC_AHB1ENR_GPIOEN() and BF2F(). I have already presented the optimal definition of GPIO_Toggle() in some topic.

Any takers? :)

 

 

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
waclawek.jan
Super User
January 11, 2024

I changed it to PA6 with the following code

 

GPIOA->MODER |= (1<<0)|(1<<4)|(1<<10);

No; you changed it to PA5.

 

Inspite of all, the LED on PC13 is not glowing.

Why would setting GPIOA registers result in any change of PC13 behaviour?

JW

gbm
Lead III
January 11, 2024

Your code above sets the PC13 output high, so the LED is off. There is no code toggling PC13 in the loop.

Using magic numbers is usually called "a complete mess", not "conventional way".

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice