Skip to main content
FGiai.1
Associate II
April 19, 2020
Question

How to turn on a LED modyfing registers directly?

  • April 19, 2020
  • 13 replies
  • 2336 views

Hi to all,

I'm trying to use the Nucleo F446RE board to switch on an external LED. by using directly the registers

IN particular, I have connected the pin PA5 in series with a resistor, a LED and finally with the GND of the board.

The code uses is shown before. Initially I have activated the AHB1 internal pheripheral. Then, I enabled and forced to HIGH the pin PA5 of the board.

int main(int argc, char* argv[])
{
	/** AHB1 **/
	volatile uint32_t *RCC_AHB1ENR = 0x0;
	RCC_AHB1ENR = (uint32_t*)(0x40023800 + 0x30);
	*RCC_AHB1ENR = *RCC_AHB1ENR | 0x1;
 
	/** GPIOA **/
	volatile uint32_t *GPIOA_MODER = 0x0, *GPIOA_ODR = 0x0;
	GPIOA_MODER = (uint32_t*)0x40020000;
	*GPIOA_MODER = *GPIOA_MODER | 0x400;
	GPIOA_ODR = (uint32_t*)(0x40020000 + 0x14);
	*GPIOA_ODR = *GPIOA_ODR | 0x20;
	
	/** Infinite loop **/
	while (1);
}

The code is correctly compiled and loaded on the board, bu the problem is that the LED doesn't turn on. Can someome suggest how to modify the code? There are some other registers to modify? Something else to do?

Thank you very much in advance.

This topic has been closed for replies.

13 replies

waclawek.jan
Super User
April 19, 2020

Code looks good.

Don't you have some debugger installed, so that you can observe the registers?

Isn't the LED reverse polarized? Can you measure the pin's voltage using multimeter?

JW

FGiai.1
FGiai.1Author
Associate II
April 19, 2020

I have no a debugger installed yet. I'm just I'm just studying and Learning the basics, so I wanted to start coding. THe LED is not reverse polarized, but I cannot verify because I have no a multimiter.

Thank you for the answer. I think the code is correct, I have to verify why it doesn't work in some way.

KnarfB
Super User
April 19, 2020

Pin PA5 is already connected to the green LED on that board. You should not need to add another LED. Your code works on my copy of that board.

FGiai.1
FGiai.1Author
Associate II
April 19, 2020

Yes I know that PA5 is connected to the green led of the board, but in this case I'm using as a general purpose output, just to try to code a very simple program.

I already tried to change Pin but nothing changed. What IDE do you use? There is some trick that can make the code not working during the flashing?

KnarfB
Super User
April 19, 2020

I'm using STMCubeIDE. Maybe you start with a C code example. Code can be generated by STM32CubeIDE. You only add few lines. There is a short intro video https://youtu.be/eumKLXNlM0U. Here are some more examples, but for a different board: https://gitlab.com/stm32mcu/wiki/-/wikis/home

FGiai.1
FGiai.1Author
Associate II
April 19, 2020

Yes I know that PA5 is connected to the green led of the board, but in this case I'm using as a general purpose output, just to try to code a very simple program.

What IDE do you use? There is some trick that can make the code not working during the flashing?

waclawek.jan
Super User
April 19, 2020

@FGiai.1​ 

How exactly do you compile the program? And how exactly do you "burn" the binary into the board?

@KnarfB​ ,

Can you please post the proven working binary/hex?

JW

KnarfB
Super User
April 19, 2020

Good idea, Jan.

@FGiai.1​ The file must be unzipped first. it is a .bin file which I cannot upload directly. You can drag the .bin file onto the "USB Drive" that shows up when the NUCLEO board is connected. That will flash the µC and switch the LED on.

KnarfB
Super User
April 19, 2020

Here is the complete project. It uses @FGiai.1​ code as main() in a cube generated project. The only difference to HAL code (not used here) I see is, that HAL code reads *RCC_AHB1ENR back to a volatile dummy variable after the write. Didn't find a hint in the ref man that this is needed.

FGiai.1
FGiai.1Author
Associate II
April 20, 2020

Hi to all,

Thanks for the answers.

I have a new version of the code. In this case, the code would turn on the PA8 pin.

int main(int argc, char* argv[])
{
	/** RCC **/
	/* RCC */
	volatile uint32_t *RCC = 0x0;
	RCC = (uint32_t*)0x40023800;
	/* RCC_AHB1ENR */
	volatile uint32_t *RCC_AHB1ENR = 0x0;
	RCC_AHB1ENR = (uint32_t*)(0x40023800 + 0x30);
	*RCC_AHB1ENR |= 0x1;
 
	/** GPIOA **/
	/* GPIOA */
	volatile uint32_t *GPIOA = 0x0;
	GPIOA = (uint32_t*)0x40020000;
	/* GPIOA_MODER */
	volatile uint32_t *GPIOA_MODER = 0x0;
	GPIOA_MODER = (uint32_t*)(0x40020000 + 0x00);
	*GPIOA_MODER |= 1 << 16;
	*GPIOA_MODER &= ~(0 << 17);
	/* GPIOA_ODR */
	volatile uint32_t *GPIOA_ODR = 0x0;
	GPIOA_ODR = (uint32_t*)(0x40020000 + 0x14);
	*GPIOA_ODR |= 1 << 8;
}

I think that the code works well because connecting with a wire PA8 and PA5 pins, the green led on the board (that connected to the PA5 pin) switche on. However, when i connect PA8 pin to external circuit composed by resistor - LED - board GND, the LED doesn't turn on (I tried both the polarizations of the LED and also to remove the resistor but nothing changed).

There is maybe some additional register to set? Maybe the generated voltage is not sufficiently high?

I have an additional question. In this code, I wrote drectly all the memory locations. But, (consider for example the GPIOA_ODR register), if I want to calculate the memory location of a register summing the boundary adress and the offset, how can I do? I tried in the following way but I think it is not correct because in this way the code shown before doesn't work anymore. Can you help also with this?

volatile uint32_t *GPIOA = 0x0;
GPIOA = (uint32_t*)0x40020000;
 
volatile uint32_t *GPIOA_ODR = 0x0;
GPIOA_ODR = (uint32_t*)(GPIOA + 0x14);

I don't know why but using this code doesn't work, while simply sobstituting in line 5 GPIOA with 0x40020000 works. the Do you know how to calculate correctly?

To compile I'm using Eclipse and to load the code on the board I'm using CubeProgrammer.

FGiai.1
FGiai.1Author
Associate II
April 20, 2020

In the second code, instead of 0014 (line 5) consider 0x14...