DEV Community

vietdt89
vietdt89

Posted on

Push button and led blink with STM32F411RE

Write a driver to listen to button push event then blink led

Tool
Board STm32F411RE
Cube IDE
Datasheet
Reference manual
User manual

Image description

1. Open User manual to locate led and button pin

Image description
To confirm the port and pin, we check the board selector in CubeIDE

Image description
Now we know that LED is on PA15 (port A pin 5), button is on PC 13 (Port C pin 13). We go to block diagram to check the bus that connect to that port. We need to enable clock to the bus before communicating with the ports
To check the bus, go to Datasheet-> block diagram
Image description
Both ports are on bus AHB1

2. Download header file

Now go to ST website and download the STM32CubeF4. This contains the header for controlling the register so that we don't need to calculate the bit location manually.
Get the latest here
Image description
We will keep these folders and delete all the remaining
\STM32Cube_FW_F4_V1.28.0\Drivers\CMSIS\Include
\STM32Cube_FW_F4_V1.28.0\Drivers\CMSIS\Device\ST\STM32F4xx

3. Create new project

Create new project with STM32F411 component
Then import the header folder to Cube project
Image description

4. Source code

If we do not have stm32f4xx header, we will have to define the register location manually
In the code, we wil use structs provided by the header.

/*
#define PERIPH_BASE             (0x40000000UL)
#define AHB1PERIPH_OFFSET               (0x00020000UL)
#define AHB1PERIPH_BASE                 (PERIPH_BASE + AHB1PERIPH_OFFSET)

#define GPIOA_OFFSET                    (0x0000UL)
#define GPIOA_BASE              (AHB1PERIPH_BASE + GPIOA_OFFSET)

#define RCC_OFFSET              (0x3800UL)
#define RCC_BASE                (AHB1PERIPH_BASE + RCC_OFFSET)

#define AHB1EN_R_OFFSET                 (0x30UL)
#define RCC_AHB1EN_R                    (*(volatile unsigned int*)(RCC_BASE + AHB1EN_R_OFFSET))

#define MODE_R_OFFSET                    (0x00UL)
#define GPIOA_MODE_R                     (*(volatile unsigned int*)(GPIOA_BASE + MODE_R_OFFSET))

#define OD_R_OFFSET              (0x14UL)
#define GPIOA_OD_R               (*(volatile unsigned int*)(GPIOA_BASE + OD_R_OFFSET))
*/
Enter fullscreen mode Exit fullscreen mode

Using header

#include "stm32f4xx.h"
#define GPIOAEN                  (1U<<0)
#define GPIOCEN                  (1U<<2)

#define PIN5                     (1U<<5)
#define PIN13                    (1U<<13)

#define LED_PIN                  PIN5
#define BTN_PIN                  PIN13

int main(void){
        // set clock for bus
    RCC->AHB1ENR |= GPIOAEN;
    RCC->AHB1ENR |= GPIOCEN;
        //set mode register for port A and port C
    GPIOA->MODER |= (1U<<10);
    GPIOA->MODER&=~(1U<<11);

    GPIOC->MODER &=~(1U<<26);
    GPIOC->MODER &=~(1U<<27);
        // reset led into off state
    //GPIOA->ODR &= ~LED_PIN;
    GPIOA->BSRR = (1U<<21);
        // blink loop
    while(1){
        if(GPIOC->IDR & BTN_PIN){//if 
            GPIOA->BSRR |= (1U<<21);
        }
        else{
            while (1){
                                //GPIOA->ODR|= LED_PIN;
                GPIOA->BSRR |= LED_PIN;
                for(int i = 0; i < 100000; i++){}//delay
                                //GPIOA->ODR &= ~LED_PIN;
                GPIOA->BSRR |= (1U<<21);
                for(int i = 0; i < 100000; i++){}//delay
                if(GPIOC->IDR & BTN_PIN){
                    break;
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Explain
1. Go to memory mapping in datasheet

Image description
We can see that AHB1 bus register starts at 0x4002 0000 and the root address of all registers starts at 0x4000 0000. From this, we will define all register that we need to control the ports.
2. Register needed

All information is in Reference manual document

  • RCC AHB1: provide clock to AHB1 bus

Image description
Port A is at pin 0, port C is at pin 2.

  • Mode register: to set operation mode for each port.

Image description
We use port A to set led, port C to receive button event so port A will be output mode, port C will be input mode
Set led at Port A pin 5, so bit 11 and 10 of mode register should be 01.
Receive button event at Port C pin 13 so bit 27 26 of mode register should be 00.

3. Set led

We have 2 ways to set led. One is to set data pin, the other is to set reset pin.

  • Set data pin Find data register

Image description
Since led pin is in pin 5. We set led on off by setting bit 5 with 1 or 0

GPIOA->ODR|= LED_PIN;
GPIOA->ODR &= ~LED_PIN;
Enter fullscreen mode Exit fullscreen mode
  • Set/reset bit reset register

Image description
Set pin 5 bit 5 in reset in bit 21. So the code is

GPIOA->BSRR |= LED_PIN;
GPIOA->BSRR |= (1U<<21);
Enter fullscreen mode Exit fullscreen mode
  • To listen to button event, we will listen to pin 13 of input data register

Image description

GPIOC->IDR & BTN_PIN
Enter fullscreen mode Exit fullscreen mode

if bit is 1, button is released, 0 button is pressed
Here we have pullup, pulldown transistor for button

  • We need pullup transistor so that when button is not pressed, the state will be pulled up to HIGH
  • We need pulldown transistor so that when button is pressed, the state will be pulled down to LOW

Top comments (0)