# **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