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?
I made two version of it, for .c and .asm. I don't know how to solve it after this.
AREA PROG, CODE, READONLY EXPORT main ENTRY RCC_AHB1ENR equ 0x40023830GPIOA_MODER equ 0x40020000GPIOA_ODR equ 0x40020014 ADC_SQR1 equ 0x40012008GPIOB_MODER equ 0x40020400GPIOB_ODR equ 0x40020414 main ldr r4, =RCC_AHB1ENR ; enable GPIOA clock ldr r5, [r4] orr r5, #3 str r5, [r4] ldr r1, =ADC_SQR1 ; enable GPIOB clock ldr r2, [r1] orr r2, #3 str r2, [r1] ldr r4, =GPIOA_MODER ; set pin A to output mode ldr r5, [r4] bic r5, #0x0000FC00 orr r5, #0x00005400 str r5, [r4]
ldr r1, =GPIOB_MODER ; set pin B to output mode ldr r2, [r1] bic r2, #0x00003000 orr r2, #0x00001000 str r2, [r1]
L1 ldr r4, =GPIOB_ODR ldr r5, =0x0000FFBF ; turn on D4 str r5, [r4] mov r0, #500 bl delay
ldr r4, =GPIOA_ODR ldr r5, =0x0000FF7F ; turn on D3 str r5, [r4] mov r0, #500 bl delay ldr r4, =GPIOA_ODR ldr r5, =0x0000FFBF ; turn on D2 str r5, [r4] mov r0, #500 bl delay ldr r4, =GPIOA_ODR ldr r5, =0x0000FFDF ; turn on D1 str r5, [r4] mov r0, #500 bl delay b L1 ; loop forever
delay ldr r1, =5325DL1 subs r1, r1, #1bne DL1 subs r0, r0, #1 bne delay bx lr endThis one is in .asm file. Can
while(1){GPIOB->BSRR = 0x00000040; // PB6 ONdelayMs(500);GPIOB->BSRR = 0x00400000; // PB6 OFFdelayMs(500);GPIOA->BSRR = 0x00800060;// PA7 OFF, PA5,PA6 ONdelayMs(500);GPIOA->BSRR = 0x004000A0;delayMs(500);GPIOA->BSRR = 0x002000C0;delayMs(500);}
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
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
Clear bit 6 in GPIO_ODR
Set bit 5 and 7 in GPIO_ODR
Set all bits in GPIO_A ODR register except bit 5 which is cleared
Clear bit 5 in GPIO_ODR
Set bit 6 and 7 in GPIO_ODR
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.
Yes, this is a little more succulent than what I wrote. And only use the BSRR to modify the ODR.
Oh I see, the coding for the LED for PB6 and LED for PA6 interfered with each other. I have tried your code and run it, and yeah, it works but after the execution of the PB6 OFF codes, the LED turns back on. Since I wanted the LED to turn off, so I copied the coding for PB6 ON after that which fixed the problem.
while(1){GPIOB->BSRR = 0x00000040; // PB6 ON (LED OFF)delayMs(500);GPIOB->BSRR = 0x00400000; // PB6 OFF (LED ON)delayMs(500);GPIOB->BSRR = 0x00000040; // PB6 ON (LED OFF)delayMs(500);GPIOA->BSRR = 0x00800060;// PA7 OFF, PA5,PA6 ONdelayMs(500);GPIOA->BSRR = 0x004000A0;delayMs(500);GPIOA->BSRR = 0x002000C0;delayMs(500);}
Thank you so much. I really appreciated the help you guys have given me. =D
So, is this line of code unnecessary for this program? I'm a little bit confused on this one.
Robert McNamara said:2) For some reason the Assembly language code turns on ADC1 and enables continuous conversion mode. The C code does not
I'm a new member here, so I'm sorry for this one. I should have explored more on the settings, before posting.