---
# System prepended metadata

title: Basic IO - GPIO

---

# **Basic IO - GPIO**

Original authors: Alex Chan, Leo Wong and Christopher Kwan

Further Modified by: William Lam

***

## **Basics**

### **Fundamental Program Structure Example: Do something every 100ms**
```c
int main(void)
{
    // Initialize Everything Here, this is like setup() in Arduino
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();     //Initialize most GPIOs on board
    MX_DMA_Init();      //Initialize DMA

    // the following is like loop() in Arduino also
    //Run code in an infinite loop: this is like loop() in Arduino
    while (1) {
      static uint32_t last_ticks = 0;	//This variable keeps its stored value through every iteration
        //Everything inside this if-statements gets called every 100ms
      if((HAL_GetTick() - last_ticks) >= 100){
            //Write your code here....
            // sth ....
            // bruh....
          last_ticks = HAL_GetTick();
      }
    }
}
```

* The **`HAL_GetTick`** function is the main thing to use for timing control in software. It counts up by one every millisecond(ms).

***
### **Data Types**
In embedded system programming, Data type  `int`, `long`, `long long`, `float`, `double` are not suggested to use. Instead, use the followings:

| Short form | Full name          | Meaning                  |
| :--------: | :----------------- | :----------------------- |
| `uint8_t`  | unsigned char      | unsigned 8 bits integer  |
|  uint16_t  | unsigned short     | unsigned 16 bits integer |
|  uint32_t  | unsigned long      | unsigned 32 bits integer |
|  uint64_t  | unsigned long long | unsigned 64 bits integer |
|   int8_t   | signed char        | signed 8 bits integer    |
|  int16_t   | signed short       | signed 16 bits integer   |
|  int32_t   | signed long        | signed 32 bits integer   |
|  int64_t   | signed long long   | signed 64 bits integer   |

Both full name and short form work.

**Note:** 
* The value of a `signed` number is typically less than half the value of an `unsigned` number because the most significant bit (MSB) in the signed representation is used to indicate the sign of the number.
* `float` and `double` should only be used when necessary as floating point calculation normally takes more time.

***

## **What is GPIO?**
>A **general-purpose input/output (GPIO)** is an digital signal pin on an integrated circuit or electronic circuit board whose behavior — including whether it acts as an input or output — is controllable by the user at run time.

>In short, GPIO is for ***outputting and reading HIGH [1] and LOW [0] values***. (Sometimes we will use GPIO for analogue values but don't worry about that for now)

### **GPIO Configuration**

* Every pin on the MCU can be used as GPIO, they are divided into a blocks of 16 pins due to internal structure
  * Each block is named by letters: `GPIOA`, `GPIOB`, `GPIOC`...
    * Each pin within the block is numbered from 0: `GPIO_PIN_0`, `GPIO_PIN_1`, `GPIO_PIN_2`...
* So every pin is referred to by a pair of values: the port and the pin: `GPIOE, GPIO_PIN_3` or when humans are talking we say `PE3`

***
### **`Macro`s for GPIO**
We will often use `#define` to give more meaningful names to the ports and pins, for ease of use:

```c
/* main.h */
#define UP_BTN_GPIO_Port     GPIOE
#define UP_BTN_Pin           GPIO_PIN_3
#define LED1_GPIO_Port       GPIOE
#define LED1_Pin             GPIO_PIN_4
#define LED2_GPIO_Port       GPIOE
#define LED2_PIN             GPIO_PIN_5
#define LED3_GPIO_Port       GPIOE
#define LED3_PIN             GPIO_PIN_6
```

***
### **GPIO Function in the Program**

The `HAL_GPIO_ReadPin` function reads the GPIO input.

```c
/* stm32f4xx_hal_gpio.h */
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
```

The `HAL_GPIO_WritePin` function write the GPIO output.
```c
/* stm32f4xx_hal_gpio.h */
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
```
* The `GPIO_PIN` parameter can be `GPIO_PIN_RESET` (0) or `GPIO_PIN_SET` (1).

The `HAL_GPIO_TogglePin` function toggle the GPIO output.
```c
/* stm32f4xx_hal_gpio.h */
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
```
***
#### Readability (Macro):

* Writing `HAL_GPIO_ReadPin(XXX_GPIO_Port, XXX_Pin)` every time may seem tidious. However with the help of magical c prepocessor, we can make it easier
```c
/* main.h */
#define gpio_read(gpio) HAL_GPIO_ReadPin(gpio##_GPIO_Port, gpio##_Pin)

// usage
uint8_t state = gpio_read(BTN1);
```

#### **Writing GPIO Output in the Program**

The following macros can be found in `main.h`

* The `gpio_set(gpio)` macro sets the GPIO pin to be 1.

* The `gpio_reset(gpio)` macro resets the GPIO pin to 0.

* The `gpio_toggle(gpio)` macro toggles the GPIO pin. (i.e. changes the GPIO pin state to 1 if it was originally 0 and vice versa)

#### **Examples:**

```c
// Turns off the LED
gpio_set(LED1);

// Turns on the LED
gpio_reset(LED1);

// Toggles the LED
gpio_toggle(LED1);
```

### **Full Example (Flickering the LED1 for every 500 ticks)**

```c
/* main.c */
int main(void) {

    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();

    volatile uint32_t last_ticks = HAL_GetTick();

    while (1) {

        if (HAL_GetTick() - last_ticks > 500) {
            last_ticks = HAL_GetTick();
            gpio_toggle(LED1); // flickering the LED1
        }
    }
    return 0;
}
```

***

## **_In Class Exercise_**:

### There are few step before using GPIO pins in your program:

1. Find which GPIO you want to use in `main.h` (if you can't find one, define it yourself).
2. Initialize the GPIO marco by yourself in `gpio.h`. Remember which GPIO function you need for the LED control.
3. Use the GPIO marco to  control the LED.

### **Requirement**
1. Turning on the LED in the first 5 seconds.
2. Flashing the LED for every 500 between 5 - 10 seconds.
3. Flashing the LED for every 100 between 10 - 15 seconds. 
4. Turning off the LED

