V dnešním cvičení se naučíme nejprve používat stdio a funkci printf, která je prvním způsobem, jak vypisovat nějaké údaje na náš počítač.
Není to dokonalé, ale pomocí printf můžeme chytnout spoustu chyb.
Naučíme se měřit čas, jak dlouho bylo tlačítko stisknuto.
Komunikaci Pico s počítačem budeme odchytávat programem minicom. (Dá se to dělat i programem screen, na Windows se může používat putty.)
stdio fungujte tak, že Pico je propojené s počítačem sériovou linkou. Sériová linka může být funkční pomocí UART kabelu a nebo přes USB kabel.
My použijme druhou možnost, protože UART kabel nemáme k dispozici, ale USB kabel máme všichni.
Na Linuxu se sériovou linkou komunikuje pomocí zařízení /dev/ttyS0 (klasická sériová linka s TTL převodníkem) nebo /dev/ttyUSB0 (UART převodník) nebo /dev/ttyACM0 (USB kabel).
Potřebujeme přímo číst a zapisovat z a do tohoto zařízení. Normální uživatel ovšem nemá k těmto zařízením přímý přístup, k nim má přístup pro čtení a zápis jenom uživatel root a dále všichni uživatelé skupiny dialout.
Musíme být tedy root nebo ve skupině dialout. Potom bude minicom fungovat normálně. Pico standardně komunikuje rychlostí 115200 baudů.
$ sudo minicom -b 115200 -c on -D /dev/ttyACM0
Lepší postup je zařadit uživatele do skupiny dialout:
# usermod -a -G dialout uzivatel
$ minicom -b 115200 -c on -D /dev/ttyACM0
Abychom mohli používat knihovnu stdio, je potřeba upravit CMakeLists.txt.
cmake_minimum_required(VERSION 3.12)
# nebudeme kopírovat pico_sdk_import.cmake do našeho adresáře projektu,
# ale použijeme to, co je v Pico SDK
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(cas_tlacitko)
pico_sdk_init()
add_executable(cas_tlacitko
cas_tlacitko.c
)
target_link_libraries(cas_tlacitko
pico_stdlib
)
# Nastavíme si možnost výpisu funkcí printf přes USB port
pico_enable_stdio_usb(cas_tlacitko 1)
# UART nebudeme používat
pico_enable_stdio_uart(cas_tlacitko 0)
pico_add_extra_outputs(cas_tlacitko)
Schéma zapojení

Kondenzátor C1 je v klidovém stavu nabit (3.3V) a zabraňuje kmitání tlačítka při stisku, protože mu malinkou chvilku trvá, než se vybije na 0V. Za tuto chvilku utichnou zákmity tlačítka. Rezistor R2 určuje rychlost vybíjení kondenzátoru C1. Čím větší R2, tím pomalejší vybíjení. Rychlost nabíjení kondenzátoru C2 určuje součet R1+R2.

Program pro měření času stisknutí tlačítka
Tlačítko je zapojeno v režimu pull-up, proto v klidovém stavu je na pinu 20 vysoká úroveň.
Jakmile zachytíme sestupnou hranu pulsu (tlačítko je sepnuto) zaznamenáme čas \(t_1\) pomocí funkce time_us_64() a čekáme na náběžnou hranu pulsu.
Po obdržení náběžné hrany pulsu opět zaznamenáme čas \(t_2\) pomocí funkce `time_us_64().
Rozdíl časů \(t_2 - t_1\) je výsledný čas v \(\mu s\), po který bylo talčítko stisknuto.
Použité funkce
Funkce time_us_64() vrací počet \(\mu s\) od startu Pica jako 64 bitové číslo.
uint64_t time_us_64()
Funkce gpio_get_events() vrací zaznamenané události na pinu pin.
uint32_t gpio_get_events( uint pin )
Funkce gpio_clear_events() vymaže zaznamenané události events na pinu pin.
void gpio_clear_events(uint gpio, uint32_t events)
Události mohou být:
-
GPIO_IRQ_EDGE_RISE— zaznamenaná náběžná hrana pulsu (přechod z 0 na 1). -
GPIO_IRQ_EDGE_FALL— zaznamenaná sestupná hrana pulsu (přechod z 1 na 0). -
GPIO_IRQ_LEVEL_LOW— událost, kdy pin je nebo byl na úrovni 0. -
GPIO_IRQ_LEVEL_HIHG— událost, kdy pin je nebo byl na úrovni 1.
Celý program
Program pro měření času tlačítka pomocí událostí.
/* Měření času stisknutí tlačítka.
cas_tlacitko.c
(c) Jirka Chráska 2025, <jirka@lixis.cz>
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
uint32_t gpio_get_events(uint gpio)
{
int32_t mask = 0xF << 4 * (gpio % 8);
return (io_bank0_hw->intr[gpio / 8] & mask) >> 4 * ( gpio % 8);
}
void gpio_clear_events(uint gpio, uint32_t events)
{
gpio_acknowledge_irq(gpio, events);
}
int main()
{
uint64_t t; // sem budeme zaznamenávat čas
stdio_init_all();
sleep_ms(2000);
gpio_set_function( 20, GPIO_FUNC_SIO );
gpio_set_dir( 20, false );
gpio_pull_up( 20 );
while( true ) {
// vymažeme události: náběžnou i sestupnou hranu
gpio_clear_events( 20, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL );
// čekáme na sestupnou hranu
while( !(gpio_get_events(20) & GPIO_IRQ_EDGE_FALL)) {
t = (uint64_t) time_us_64();
}
gpio_clear_events( 20, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE );
// čekáme na náběžnou hranu
while( !(gpio_get_events( 20 ) & GPIO_IRQ_EDGE_RISE )) { }
t = (uint64_t)( time_us_64() - t);
// vytiskneme rozdíl časů v milisekundách do stdio
printf("%llu ms\n", t/1000);
sleep_ms(50);
}
}
$ cd cas_tlacitko
$ mkdir build
$ cd build
$ cmake ..
$ make -j4
Tato ukázka měření času stisknutí tlačítka se nám bude hodit při stavbě generátoru obdélníkových pulsů proměnné frekvence a střídy (verze 2.0)