Try   HackMD

STM32 - GPIO, Delay and Debugger

tags: firmware_hardware electrical_system NTURT

Author: @andre-liang

reference link: https://www.leagueoflegends.com/en-us/champions/gangplank/

Preface

General-purpose input/output (GPIO) is the easiest way for a microcontroller to communicate with outside world using digital signal.

Create a New Project

Open up STM32CubeIDE, click on File -> New -> STM32 Project. On the target selection screen, type in STM32F103C8T6 as commercial part number.

Then choose a project name.

Then you should see the project window.

Configure Pins

In order for the GPIO functionality to work properly, we must tell the microcontroller we want each pin to be a input pin or a output pin, also the input/output mode.

There are two output mode and three input mode.

Output Mode

  • Output Push-Pull
  • Output Open-Drain

reference link: https://circuitdigest.com/forums/embedded/difference-between-open-drain-and-push-pull

As the name implies, the push-pull mode is capable of driving two output levels: pull to ground and push to power supply voltage. It is implemented with a pair of switch. This configuration is most commonly used in interfaces that have unidirectional lines.

While in open-drain mode, the pin can drive it only to ground. The other possible state is high impedance (Hi-Z), which means the voltage depends on external voltage. This configuration most commonly used in communication interfaces where multiple devices are connected on the same line.

We usually use push-pull mode as default.

Further reading: link

Input Mode

  • None
  • Pull-Up
  • Pull-Down

reference link: https://www.mlmvlab.bime.ntu.edu.tw/%E5%BE%AE%E6%8E%A7%E5%88%B6%E5%99%A8%E5%8E%9F%E7%90%86%E8%88%87%E6%87%89%E7%94%A8

The pull-up/pull-down resistor is used to prevent reading floating value when connected to open-circuit. In pull-up mode, the resistor keeps the input at HIGH, while in pull-down mode the resistor keeps the input at LOW.

To configure each pin to specific pin mode, open the <project-name>.ioc in the root of the project folder, right-click on the target pin and toggle the pin mode.

Click on Pinout & Configuration -> System Core -> GPIO to switch between input/output mode or play around with other GPIO features.

Note: All the formentioned settings could theoretically be set by manually changing the value of different registers, but we usually let the IDE to do that tedious job for us

Save the <project-name>.ioc and let the code generation tool to apply the settings for you.

Code Structure

When you are learning C/C++, the first program you write probably looks like this:

#include <iostream>

int main()
{
    std::cout<<"Hello World!"<<std::endl;
}

The main() function is the entry point of the program, i.e. the program execution starts from that function call.

In a STM32CubeIDE project, the entry point is the <project-name>/Core/Src/main.c.

int main(void)
{
    /* Settings for HAL library */
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    /* Only executed once */
    while (1)
    {
    /* Executed indefinitely*/
    }
}

You can modify the file to make the microcontroller to do what you want.

Writing/Reading Digital Signal

Write Signal

To alter the digital signal output of certain pin, we use the following function:

HAL_GPIO_WritePin(GPIOx, GPIO_Pin, PinState);

A pin is defined as P<GPIOx><GPIO_Pin>, and PinState could be either GPIO_PIN_SET for output HIGH-Voltage or GPIO_PIN_RESET for LOW-Voltage.

For example:

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);

Means to output HIGH at pin PA0. You can type <space>+<control> to activate auto-complete.

Read Signal

To read the digital signal of certain pin, we use:

var = HAL_GPIO_ReadPin(GPIOx, GPIO_Pin);

Debugger

First declare a variable outside main() function scope, then read the pin value to that variable.

int buttonState;

int main(void){
    // HAL init functions ommited;
    while(1){
        buttonState = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
    }
}

For convenience, I use a button module to generate a input signal. When pressed down, the OUT pin will output a HIGH signal.Connect the OUT pin to PA0.

Since STM-32 don't have a screen, you can't output variables to standard output like we normally do in a console application. But we can use a dubugger to see the value of variables directly.

To use the debugger, click Debug <project-name> Debug (with bug icon) to start debugging.

Then click the search icon on the top-right corner, search for Live Expressions and enter the variable name you want to observe.

You should see the value changes as you press down the button.

Delay

We can use HAL_Delay(delayTime); to suspends (waits) execution of the microcontroller for a given number of micro-seconds.

while (1){
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,         GPIO_PIN_SET);
    HAL_Delay(200); // Stop for 0.2 second
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
    HAL_Delay(200);
}

Then connect a LED to pin A0, remember to attach a resistor to limit the current flow.

Then you should see the LED blinks every 0.2 second.