사전 GPIO
개념

GPIO

gabury1고친 사람 github-actions[bot]

GPIO 는 프로그램이 칩의 핀 하나를 직접 켜고 끄거나 읽게 해 주는 기능입니다. 프로그램은 핀의 전압을 높여 기판 위의 작은 불을 켭니다. 버튼이 눌렸는지는 핀의 전압을 읽어서 압니다. 핀을 무엇에 쓸지는 칩을 만든 쪽이 아니라 기판을 설계하고 프로그램을 짜는 쪽이 정합니다.

쉽고 빠른 이해

GPIO 는 칩 밖으로 나온 핀 하나를 프로그램이 스위치처럼 다루게 해 줍니다. 예를 들어 프로그램이 핀 하나의 전압을 올리면 그 핀에 이어 둔 불이 켜집니다.

칩을 만드는 회사는 그 칩이 어떤 기판에 올라가 무엇과 이어질지 모릅니다. 그래서 쓰임을 정하지 않은 핀을 여럿 남겨 둡니다. 불을 달든 버튼을 달든 기판을 설계하고 프로그램을 짜는 쪽이 고릅니다.

어떻게 도는가:

  1. 프로그램이 핀마다 내보낼지 읽을지 정합니다
  2. 내보내기로 한 핀에는 높음이나 낮음을 적어 전압을 정합니다
  3. 읽기로 한 핀에서는 지금 전압이 높은지 낮은지를 읽습니다

대가도 있습니다. 핀은 높음과 낮음 두 값만 압니다. 센 전류를 흘리거나 일정한 간격으로 켜고 끄기를 오래 되풀이하는 일은 따로 만든 회로에 맡겨야 합니다.

상세

새 집을 지으면서 벽 안에 쓰임을 정하지 않은 전선 단자를 몇 개 남겨 둔다고 해 봅시다. 집주인은 나중에 거기에 조명을 달 수도 있고 초인종 버튼을 달 수도 있습니다. 무엇을 달지는 집을 지은 사람이 아니라 사는 사람이 정합니다.

이 절은 GPIO(General-Purpose Input/Output, 범용 입출력)가 왜 있는지에서 출발합니다. 그다음 핀 하나를 출력과 입력으로 쓸 때 전압이 어떻게 움직이는지, 프로그램이 그 핀을 어떻게 건드리는지 따라갑니다. 끝으로 GPIO 로 하기 어려운 일과 운영체제에서 보이는 모습을 봅니다.

칩은 밖으로 금속 다리를 여러 개 내놓습니다. 이 다리를 핀이라고 합니다. 칩은 핀으로 기판 위의 다른 부품과 전기로 이어집니다.

GPIO 는 쓰임이 정해지지 않은 핀을 프로그램이 다루게 해 주는 기능입니다. 프로그램은 핀마다 출력으로 쓸지 입력으로 쓸지 고릅니다. 출력은 프로그램이 핀의 전압을 정하는 것입니다. 입력은 프로그램이 핀의 전압을 읽는 것입니다.

기판 위의 LED(Light-Emitting Diode, 발광 다이오드) 하나를 켜고 끄는 일이 GPIO 를 쓰는 가장 작은 예입니다. 프로그램이 LED 가 이어진 핀의 전압을 높이면 불이 켜집니다. 전압을 낮추면 꺼집니다.

GPIO 는 주로 마이크로컨트롤러에 들어 있습니다. 마이크로컨트롤러는 프로세서와 메모리와 주변 회로를 칩 하나에 담은 작은 컴퓨터입니다. 리모컨이나 세탁기 안에서 도는 칩이 대개 이것입니다.

주변 회로는 프로세서 곁에 붙어 핀 다루기·통신·시간 재기 같은 일을 맡는 회로입니다. 프로세서가 이런 일을 하나하나 직접 하지 않게 덜어 줍니다. GPIO 도 이런 주변 회로 가운데 하나입니다.

쓰임을 정하지 않은 핀이 필요한 까닭

칩 하나는 수많은 기판에 올라갑니다. 같은 마이크로컨트롤러가 어떤 기판에서는 온도계를 읽고 다른 기판에서는 문 잠금장치를 움직입니다. 칩을 만드는 쪽은 그 핀 끝에 무엇이 이어질지 모릅니다.

그래서 칩은 전원처럼 쓰임을 정해 둔 핀과 함께 쓰임을 비워 둔 핀을 여럿 남깁니다. 비워 둔 핀에 무엇을 붙일지는 기판을 설계하고 프로그램을 짜는 쪽이 정합니다. 이 비워 둔 핀이 GPIO 핀입니다.

GPIO 가 없으면 버튼 하나, 불 하나마다 그 일만 하는 전용 회로를 칩 안에 넣어야 합니다. 칩이 미리 알 수 없는 부품은 아예 붙일 수 없게 됩니다.

높음과 낮음 두 값

GPIO 핀이 아는 값은 둘입니다. 전압이 높은 상태와 낮은 상태입니다. 프로그램은 높음을 1 로, 낮음을 0 으로 읽고 씁니다. 이렇게 두 값만 쓰는 신호를 디지털 신호라고 합니다.

높음은 칩의 전원 전압에 가까운 값입니다. 낮음은 0 볼트에 가까운 값입니다. 전원 전압이 얼마인지는 칩마다 다릅니다. 그 사이의 어중간한 전압은 칩이 높음으로 읽을지 낮음으로 읽을지 보장되지 않습니다.

핀이 견디는 전압에도 위쪽 끝이 있습니다. 전원 전압보다 높은 전압을 핀에 걸면 칩이 망가질 수 있습니다. 전원 전압이 다른 두 칩을 이을 때는 전압을 바꿔 주는 레벨 시프터를 사이에 둡니다.

아래 그림은 핀에 걸리는 전압을 위에서 아래로 구간별로 쌓은 것입니다. 볼트 수는 칩마다 달라서 적지 않았습니다.

block-beta
columns 1
  a["전원 전압보다 높음 — 칩이 망가질 수 있다"]
  b["전원 전압 근처 — 높음(1)"]
  c["어중간한 전압 — 보장되지 않는다"]
  d["0 볼트 근처 — 낮음(0)"]

그림에서 높음과 낮음 사이에는 어느 쪽으로 읽힐지 보장되지 않는 띠가 끼어 있습니다. 맨 위 구간은 값을 읽기 전에 칩이 망가질 수 있는 전압입니다.

출력 — 핀의 전압을 정하기

출력으로 정한 핀은 프로그램이 적은 값을 전압으로 내보냅니다. 1 을 적으면 핀이 높은 전압이 됩니다. 0 을 적으면 낮은 전압이 됩니다. 핀은 프로그램이 다른 값을 적을 때까지 그 전압을 유지합니다.

회로에서 0 볼트로 삼는 기준점을 접지라고 합니다. 핀과 접지 사이에 LED 와 저항을 이어 둡니다. 핀에 1 을 적으면 전류가 흘러 불이 켜집니다. 저항은 전류가 너무 많이 흐르지 않게 막습니다.

GPIO 핀이 내보낼 수 있는 전류는 작습니다. 모터처럼 전류를 많이 먹는 부품은 핀으로 직접 돌리지 못합니다.

그럴 때는 핀으로 트랜지스터를 켭니다. 트랜지스터는 작은 전류로 큰 전류를 여닫는 부품입니다. 모터에 흐르는 큰 전류는 전원에서 모터와 트랜지스터를 거쳐 접지로 따로 흐릅니다.

flowchart TD
    subgraph LED["LED 켜기"]
        P1["출력 핀"] --- R1["저항"]
        R1 --- D1["LED"]
        D1 --- G1["접지"]
    end
    subgraph MOT["모터 돌리기"]
        V2["전원"] --- M2["모터"]
        M2 --- T2["트랜지스터"]
        T2 --- G2["접지"]
        P2["출력 핀"] -->|켠다| T2
    end
    G1 ~~~ V2

그림 위쪽은 LED 회로이고 아래쪽은 모터 회로입니다. 모터 회로에서 출력 핀은 트랜지스터를 켜기만 합니다. 큰 전류는 핀을 거치지 않고 전원에서 접지로 흐릅니다.

입력 — 핀의 전압을 읽기

입력으로 정한 핀은 프로그램이 읽을 때마다 그 순간의 전압을 0 이나 1 로 돌려줍니다. 입력 핀은 전압을 내보내지 않고 듣기만 합니다.

버튼이 대표적인 예입니다. 버튼 한쪽은 핀에, 다른 쪽은 접지에 잇습니다. 버튼을 누르면 핀이 접지와 이어져 0 이 읽힙니다.

버튼을 떼면 핀은 어디에도 이어지지 않습니다. 이렇게 떠 있는 핀은 주변의 전기 잡음에 따라 0 과 1 을 오락가락합니다. 이 상태를 플로팅이라고 합니다.

플로팅을 막으려고 핀과 전원 사이에 저항을 하나 둡니다. 이 저항을 풀업 저항이라고 합니다. 버튼을 떼면 저항이 핀을 전원 쪽으로 끌어올려 1 이 읽힙니다. 버튼을 누르면 핀이 접지에 곧바로 이어져 0 이 읽힙니다.

거꾸로 핀과 접지 사이에 두는 저항은 풀다운 저항이라고 합니다. 이때 버튼은 핀과 전원 사이에 둡니다. 버튼을 떼면 0, 누르면 1 이 읽힙니다.

flowchart TD
    subgraph UP["풀업 — 떼면 1, 누르면 0"]
        V1["전원"] --- R1["풀업 저항"]
        R1 --- P1["입력 핀"]
        P1 --- B1["버튼"]
        B1 --- G1["접지"]
    end
    subgraph DOWN["풀다운 — 떼면 0, 누르면 1"]
        V2["전원"] --- B2["버튼"]
        B2 --- P2["입력 핀"]
        P2 --- R2["풀다운 저항"]
        R2 --- G2["접지"]
    end
    G1 ~~~ V2

그림 위쪽에서 버튼이 떨어져 있으면 입력 핀은 풀업 저항을 거쳐 전원에만 이어집니다. 버튼을 누르면 입력 핀과 접지가 곧바로 이어져 0 이 읽힙니다. 아래쪽 풀다운은 저항과 버튼의 위아래를 맞바꾼 꼴이라 읽히는 값도 뒤집힙니다.

많은 칩이 이 두 저항을 핀 안쪽에 넣어 둡니다. 프로그램은 그 저항을 켜고 끌 수 있습니다.

레지스터로 핀을 다루는 법

프로그램은 핀에 함수를 부르듯 말을 걸지 않습니다. 칩 안의 레지스터에 값을 적고 읽습니다. 레지스터는 주변 회로 안에 있는 작은 저장 칸입니다. 칸마다 주소가 붙어 있어 프로그램은 메모리를 읽고 쓰듯 다룹니다.

이렇게 주변 회로를 메모리 주소로 다루는 방식을 메모리 맵 입출력이라고 합니다. 프로그램 쪽에서는 정해진 주소에 값을 쓰는 것뿐입니다. 그 값이 핀의 전압으로 바뀌는 일은 칩의 회로가 맡습니다.

GPIO 레지스터는 핀 하나에 비트 하나를 줍니다. 32비트 레지스터 하나가 핀 32개를 맡는 식입니다. 레지스터의 5번 비트가 5번 핀입니다.

아래 그림은 레지스터를 8비트로 줄여 그린 것입니다. 칸 하나가 비트 하나이고, 칸에 적힌 번호가 그 비트가 맡는 핀입니다. 왼쪽 끝이 7번, 오른쪽 끝이 0번이라 뒤에 나올 코드의 0b 이진수 값과 같은 순서입니다.

block-beta
columns 8
  b7["7번"] b6["6번"] b5["5번"] b4["4번"] b3["3번"] b2["2번"] b1["1번"] b0["0번"]

핀을 다루는 데 쓰는 레지스터는 대개 셋입니다. 아래 표는 레지스터마다 비트 하나가 무엇을 정하는지 보입니다.

레지스터 비트 하나가 정하거나 알려 주는 것
방향 레지스터 이 핀이 입력인가 출력인가
출력 레지스터 출력 핀에 내보낼 값
입력 레지스터 입력 핀에서 지금 읽히는 값

레지스터 이름과 주소는 칩마다 다릅니다. 칩 제조사가 내는 설명서인 데이터시트에 적혀 있습니다.

칩 위에서 도는 프로그램을 펌웨어라고 합니다. 펌웨어는 레지스터 주소를 가리키는 포인터로 레지스터에 값을 쓰고 읽습니다. 아래 코드는 보기 쉽게 그 레지스터를 변수 out 으로 흉내 냈습니다.

코드는 출력 레지스터의 5번 비트만 1 로 올렸다 내립니다. 1 << 5 는 1 을 왼쪽으로 다섯 칸 밀어 5번 비트만 1 인 값을 만듭니다. 오른쪽 주석이 그 줄을 실행한 뒤의 값입니다.

C
uint8_t out = 0b00000000;
out |= (1 << 5);    // 0b00100000
out &= ~(1 << 5);   // 0b00000000

|= 는 5번 비트만 1 로 만들고 나머지 일곱 비트는 건드리지 않습니다. &= ~ 는 5번 비트만 0 으로 만듭니다. 덕분에 다른 핀 일곱 개는 하던 일을 계속합니다.

입력 레지스터를 읽을 때는 거꾸로 원하는 비트만 떼어 냅니다. 아래는 변수 in 으로 흉내 낸 입력 레지스터에서 3번 핀의 값을 읽는 줄입니다.

C
uint8_t in = 0b00001000;
int v = (in >> 3) & 1;   // 1

in >> 3 이 3번 비트를 맨 오른쪽으로 옮깁니다. & 1 은 그 비트 하나만 남깁니다.

입력의 변화를 알아채는 두 방법

버튼이 눌린 순간을 알려면 프로그램이 핀의 변화를 알아채야 합니다. 방법은 둘입니다. 백엔드에서 상태 조회 엔드포인트를 주기적으로 부르는 것과 웹훅을 받는 것의 차이와 닮았습니다.

첫째는 폴링입니다. 프로그램이 정해진 간격으로 입력 레지스터를 되풀이해 읽고 값이 바뀌었는지 봅니다. 단순한 대신 아무 일이 없어도 읽기를 계속합니다. 간격이 길면 짧은 눌림을 놓칩니다.

sequenceDiagram
    participant P as 프로그램
    participant R as 입력 레지스터
    loop 정해진 간격마다
        P->>R: 읽는다
        R-->>P: 1
    end
    P->>R: 읽는다
    R-->>P: 0 — 눌렸다

그림은 풀업 저항을 단 버튼을 폴링하는 모습입니다. 떼어 둔 동안에는 읽을 때마다 1 이 돌아옵니다. 누른 뒤 처음 읽을 때 0 이 돌아와서야 프로그램이 변화를 압니다.

둘째는 인터럽트입니다. 인터럽트는 프로세서가 하던 일을 멈추고 급한 일을 먼저 처리하게 하는 신호입니다. GPIO 핀은 값이 바뀌는 순간 인터럽트를 걸도록 설정할 수 있습니다. 그러면 프로세서는 평소 다른 일을 하다가 핀이 바뀔 때만 미리 등록한 처리 코드를 돌립니다.

sequenceDiagram
    participant I as 입력 핀
    participant C as 프로세서
    participant H as 처리 코드
    Note over C: 다른 일을 한다
    I->>C: 값이 바뀌어 인터럽트를 건다
    C->>H: 처리 코드를 돌린다
    H-->>C: 끝나면 돌아온다
    Note over C: 하던 일을 잇는다

인터럽트 쪽 그림에는 되풀이하는 읽기가 없습니다. 프로세서는 핀이 바뀌었다는 신호를 받았을 때만 처리 코드로 건너갑니다.

어느 변화에 인터럽트를 걸지도 고릅니다. 낮음에서 높음으로 오르는 순간을 상승 에지라고 합니다. 높음에서 낮음으로 내리는 순간은 하강 에지입니다. 풀업 저항을 단 버튼이라면 누르는 순간이 하강 에지입니다.

이렇게 값이 바뀌는 순간에 반응하는 방식을 에지 트리거라고 합니다. 값이 바뀔 때 한 번만 처리 코드가 돌므로, 버튼을 누르고 있는 동안에는 다시 불리지 않습니다.

기계식 버튼은 누르는 순간 접점이 몇 번 붙었다 떨어집니다. 그래서 한 번 눌렀는데 에지가 여러 번 생깁니다. 이 떨림이 채터링입니다.

채터링을 걸러 내는 일은 디바운싱입니다. 흔히 첫 에지 뒤 짧은 시간 동안 들어오는 변화를 무시합니다.

한 비트만 바꿀 때 생기는 경쟁

out |= (1 << 5) 는 한 줄이지만 프로세서는 세 단계로 처리합니다. 레지스터를 읽습니다. 읽은 값에서 5번 비트를 바꿉니다. 바꾼 값을 다시 씁니다.

읽은 직후에 인터럽트가 들어와 그 처리 코드가 같은 레지스터의 3번 비트를 바꿨다고 해 봅시다. 원래 코드는 처리 코드가 끝난 뒤 먼저 읽어 둔 낡은 값에 5번 비트만 바꿔 씁니다. 3번 비트에 한 변경은 사라집니다. 데이터베이스에서 두 트랜잭션이 같은 행을 읽고 고쳐 쓸 때 한쪽 수정이 사라지는 갱신 손실과 같은 꼴입니다.

sequenceDiagram
    participant A as 원래 코드
    participant R as 출력 레지스터
    participant H as 처리 코드
    A->>R: 읽는다
    R-->>A: 0b00000000
    Note over A,H: 인터럽트가 끼어든다
    H->>R: 3번 비트를 올려 쓴다 0b00001000
    A->>R: 낡은 값에 5번 비트만 바꿔 쓴다 0b00100000
    Note over R: 3번 비트 변경이 사라졌다

그림에서 원래 코드가 마지막에 쓴 값은 3번 비트가 0 인 낡은 값을 바탕으로 합니다. 처리 코드가 올려 둔 3번 비트가 그 값에 덮여 사라집니다.

그래서 많은 칩이 비트를 올리기만 하는 레지스터와 내리기만 하는 레지스터를 따로 둡니다. 올리기 레지스터의 5번 비트에 1 을 적으면 5번 핀만 높음이 됩니다. 0 을 적은 비트는 아무것도 바꾸지 않습니다.

sequenceDiagram
    participant A as 원래 코드
    participant S as 올리기 레지스터
    participant H as 처리 코드
    A->>S: 0b00100000 을 한 번 쓴다
    H->>S: 0b00001000 을 한 번 쓴다
    Note over S: 출력은 0b00101000 — 두 비트 모두 남는다

앞 그림과 달리 읽는 화살표가 없습니다. 두 쪽이 저마다 자기 비트에 1 만 적으므로 순서가 어떻게 섞여도 두 변경이 모두 남습니다.

읽을 필요 없이 쓰기 한 번으로 끝나므로 끼어들 틈이 없습니다. 중간에 끼어들 수 없는 이 성질이 원자성입니다.

한 핀을 여러 회로가 나눠 쓰는 핀 다중화

칩 안에는 GPIO 말고도 핀을 쓰려는 회로가 많습니다. 칩끼리 데이터를 주고받는 통신 회로가 대표적입니다.

통신하는 두 칩은 상대가 신호를 언제 읽을지 맞춰야 합니다. 일정한 간격으로 오르내리며 읽고 쓸 때를 알려 주는 신호를 클럭이라고 합니다. 클럭 선은 이 신호만 나르는 선입니다.

아래 표는 기판 위에서 흔히 쓰는 통신 방식 셋입니다. 셋 다 칩 바깥으로 선을 몇 가닥 내야 하므로 핀을 차지합니다.

방식 하는 일
I2C(Inter-Integrated Circuit) 선 두 가닥에 칩 여럿을 매달고 주소로 상대를 부른다
SPI(Serial Peripheral Interface) 클럭 선과 데이터 선으로 칩과 빠르게 주고받는다
UART(Universal Asynchronous Receiver-Transmitter) 클럭 선 없이 속도를 미리 맞춰 두 장치가 주고받는다

핀 수는 한정되어 있어 회로마다 핀을 따로 줄 수 없습니다. 그래서 핀 하나에 여러 회로를 이어 두고 그중 하나만 고르는 선택기를 둡니다. 이 구조를 핀 다중화라고 합니다.

flowchart TD
    G["GPIO 회로"] --> M["선택기"]
    I["I2C 회로"] --> M
    S["SPI 회로"] --> M
    U["UART 회로"] --> M
    M --> P["핀 하나"]

그림에서 네 회로는 한 핀을 두고 선택기 앞에 모여 있습니다. 선택기가 고른 회로 하나만 핀에 닿습니다. 프로그램은 선택 레지스터에 값을 적어 이 핀을 GPIO 로 쓸지 다른 기능으로 쓸지 정합니다. GPIO 가 아닌 쪽은 대체 기능이라고 부릅니다.

I2C 와 SPI 를 다룰 때도 GPIO 가 자주 나옵니다. SPI 에서 말을 걸 칩을 고르는 선은 흔히 GPIO 핀 하나로 냅니다. 프로그램은 대화 전에 그 핀을 낮음으로 내립니다. 대화가 끝나면 높음으로 올립니다.

sequenceDiagram
    participant P as 프로그램
    participant G as GPIO 핀
    participant T as 상대 칩
    P->>G: 낮음으로 내린다
    G->>T: 이 칩이 선택된다
    P->>T: SPI 로 주고받는다
    P->>G: 높음으로 올린다
    Note over T: 대화가 끝난다

그림에서 GPIO 핀은 데이터를 나르지 않습니다. 지금 말을 거는 상대가 누구인지 알려 주는 일만 합니다.

통신 회로가 없거나 모자라면 GPIO 핀을 빠르게 켜고 꺼서 통신 신호를 소프트웨어로 흉내 내기도 합니다. 이를 비트 뱅잉이라고 합니다. 회로 없이 어느 핀으로나 통신할 수 있는 대신 프로세서가 신호를 바꿀 때를 하나하나 직접 맞춰야 합니다.

GPIO 로 하기 어려운 일

GPIO 는 두 값을 프로그램이 정한 때에 읽고 쓰는 일에 맞습니다. 이 틀을 벗어나는 일은 따로 만든 회로가 맡습니다. 그 가운데 둘을 먼저 풉니다.

ADC(Analog-to-Digital Converter, 아날로그-디지털 변환기)는 전압 같은 연속된 값을 숫자로 바꾸는 회로입니다. 온도 센서처럼 중간 전압을 내는 부품은 이 회로로 읽습니다.

PWM(Pulse Width Modulation, 펄스 폭 변조)은 켜짐과 꺼짐을 빠르게 되풀이하는 방식입니다. 켜진 시간의 비율로 LED 밝기나 모터 속도를 조절합니다. PWM 회로는 한 번 설정해 두면 프로세서가 손대지 않아도 고른 간격으로 켜고 끕니다.

아래 표는 GPIO 로 어려운 일 셋과 각각을 맡는 회로를 모은 것입니다. 셋째 줄의 통신 회로는 앞 소절에서 본 것입니다.

하고 싶은 일 GPIO 로 어려운 까닭 맡는 회로
온도 센서가 내는 중간 전압 읽기 높음과 낮음 두 값만 안다 ADC
고른 간격으로 켜고 끄기를 오래 되풀이 프로그램이 다른 일을 하거나 인터럽트가 끼면 간격이 흔들린다 PWM 회로 · 타이머
신호가 촘촘히 바뀌는 통신 소프트웨어로 신호를 바꾸면 프로세서가 거기에 묶인다 I2C · SPI · UART 회로

운영체제에서 보이는 모습

마이크로컨트롤러에서는 펌웨어가 레지스터를 곧바로 건드립니다. 운영체제가 도는 기판에서는 사정이 다릅니다. 커널은 운영체제에서 하드웨어를 직접 다루는 중심부입니다.

운영체제에서는 레지스터를 커널이 쥡니다. 사용자 프로그램은 커널을 거쳐 핀을 다룹니다.

리눅스 커널은 GPIO 회로 하나가 맡은 핀들을 /dev/gpiochip0 같은 장치 파일 하나로 내놓습니다. 장치 파일은 프로그램이 보통 파일처럼 열어 장치와 주고받는 통로입니다. 프로그램은 이 파일을 열고 핀 번호를 골라 값을 읽거나 씁니다. 이 일을 쉽게 해 주는 라이브러리로 libgpiod가 있습니다.

flowchart TD
    subgraph MCU["마이크로컨트롤러"]
        F["펌웨어"] --> R1["레지스터"]
    end
    subgraph OS["운영체제가 도는 기판"]
        U["사용자 프로그램"] --> L["libgpiod"]
        L --> D["/dev/gpiochip0"]
        D --> K["커널"]
        K --> R2["레지스터"]
    end
    R1 ~~~ U

그림 위쪽은 마이크로컨트롤러이고 아래쪽은 운영체제가 도는 기판입니다. 운영체제에서는 프로그램과 레지스터 사이에 라이브러리와 장치 파일과 커널이 끼어듭니다.

예전에는 /sys/class/gpio 아래의 파일에 숫자를 적어 핀을 다뤘습니다. 이 방식은 핀을 쓰던 프로그램이 끝나도 설정이 남습니다. 장치 파일 방식은 프로그램이 파일을 닫으면 잡았던 핀을 놓아 줍니다. 지금은 옛 방식을 쓰지 않기를 권합니다.

어느 핀에 무엇이 이어졌는지는 기판마다 다릅니다. 리눅스는 이 정보를 기판을 설명하는 디바이스 트리에서 읽습니다. 그래서 같은 LED 제어 코드가 설명 파일의 핀 번호만 바꿔 다른 기판에서도 동작합니다.

관련 항목

GPIO 핀이 다루는 전기 신호와 회로 요소

디지털 신호 · 전압 · 접지 · 풀업 저항 · 풀다운 저항 · 플로팅 · 오픈 드레인 · 푸시풀 · 하이 임피던스 · 레벨 시프터

GPIO 를 다루는 레지스터와 소프트웨어

레지스터 · 메모리 맵 입출력 · 비트 · 비트 연산 · 펌웨어 · 데이터시트 · 디바이스 드라이버

GPIO 입력의 변화를 알아채는 방법

폴링 · 인터럽트 · 에지 트리거 · 레벨 트리거 · 채터링 · 디바운싱 · 웹훅

GPIO 레지스터를 고칠 때 생기는 동시성 문제

경쟁 상태 · 갱신 손실 · 원자성 · 트랜잭션

GPIO 핀을 나눠 쓰거나 흉내 내는 통신 방식

I2C · SPI · UART · 클럭 · CAN · 1-Wire · 칩 선택 · 비트 뱅잉 · 핀 다중화

GPIO 가 못 하는 일을 맡는 주변 회로

ADC · DAC · PWM · 타이머 · DMA

GPIO 핀에 이어지는 부품

LED · 버튼 · 트랜지스터 · 릴레이 · 센서 · 모터 드라이버

GPIO 를 운영체제에서 다루는 구성 요소

운영체제 · 커널 · 리눅스 커널 · 장치 파일 · libgpiod · 디바이스 트리

GPIO 가 속하는 상위 분류

핀 · 마이크로컨트롤러 · SoC · 임베디드 · 주변 장치 · 디지털 회로 · 버스

다른 이름: General-Purpose Input/Output · 범용 입출력 · GPIO 핀 · 범용 입출력 핀