Zkonstruujeme blikající maják na sanitku. Tlačítkem budeme ovládat zapnutí a vypnutí majáku, případně změnu způsobu blikání.
Schéma zapojení

Funkce použité v programu
void gpio_set_function( uint pin, GPIO_FUNC_SIO ) (1)
static void gpio_set_dir( uint pin, bool out) (2)
static void gpio_pull_up( uint pin ) (3)
void gpio_init_mask( uint32_t maska ) (4)
static void gpio_set_dir_out_masked( uint32_t maska ) (5)
static void gpio_set_mask( uint32_t maska ) (6)
static void gpio_clr_mask( uint32_t maska ) (7)
void sleep_ms( uint milisekundy) (8)
uint32_t gpio_get_events( uint gpio ) (9)
void gpio_clear_events( uint gpio, uint32_t events ) (10)
gpio_acknowledge_irq(uint gpio, uint32_t events) (11)
| 1 | Nastavuje pin pro použití jako GPIO. |
| 2 | Nastavuje směr pinu na vstupní: out je false, nebo na výstupní; out je true. |
| 3 | Připojuje k vstupnímu pinu vnitřní pull-up rezistor. |
| 4 | Počáteční inicializace pinů, které jsou jedničkové v masce. |
| 5 | Nastavení směru pinů na výstupní, které jsou jedničkové v masce. |
| 6 | Rozsvícení pinů, které jsou jedničkové v masce. |
| 7 | Zhasnutí pinů, které jsou jedničkové v masce. |
| 8 | Pauza programu v milisekundách. |
| 9 | Vrací množinu událostí, které nastaly na pinu gpio. Události mohou být GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE | GPIO_IRQ_LEVEL_LOW | GPIO_IRQ_LEVEL_HIGH. |
| 10 | Vymaže záznamy událostí na pinu gpio. Události mohou být GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE | GPIO_IRQ_LEVEL_LOW | GPIO_IRQ_LEVEL_HIGH. |
| 11 | Potvrzuje přerušení GPIO na pinu gpio pro zadané události events na volajícím jádru procesoru. |
Jak se tyto funkce používají si můžete přečíst v dokumentaci k Pico SDK.
Program
Program je udělán tak, že periodicky čte události na GPIO 22 (tam je připojeno tlačítko) a reaguje na ně — funkce chytni_udalost(). Nepoužívá přerušení.
Pin 22 je pomocí interního pull-up rezistoru na vysoké úrovni a stisknutím tlačítka se přizemní. Tím při každém stisknutí tlačítka Pico vygeneruje pro pin 22 událost GPIO_IRQ_EDGE_FALL (pin spadnul na nulu).
Pokud funkce chytni_událost() zaznamená událost GPIO_IRQ_EDGE_FALL, tak ji vynuluje a změní stav programu (globální proměná enum STAV tlacitko).
Stavy se mění cyklicky z vypnuto → zapnuto → efekt1 → efekt2 → efekt3 → vypnuto.
Stavům odpovídají funkce vypnuto_func(), zapnuto_func(), efekt1_func(), efekt2_func() a efekt3_func(), které dělají blikání.
Pro každý efekt bliká maják trochu jinak.
/* Maják na sanitku verze 2 s ovládacím tlačítkem
* (c) Jirka Chráska 2025; <jirka@lixis.cz>
* licence BSD 3 clause
*/
#include "pico/stdlib.h"
#include "hardware/structs/iobank0.h"
// GPIO0 až GPIO11 budou LED majáku
// GPIO22 bude pro ovládací tlačítko
uint32_t piny_majak = 1 | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7) | (1<<8) | (1<<9) | (1<<10) | (1<<11);
// to samé mohu udělat pomocí: uint32_t piny_majak = 0xfff;
// počáteční nastavení LED majáku
void majak_init()
{
gpio_init_mask( piny_majak ); // nastavení pinů 0 a 11
gpio_set_dir_out_masked( piny_majak ); // na výstupní
gpio_set_mask( piny_majak ); // testovací rozsvícení
sleep_ms(1000);
gpio_clr_mask( piny_majak ); // zhasnu maják
}
uint32_t gpio_get_events(uint gpio)
{
int32_t mask = 0xF << 4 * (gpio % 8);
return (iobank0_hw->intr[gpio / 8] & mask) >> 4 * ( gpio % 8);
}
void gpio_clear_events(uint gpio, uint32_t events)
{
gpio_acknowledge_irq(gpio, events);
}
// nastavení tlačítka na GPIO22
void tlacitko_init()
{
gpio_set_function(22, GPIO_FUNC_SIO);
gpio_set_dir(22,false);
gpio_pull_up(22);
gpio_clear_events(22, GPIO_IRQ_EDGE_FALL );
}
// definice stavu majáku
typedef enum st { vypnuto, zapnuto, efekt1, efekt2, efekt3 } STAV;
STAV tlacitko = vypnuto;
int sleep_time = 100; // čas v milisekundách, určující rychlost blikání
// odchytávání a zpracování událostí na GPIO22
void chytni_udalost()
{
int32_t event = gpio_get_events( 22 );
sleep_ms(10);
gpio_clear_events(22, GPIO_IRQ_EDGE_FALL);
if( event & GPIO_IRQ_EDGE_FALL ) {
switch( tlacitko ) {
case vypnuto: tlacitko = zapnuto; break;
case zapnuto: tlacitko = efekt1; break;
case efekt1: tlacitko = efekt2; break;
case efekt2: tlacitko = efekt3; break;
case efekt3: tlacitko = vypnuto; break;
default: tlacitko = zapnuto; break;
}
}
}
// rozsvícení všech LED majáku
void zapnuto_func()
{
gpio_set_mask( piny_majak );
sleep_ms(sleep_time*20);
}
// vypnutí všech LED majáku
void vypnuto_func()
{
gpio_clr_mask( piny_majak );
sleep_ms(sleep_time*20);
}
// maják jezdí zleva doprava a zprava doleva
void efekt1_func()
{
int i;
// masky pro jednotlivé stavy majáku pro efekt1
uint32_t masky[10] = {0x7, 0xe, 0x1c, 0x38, 0x70, 0xe0, 0x1c0, 0x380, 0x700, 0xe00};
gpio_clr_mask( piny_majak );
for( i=0; i<10; i++ ) {
gpio_set_mask( masky[i] );
sleep_ms(sleep_time);
gpio_clr_mask( masky[i] );
}
for( i=9; i>=0; i-- ) {
gpio_set_mask( masky[i] );
sleep_ms(sleep_time);
gpio_clr_mask( masky[i] );
}
}
// maják periodicky bliká všemi LED
void efekt2_func()
{
gpio_clr_mask( piny_majak );
sleep_ms( sleep_time );
gpio_set_mask( piny_majak );
sleep_ms( sleep_time );
}
// v blikání se střídají sudé a liché LED
void efekt3_func()
{
uint32_t masky[2] = {0b101010101010, 0b010101010101};
gpio_clr_mask( piny_majak );
gpio_set_mask( masky[0] );
sleep_ms(sleep_time*2 );
gpio_clr_mask( masky[0] );
gpio_set_mask( masky[1] );
sleep_ms( sleep_time*2 );
gpio_clr_mask( masky[1] );
sleep_ms( sleep_time*2 );
gpio_set_mask( masky[0] );
sleep_ms(sleep_time*2 );
gpio_clr_mask( masky[0] );
gpio_set_mask( masky[1] );
sleep_ms( sleep_time*2 );
gpio_clr_mask( masky[1] );
}
int main( void )
{
majak_init();
tlacitko_init();
tlacitko = vypnuto;
while(1) {
switch( tlacitko ) {
case vypnuto: vypnuto_func(); break;
case zapnuto: zapnuto_func(); break;
case efekt1: efekt1_func(); break;
case efekt2: efekt2_func(); break;
case efekt3: efekt3_func(); break;
default: vypnuto_func(); break;
}
chytni_udalost();
}
}
cmake_minimum_required(VERSION 3.13)
# toto je lepší, nemusíme pico_sdk_import.cmake kopírovat
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
#include(pico_sdk_import.cmake)
project(majak2 C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
add_executable(majak2
majak2.c
)
target_link_libraries(majak2 pico_stdlib)
pico_add_extra_outputs(majak2)
$ cd majak2
$ mkdir build
$ cd build
$ cmake ..
$ make -j8