Skip to main content
Visitor II
January 9, 2024
Question

STM32F411 - common short questions ...

  • January 9, 2024
  • 15 replies
  • 7455 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.

    15 replies

    Graduate II
    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
    Visitor II
    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 ...

    Super User
    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;

    timbo2023Author
    Visitor II
    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
    Visitor II
    January 9, 2024

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

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

    timbo2023Author
    Visitor II
    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
    Visitor II
    January 10, 2024

    Ich changed the mode register to

     

     

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

     

    Could you check it?

    timbo2023Author
    Visitor II
    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);
    }
    Graduate
    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
    Visitor II
    January 10, 2024

     

    Sorry I do not understand your code writing style Danish1.

     

    But interesting information regarding the stm32G types...

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

    Graduate
    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? :)

     

     

    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

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