GPIO - user version
Let's throw away the useless theories and focus on how to use it
GPIO are simply the pins/wires on the MCU (CPU of your robot)
We call the pins
PA0, PA1, PA2, ... , PA16,
PB0, PB1, ... , PB16,
PC0, ... , PC16,
...,
PI0, ... , PI16
Remember to ask your HW which pins they plug their wires in
GPIO Pins can be set for Input or Output
Input examples:
buttons
toggle switch
digital line sensors (that only returns white and black)
Output examples:
LEDs (On/Off)
Pneumatic cylinders (extend/retract)
Initialization of GPIO
We need to tell the MCU whether we use it for input/output
TODO : how to setup the GPIO pins on .ioc file on CubeIDE
// By default, this line of code is already in your main.c
// It initializes all GPIO that you set up in the .ioc file
MX_GPIO_Init();
GPIO for Input
/* main.h */
#define gpio_read(gpio) HAL_GPIO_ReadPin(gpio##_GPIO_Port, gpio##_Pin)
// usage
uint8_t state = gpio_read(BTN1);
Don't ask why, your HW teammate might make the circuit "0 for Pressed and 1 for Released" so you never know which is Pressed and which is Released until you try it yourself.
More Readability:
Writing gpio_read(BTN1)
is also not very readable because you don't know if gpio_read(BTN1) == 1
is pressed or gpio_read(BTN1) == 0
is pressed.
So, we defined some more macro functions in main.h for more readability:
/* main.h */
#define btn_read(btn) gpio_read(btn)
If one day your hardware groupmate accidentally swapped the wires of buttons, you can simply change the defines above. You don't need to read through your hundreds/thousands of lines of code and change every gpio_read() you wrote.
GPIO for Output
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)
Don't ask why, your HW teammate might make the circuit "0 for On and 1 for Off" so you never know which is On and which is Off until you try it yourself.
Examples:
/* main.h */
#define gpio_set(gpio) HAL_GPIO_WritePin(gpio##_GPIO_Port, gpio##_Pin, GPIO_PIN_SET)
#define gpio_reset(gpio) HAL_GPIO_WritePin(gpio##_GPIO_Port, gpio##_Pin, GPIO_PIN_RESET)
#define gpio_toggle(gpio) HAL_GPIO_TogglePin(gpio##_GPIO_Port, gpio##_Pin)
// usage
// 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)
/* 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;
}
More Readability:
Writing gpio_set(LED1)
is still not very readable because you don't know if it is turning on/off the LED1.
So, we defined some more macro functions in main.h for more readability:
/* main.h */
#define led_on(led) gpio_reset(led) // notice that reset the pin turns the led on
#define led_off(led) gpio_set(led)
#define led_toggle(led) gpio_toggle(led)
If one day your hardware groupmate accidentally swapped the wires of all LEDs, you can simply change the defines above. You don't need to read through your hundreds/thousands of lines of code and change every gpio_set() gpio_reset() you wrote.
Last updated