
GPIO(General Purpose Input/Output)는 마이크로컨트롤러가 외부 세계와 소통하기 위한 기본 통로이다. 설정에 따라 출력(OUTPUT)을 통해 외부 장치에 신호를 보내거나, 입력(INPUT)을 통해 외부 장치의 신호를 읽을 수 있다.
보드에는 여러 개의 핀이 있으며, 각 핀마다 번호가 붙어 있다. 모든 핀이 GPIO는 아니며, 일부는 GND(접지), 전원 입력(VCC) 등 다른 기능을 가진다. 어떤 핀이 어떤 기능을 하는지는 반드시 핀아웃(pinout) 문서를 참고해야 한다.
GPIO는 디지털 신호(이진 값)를 주고받는다.
예시:
버튼을 제대로 연결하지 않으면 입력 핀이 Floating이 되어 눌리지 않았는데 무작위로 High/Low 값을 읽을 수 있다.
이를 해결하기 위해 풀업(Pull-up) 또는 풀다운(Pull-down) 저항을 사용한다.

대다수의 마이크로컨트롤러는 내부 풀업/풀다운 저항을 지원하며, SW로 설정할 수 있다. 그러나 경우에 따라 안정성을 위해 외부 저항이 필요할 수도 있다.
버튼은 기계적 장치라 눌리는 순간 접점이 튀면서 여러 번 빠르게 on/off 신호가 발생할 수 있다. 이 때문에 한 번 눌렀는데 여러 번 눌린 것처럼 인식되는 문제가 생긴다. 이를 해결하는 방법은 Debouncing이다.
※ LED 제어 시 주의사항: 저항 필수
LED는 전류가 한 방향으로 흐르면서 빛을 내는 소자이다. 하지만 전류가 과도하게 흐르면 LED와 마이크로컨트롤러가 손상될 수 있다.
따라서 저항(일반적으로 220 Ω~1 kΩ)을 직렬로 연결해 전류를 제한해야 한다. 만약 저항이 작다면 LED는 더 밝아지고, 반대로 저항이 크다면 LED가 어둡게 켜진다.

본 블로그에서 다룰 보드는 Nucleo WB55LG이다. 이 보드는 IoT 목적에 맞게 설계되었으며 다양한 기능을 제공한다. 주요 특징은 다음과 같다.
① STM32WB 마이크로컨트롤러 탑재
② GPIO 핀 다수 제공
③ 내부 타이머 지원
④ 보드 내장 기능
① Arduino 호환 커넥터
② Morpho 커넥터
주의할 점은 Arduino 커넥터와 Morpho 커넥터가 같은 MCU pin을 공유할 수 있다는 것이다. 예를 들어, Arduino D10 핀이 Morpho의 15번 핀과 동일할 수 있다. 따라서 핀 충돌에 유의해야 한다.
pinout diagram은 각 핀이 어떤 기능을 가지는지 나타낸다.
따라서 단순히 LED를 연결할 때는 특별한 기능이 없는 GPIO 핀을 사용하는 것이 바람직하다.
필자가 참고한 강의에서는 원격 실습 환경을 사용하며, 여기에 이미 여러 외부 주변 장치가 연결되어 있다. 이를 나타낸 것이 Fritzing 다이어그램이다.

본 실습에서는 첫 번째 버튼(Button 1)만 사용할 것이다. 참고로, 이 버튼은 마이크로컨트롤러의 5번 핀(PC_5)에 연결되어 있다.
입력을 읽기 위해 사용하는 것이 DigitalIn이다. DigitalOut과 비슷하지만 약간 다르다.
예를 들어 DigitalIn button1(BUTTON1); 형태로 선언할 수 있다.
이 객체는 해당 GPIO를 입력 모드로 초기화하기 때문에 따로 핀 모드를 직접 지정할 필요는 없다. 하지만 버튼에는 풀업(pull-up) 또는 풀다운(pull-down) 저항을 설정하는 것이 매우 중요하다. 그렇지 않으면 버튼이 눌리지 않았을 때 핀이 floating 상태가 된다. 따라서 두 번째 인자로 핀 모드를 지정할 수 있는데, 여기서는 기본값을 풀업 모드로 설정하겠다.
그리고나서 LED 깜빡임을 버튼으로 제어해보겠다. 코드에서는 단순히 버튼 상태를 읽어서 조건문으로 확인하면 된다. 그런데 여기서는 풀업을 썼으니, 버튼을 누르면 LOW(0)가 입력된다. 따라서 조건문에서는 if(!button1)과 같은 방식으로 반전시켜야 한다.
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*/
#include "mbed.h"
// Blinking rate in milliseconds
#define BLINKING_RATE 500ms
#define EXTERNAL_LED1 PB_13
#define EXTERNAL_LED2 PB_14
#define BUTTON_1 PC_5
int main()
{
// Initialise the digital pin LED1 as an output
DigitalOut led1(EXTERNAL_LED1);
DigitalOut led2(EXTERNAL_LED2);
DigitalIn button1(BUTTON_1, PinMode::PullUp);
while (true) {
if (!button1) {
led1 = !led2;
led2 = !led2;
ThisThread::sleep_for(BLINKING_RATE);
}
}
}

<참고 자료>
https://learn.sparkfun.com/tutorials/pull-up-resistors/all
https://os.mbed.com/platforms/ST-Nucleo-WB55RG/
https://www.udemy.com/course/microcontrollers-iot-learn-with-real-online-hardware/?kw=Microcontrollers+%26+Embedded+Systems%3A+Use+Real+STM32+Online&src=sac