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

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

     

     

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

     

    timbo2023Author
    Visitor II
    January 11, 2024

    Is it not possible to toggle the ODR register?

     

     

    Super User
    January 11, 2024

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

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

    Excuse me, I do not understand it.

     

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

    And that is only possible with a BSRR register?

     

    timbo2023Author
    Visitor II
    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?

     

     

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