cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F411 - common short questions ...

timbo2023
Associate III

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~

35 REPLIES 35
timbo2023
Associate III

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);
}
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; 

Do you know how to debug, step through and examine registers? The SFRs window in STM32CubeIDE will show register values.

If you feel a post has answered your question, please click "Accept as Solution".
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

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...

 

Sorry I do not understand your code writing style Danish1.

 

But interesting information regarding the stm32G types...

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? 🙂

 

 

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

Sorry I do not understand your code writing style Danish1.

It would be helpful if you could say which bits of my reply you think you understand, and which don't make sense to you.

If you look at the Reference Manual for your stm32, you will see that in MODER pairs of bits set the function of a GPIO pin.

If I write the value of GPIOA->MODER in value binary, using "x" as don't care, the direction/mode of pin 0 is:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00 Digital Input for pin 0

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01 Digital Output for pin 0

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx10 Alternate Function for pin 0

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx11 Analog Input for pin 0

Your code (GPIOA->MODER |= 1) was setting bit zero (the right-most bit), with no control over what was in bit one (the next-to-right bit). As long as you could be certain that bit one was reset, your code would work. But if it should happen that you had used that pin for some other function that used the pin e.g. as analog, then setting bit zero would not change it to digital output; instead it would be analog input.

Ouch -

 

@waclawek.jan- thank you for your input, but when I set A6 - it is the 5th entry of the mode register, therefore pin 10.

@gbm - thank you for your answer, we work without HAL library and in a common conventional way. The idea with the defines at the beginning are still good.