This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How can I use GPIOA and GPIOB at the same time?

This is the program I'm trying to run. It's actually a program for a running light but for GPIOB's LED which is connected for the first LED just stayed on all the time, while the other 3 LED which is at GPIOA is is a running light sequence.

#include "stm32f4xx.h"
void delayMs(int n);

int main(){
RCC -> AHB1ENR |= 3;
GPIOA -> MODER &= ~0x0000FC00;
GPIOA -> MODER |= 0x00005400;
GPIOB -> MODER &= ~0x00003000;
GPIOB -> MODER |= 0x00001000;

while(1){
GPIOB->BSRR |= 0x004000A0;
delayMs(500);
GPIOA->BSRR |= 0x00800060;
delayMs(500);
GPIOA->BSRR |= 0x004000A0;
delayMs(500);
GPIOA->BSRR |= 0x002000C0;
delayMs(500);
}
}

void delayMs (int n){
int i;
for(; n>0; n--)
for(i=0; i<3000; i++);
}

Can someone help me?

Parents
  • I am very impressed with your level of skill, your ability to actually read the STM reference manual and actually write succinct and "proper" code in both C and assembly language.  The only difference with  your code seems to be the use of the Bit Set Reset Register (used in the C code and by far the best choice to modify the Output Data Register) and the Direct modification of the Output Data Register in the Assembly code.

    IF your system only consists of the 4 LED's you are describing, I would expect the Assembly code AND C code to behave EXACTLY as you are describing.

    Your code is modifiy GPIO_A to turn on and off the 3 LED's connected to it and Your code is modifiying GPIO_B to turn on (but never off, but it could) the single LED.

    If you want the LED on GPIO_B to turn off, you will need to set the bit in the output data register to 1.  Your code only ever sets it to zero.

    You have CLEARLY read the Reference Manual.  You understand of the RCC and the GPIO.   

    Our code does this

    1) Enable the Clocks for GPIOA and GPIOB.  Does this in both C and assembly language.

    2) For some reason the Assembly language code turns on ADC1 and enables continuous conversion mode. The C code does not

    3)  You set 1 bit in GPIO_B to output

    4) You set 3 bits in GPIO_A to output

    5) The loop starts.  This also has a slight differenct

    6)    Assembly

                Set all bits in GPIO_B ODR register except bit 6 which is cleared.

            C

                Clear bit 6 in GPIO_B_ODR

                Set bit 5 and 7 in GPIO_B_ODR

                All other bits remain as they were

    7) Assembly

                Set all bits in GPIO_A ODR register except bit 7 which is cleared

          C

               Clear bit 7 in GPIO_ODR

               Set bit 5 and 6 in GPIO_ODR

                all other bits remain as they were

    8) Assembly

                Set all bits in GPIO_A ODR register except bit 6 which is cleared

          C

               Clear bit 6 in GPIO_ODR

               Set bit 5 and 7 in GPIO_ODR

                all other bits remain as they were

    7) Assembly

                Set all bits in GPIO_A ODR register except bit 5 which is cleared

          C

               Clear bit 5 in GPIO_ODR

               Set bit 6 and 7 in GPIO_ODR

                all other bits remain as they were

    At this point they both loop back to step 6

    So, as coded your code Turns on the LED connected to GPIO_B pin 6.  It never makes it anything different. IF you want the LED to go off, at some point you will need to set the value in the GPIO_B ODR Pin 6 to a 1..  

    The code modifies port At so that the only the LED on Pin 7 is on the 500ms, then only the LED on Pin 6 is on for 500ms, then only the LED on Pin 5 is on, but for 1000ms.  (In all of these cases the LED on PortB stays on.

    I would change it so your code uses only the Bit Set Reset Register to make changes to the ODR register.  It would decide at what point you want to LED on Port B to burn off and make sure at that point in our code, you do to set that bit to a 1.

    GPIOB->BSRR = 0x00400000; // This should turn the LED on PortB on.  ( all the bits in the 16 bit value 0x0040 are cleared)

    GPIOB->BSRR = 0x00000040; .. This should turn the LED on PortB off.  ( all the bits in the 16 bit value 0x0040 are set)

    So using the BSRR allows  you to clear up the 16 bits (the first 16 in the 32 bit value, and to Set up to 16 bits (the last 16 bits in the 32-bit value) 

    IF you ask for a bit to be cleared and the same bit to be set, it will only be set.

    Using the BSRR register will not modify any bits in the ODR that you do not specify to be modified.

      

                

Reply
  • I am very impressed with your level of skill, your ability to actually read the STM reference manual and actually write succinct and "proper" code in both C and assembly language.  The only difference with  your code seems to be the use of the Bit Set Reset Register (used in the C code and by far the best choice to modify the Output Data Register) and the Direct modification of the Output Data Register in the Assembly code.

    IF your system only consists of the 4 LED's you are describing, I would expect the Assembly code AND C code to behave EXACTLY as you are describing.

    Your code is modifiy GPIO_A to turn on and off the 3 LED's connected to it and Your code is modifiying GPIO_B to turn on (but never off, but it could) the single LED.

    If you want the LED on GPIO_B to turn off, you will need to set the bit in the output data register to 1.  Your code only ever sets it to zero.

    You have CLEARLY read the Reference Manual.  You understand of the RCC and the GPIO.   

    Our code does this

    1) Enable the Clocks for GPIOA and GPIOB.  Does this in both C and assembly language.

    2) For some reason the Assembly language code turns on ADC1 and enables continuous conversion mode. The C code does not

    3)  You set 1 bit in GPIO_B to output

    4) You set 3 bits in GPIO_A to output

    5) The loop starts.  This also has a slight differenct

    6)    Assembly

                Set all bits in GPIO_B ODR register except bit 6 which is cleared.

            C

                Clear bit 6 in GPIO_B_ODR

                Set bit 5 and 7 in GPIO_B_ODR

                All other bits remain as they were

    7) Assembly

                Set all bits in GPIO_A ODR register except bit 7 which is cleared

          C

               Clear bit 7 in GPIO_ODR

               Set bit 5 and 6 in GPIO_ODR

                all other bits remain as they were

    8) Assembly

                Set all bits in GPIO_A ODR register except bit 6 which is cleared

          C

               Clear bit 6 in GPIO_ODR

               Set bit 5 and 7 in GPIO_ODR

                all other bits remain as they were

    7) Assembly

                Set all bits in GPIO_A ODR register except bit 5 which is cleared

          C

               Clear bit 5 in GPIO_ODR

               Set bit 6 and 7 in GPIO_ODR

                all other bits remain as they were

    At this point they both loop back to step 6

    So, as coded your code Turns on the LED connected to GPIO_B pin 6.  It never makes it anything different. IF you want the LED to go off, at some point you will need to set the value in the GPIO_B ODR Pin 6 to a 1..  

    The code modifies port At so that the only the LED on Pin 7 is on the 500ms, then only the LED on Pin 6 is on for 500ms, then only the LED on Pin 5 is on, but for 1000ms.  (In all of these cases the LED on PortB stays on.

    I would change it so your code uses only the Bit Set Reset Register to make changes to the ODR register.  It would decide at what point you want to LED on Port B to burn off and make sure at that point in our code, you do to set that bit to a 1.

    GPIOB->BSRR = 0x00400000; // This should turn the LED on PortB on.  ( all the bits in the 16 bit value 0x0040 are cleared)

    GPIOB->BSRR = 0x00000040; .. This should turn the LED on PortB off.  ( all the bits in the 16 bit value 0x0040 are set)

    So using the BSRR allows  you to clear up the 16 bits (the first 16 in the 32 bit value, and to Set up to 16 bits (the last 16 bits in the 32-bit value) 

    IF you ask for a bit to be cleared and the same bit to be set, it will only be set.

    Using the BSRR register will not modify any bits in the ODR that you do not specify to be modified.

      

                

Children