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.
| 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.
| 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 |
| 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.

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:
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.
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.
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

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 |
#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.
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)
$ 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.