V tomto článku se podíváme na základní operace svázané s systémem programovatelných vstupů a výstupů (General Purpose Input/Output — GPIO). Zaměříme se nejprve na výstup. Potom se budeme se zabývat otázkami, jak rychle můžeme měnit GPIO linky, jak vytvářet pulsy zadaného trvání a jak měnit několik linek synchronizovaně.

Piny na Picu

První věc, na co se podíváme, je uspořádání Pinů na standardním Picu, některé kompatibilní zařízení mají méně pinů anebo jsou jinak uspořádány. Procesor RP2040 má 30 GPIO linek, od GP0 do GP29, přičemž 26 jich je vyvedeno na kontakty destičky a můžeme je používat. Další čtyři jsou použité interně. GP23 je použité k řízení napájení. GP24 testuje, zda je přítomné napájení z USB, GP25 ovládá vestavěnou LED a GP29 slouží k měření systémového napájecího napětí. Další čtyři linky jsou připojeny pomocí SPI sběrnice k flash paměti.

Tabulka 1. Interní GPIO piny na Raspberry Pi Pico
GPIO29 Slouží v ADC režimu (jako ADC3) k měření napětí VSYS/3

GPIO25

Připojen na interní LED

GPIO24

VBUS sense, je na vysoké úrovni, poku je přítomno napětí na VBUS, jinak je na nízké úrovni

GPIO23

Řídí vestavěny SMPS Power Save pin (šetření energií)

Pico W používá tyto čtyři piny ke komunikaci s wifi obvodem Infineon CYW43439 pomocí SPI sběrnice.

Tabulka 2. Interní GPIO piny na Raspberry Pi Pico W
GPIO29 Slouží v režimu wifi (jako ADC3) k měření napětí VSYS/3

GPIO25

Wireless SPI CS — zapíná GPIO29 ke čtení VSYS

GPIO24

Použité pro wireless SPI data/IRQ

GPIO23

Použité pro wireless power on signál

Tabulka 3. Další GPIO piny použité pro Wifi obvod na Pico W
WL_GPIO2 VBUS sense, je na vysoké úrovni, poku je přítomno napětí na VBUS, jinak je na nízké úrovni

WL_GPIO1

Řídí vestavěny SMPS Power Save pin (šetření energií)

WL_GPIO0

Připojen na interní LED

Kromě řízení interní LED diody, žádný z těchto pinů nemá vliv na použití v typickém Pico programu.

Obě Pica majé další čtyři GPIO linky, schované v procesoru a použité k vytvoření SPI sběrnice pro komunikaci s interní flash pamětí. Každá GPIO linka s vyjimkou GP22 má více použití, na obrázku je to ukázáno.

Zapojení pinů Pico

Pico pinout

U každého pinu můžeme programově zvolit, k čemu budeme daný pin používat, budˇ jako GPIO nebo UART nebo \(I^2C\) nebo SPI nebo ADC. Teď se budeme věnovat všeobecnému použití GPIO. Jediný pin, který slouží jenom jako GPIO je právě GP22. Můžeme třeba použít GP26 pro naše účely, ale potom už ho nebude možné použít pro analogově digitální převodník (ADC). Jediný pin, který se dá používat jenom jako GPIO je GP22, a proto ho budeme převážně používat.

Základní GPIO funkce

V SDK máme mhoho funkcí, nejzákladnější jsou ty, co se zabývají pouze jednou linkou. Na každou linku se můžeme odkazovat celým číslem. Čtyři nejdůležitejší funkce pro GPIO:

Inicializace GPIO linky
void gpio_init(uint gpio)

Tato funkce inicializuje jednu linku podle čísla gpio, která bude programově ovládaná (GPIO_FUNC_SIO) a nastaví ji jako vstupní, což je bezpečnější z hardwarové stránky.

Nastavení funkce pinu
void gpio_set_function (uint gpio, enum gpio_function fn)

kde enum gpio_function fn je jedno z:

  • GPIO_FUNC_XIP  — speciální funkce pro QSPI piny

  • GPIO_FUNC_SPI — SPI sběrnice

  • GPIO_FUNC_UART — UART

  • GPIO_FUNC_I2C  — \(I^2C\) sběrnice

  • GPIO_FUNC_PWM  — pulsně šířková modulace PWM

  • GPIO_FUNC_SIO — programové řízení vstupu/výstupu

  • GPIO_FUNC_PIO0 — programové řízení vstupu/výstupu PIO0

  • GPIO_FUNC_PIO1 — programové řízení vstupu/výstupu PIO1

  • GPIO_FUNC_GPCK — GPIO hodiny

  • GPIO_FUNC_USB — USB

  • GPIO_FUNC_NULL

Funkce gpio_init() zanechá pin ve stavu vstupu. Chceme-li explicitně nastavit pin jako vstupní nebo výstupní, použijeme:

static void gpio_set_dir(uint gpio, bool out)

Pokud out je true je to výstupní pin, pokud je out false je to vstupní pin.

Je-li linka nastavena, můžeme si přečíst v jakém je stavu pomocí funkce:

static bool gpio_get(uint gpio)

a funkcí

gpio_put(uint gpio, bool value)

můžeme zapisovat do linky.

Existuje množství dalších GPIO funkcí, ale tyto nám stačí abychom mohli udělat jednoduchý vstup/výstup do jedné linky.

Naše projekty — CMakeLists.txt

Nejčastějším problémem začátečníka bývá, že neví jak upravit existující soubor CMakeLists.txt, který je řídícím souborem pro sestavení našeho programu. Různá jména, která se objevují v typickém CMakeLists.txt jsou si podobná, a dá se těžko určit, k čemu přesně jsou.

Nejjednodušší CMakeLists.txt, který se dá použít, vypadá takto:
cmake_minimum_required(VERSION 3.13)
include(pico_sdk_import.cmake)

project(jmeno_projektu C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
add_executable(jmeno_spustitelneho_souboru
    zdrojovy_kod.c
)
target_link_libraries(jmeno_spustitelneho_souboru pico_stdlib)
pico_add_extra_outputs(jmeno_spustitelneho_souboru)

Blikání

Uděláme jednoduchý program, který bude blikat LED diodou, připojenu k pinu GP22

Schema zapojení

blik1 schema

Rezistor R1 slouží k omezení tekoucího proudu LED diodou. Pokud je na výstupním pinu 22 3.3V a na LED diodě je úbytek napětí přibližně 1.7V, potom tekoucí proud podle Ohmova zákona bude:

\(I = \frac{U_{pin} - U_{led}}{R_1} = \frac{3.3V - 1.7V}{200 \Omega} = 0.008 A = 8 mA \)

Pro omezení proudu LED je možné použít libovolný rezistor v rozsahu od 100 Ω výše. Maximální přípustný proud LED diodou je obvykle 20 mA. Maximální bezpečný proud z GPIO pinu je 16 mA. Schéma je kresleno programem KiCAD — celé schéma v KiCADu
blik.c
#include "pico/stdlib.h"

int main()
{
    gpio_init(22);          (1)
    gpio_set_dir(22, true); (2)
    while( true ) {
        gpio_put(22,1);     (3)
        sleep_ms(1000);
        gpio_put(22,0);     (4)
        sleep_ms(1000);
    }
}
1 Inicializace linky 22 a nastavení jako vstupní
2 Nastavení linky 22 jako výstupní
3 Na lince 22 je nastavena jednička (pin je na úrovni 3.3 V a LED svítí)
4 Na lince 22 je nastavena nula (pin je na úrovni 0 V a LED nesvítí)

Ve výsledku program bude donekonečna blikat LEDkou v intervalu 2 sekund.

K sestavení programu potřebujeme jednoduchý soubor CMakeLists.txt, což je řídící soubor programu cmake, který nám vytvoří příslušné soubory Makefile pro program make, který provede sestavení programu. Dále potřeubujeme soubor pico_sdk_import.cmake, což je soubor, který vkládá cmake do projektu a obsahuje nastavení Pico SDK.

CMakeLists.txt
cmake_minimum_required(VERSION 3.12)

# Name project
SET(ProjectName blik)

# Import those libraries
include(pico_sdk_import.cmake)

# Define project
project(${ProjectName})

# Initialize the Raspberry Pi Pico SDK
pico_sdk_init()


add_executable(blik
        blik.c
        )

# pull in common dependencies
target_link_libraries(blik pico_stdlib)

# create map/bin/hex file etc.
pico_add_extra_outputs(blik)
Sestavení programu
$ cd blik           (1)
$ mkdir build       (2)
$ cd build          (3)
$ cmake ..          (4)
$ make -j $(nproc)  (5)
1 Přepneme se do adresáře s programem blik.c
2 Vytvoříme si pomocný adresář pro sestavení
3 Přepneme se do něj
4 Spustíme cmake ..
5 Pokud cmake proběhlo bez chyb, spustíme program make a sestavíme program. Parametr -j $(nproc) není nezbytně nutný, říká programu make, že má spustit paralelně více procesů (podle počtu jader procesoru) a zrychlit tak sestavení programu.

V adresáři build nám vznikne soubor blik.uf2, který nahrajeme do Pica a bude fungovat.

Veškeré soubory, které vzniknou v adresáři build, jsou pomocné a může je kdykoliv smazat.

Zdroje a odkazy