In this post, I will be talking about controlling an LED on the Nucleo-64 board. We will go through the steps of accessing registers on the board, and even create a delay function to have the LED blink.

Picking the LED

To start, I used the STM32 Nucleo-64 board with a STM32F446RE MCU. This will be all we need. Next, we need to determine which LED we will be using and how to control it. This can be found in the reference manual of the board. In our case, we will be using the user LED LD2, which can be controlled using the IO pin PA5. With that in mind, we need to do a little initial setup before actually being able to turn on the LED.

Registers

Before we can interact with the LED, we need to access a few registers. Because the LED can be controlled using pin 5 on Port A, we need to enable the clock for Port A. To do this, we need to access to the RCC AHB1 Peripheral Clock Enable Register. The base address for this register is 0x40023800. This can be found in the reference manual for the board. The offset for the clock enable register is 0x30. So now that we know the address (0x40023830), we can create a pointer variable to store the address:

uint32_t* pRCC_PortA = (uint32_t*) 0x40023830; //address for clock enable register

The next step is to set the pin 5 from Port A to be output, since we are outputting light from the board. Again, we will need to access a register, this one being the GPIO Port Mode register. The address for this register is 0x40020000:

uint32_t* pPortModeA = (uint32_t*) 0x40020000; //address for GPIO pin mode

The last register we need will be the GPIO Port Output Data register, which will be located at 0x40020014:

uint32_t* pOutput_data_r = (uint32_t*) 0x40020014;    // address for data output register

Turning on the LED

Now that have the necessary registers, we can begin programming to actually turn on the LED. First, in the clock enable register, we need to set bit 0 for Port A to 1:

//Enable clock for Port A
*pRCC_PortA |= 0x01;

Next we need to set the mode of port A to output. According to the reference manual, each pin in Port A has two bits for setting the mode. For PA5, we use bits 10 and 11. So let’s set the bits to 01 to set the pin to be output:

//Set the pin mode for PA5 to output
*pPortModeA |= (1 << 10); //set bits 10 and 11 to 01

Lastly, we need to turn on the LED by going into the output data register and setting bit 5 to 1:

*pOutput_data_r |= (1 << 5); //turn led on

After that, we can insert a while(1) and test our code on the board.

To turn the LED on and off continuously, we can create a simple delay function to toggle the LED after a certain amount of time. In the delay function, all we will have is a for loop that iterates a certain number of times.

void delay(long int num){
	for(int i=0;i<num;i++);
}

When the for loop completes the iterations, we simply update the output data register and set bit 5 to either 0 or 1 in the while loop. For the num, I just used a large number like 1000000 to test.

while(1){
    	 delay(num);
    	 *pOutput_data_r |= (1 << 5); //turn led on

    	 delay(num);
    	 *pOutput_data_r &= ~(1 << 5);// turn led off

     }

And that’s how you can interact with the LED on the Nucleo-64 board.

Full Code:

#include <stdint.h>

void delay(long int num){
	for(int i=0;i<num;i++);
}

int main(void)
{
	long int num = 1000000;

     uint32_t* pRCC_PortA = (uint32_t*) 0x40023830; //address for clock enable register
     uint32_t* pPortModeA = (uint32_t*) 0x40020000; //address for GPIO pin mode
     uint32_t* pOutput_data_r = (uint32_t*) 0x40020014; // address for data output register

     //Enable clock for Port A
     *pRCC_PortA |= 0x01;

     //Set the pin mode for PA5 to output
     *pPortModeA |= (1 << 10); //set bits 10 and 11 to 01


     while(1){
    	 delay(num);
    	 *pOutput_data_r |= (1 << 5); //turn led on

    	 delay(num);
    	 *pOutput_data_r &= ~(1 << 5);// turn led off

     }
}