11 - Úvod do Nucleo STM32F446RE

Desky Nucleo STM32F446RE jsou studenstvu dostupné na cvičení. Z vypracování úkolů na embedded programování je možné na cvičení získat až 6 bodů.

(Pro vyučující.)

Vývoj v prostředí Keil Studio

  • Vytvořte si účet ve webovém vývojovém prostředí https://studio.keil.arm.com/, pokud jej ještě nemáte.
  • Založte projekt pro NUCLEO-F446RE a pojmenujte jej prg-nucleo.
  • Do souboru main.cpp vložte jednoduchý program pro periodické blikání LED.

#include "mbed.h"
 
DigitalOut myled (LED1); // "Handle" to the LED.
 
int main() {
    while (1) {
        myled = !myled; // Flip the state of the LED.
        ThisThread::sleep_for(1s); // Efficient MCU sleep.
    }
}

  • Program zkompilujte tlačítkem Build project. (První kompilace může trvat dlouho.)
  • Po zkompilování se stáhne do počítače výsledný binární soubor.
  • Připojte Nucleo k počítači; Nucleo se nahlásí jako externí disk.
  • Nahrajte binární soubor na Nucleo zkopírováním souboru na “disk”.
Vývojové prostředí Keil používá pro mbed programování jazyk C++, jehož syntax vychází z C. Pro ukázkové příklady vystačíme se znalostí progrmaování a intuitivním vytvářením objektů (volání konstruktorů) a volání metod objektů. Objekt si můžeme představit jako složený typ struct, který kromě datových položek má také metody, například objekt mybutton může mít funkci fall() pro předání ukazatele na funkci volanou při detekci změny úrovně na tlačítku, např. mybutton.fall(&on_button_fall). V rámci PRG se C++ věnují přednášky 10 až 13.

LED svítí pokud je tlačítko stisknuté

  • Vyzkoušejte jednoduchý program pro ovládání LED stiskem tlačítka.

#include "mbed.h"
 
DigitalOut myled(LED1);
DigitalIn mybutton(BUTTON1); 
 
int main() {
   while (1) {
      if (mybutton == 0) {
         myled = 1;
      } else {
         myled = 0;
      }
   }
}

Slovy jazyka C, proměnná myled je datového typu DigitalOut. Terminologií C++ se jedná o instanci třídy DigitalOut. Instance třídy je spjata se sadou funkcí, které s ní umí pracovat - tzv. metodami. Metoda může být tzv. konstruktor, který instanci inicializuje. (Ve smyslu jako když inicializujeme proměnnou typu int.) Konstruktor může přijímat parametry, jako jakákoliv jiná funkce. V našem případě předáváme “název pinu”, který chceme ovládat. (Představte si, že výsledná instance je jakýsi ovladač/driver/API, který umí pracovat s LED diodou.) To, že můžeme “do proměnné přiřadit”, je pouze syntax sugar, který ve skutečnosti volá metodu write. Více vizte např. https://en.cppreference.com/w/cpp/language/class. Metoda write implementuje samotný mechanismus, který způsobí, že se na pinu objeví vysoká úroveň napětí. Vizte např. B3B38LPE1, B4M38AVS, B0B35APO.

Stisknutí tlačítka změní stav LED

  • Program rozšiřte tak, aby jeden stisk tlačítka střídavě LED rozsvítil nebo zhasnul.

Příklad řešení

Robustní detekce stisku tlačítka

  • Nedokonalý kontakt tlačítka způsobí probliknutí. (Zkuste tlačítko stisknout velice zlehka.)
  • Při změně stavu tlačítka může vzniknout šum.
  • Jak eliminovat toto nechtěné chování?

Možné řešení

Efektivní detekce stisku tlačítka

  • Využít procesorové přerušení pro efektivní obsluhu tlačítka.
  • MCU “začne sledovat” daný pin. Při náběžné hraně vyvolá tzv. přerušení (interrupt), který pozastaví běžící program a začne místo toho vykonávat obslužnou rutinu. Pokud zrovna MCU spí tak se probudí.
  • Nucleo má jednojádrové MCU. Opravdový paralelismus není možný.
  • Přerušení by mělo mít co nejrychlejší obsluhu.

Možné řešení

Efektivní a robustní detekce stisku tlačítka

  • Zkombinujme obě myšlenky dohromady.
  • MCU má v sobě zabudovaný časovač, který můžeme využít přes třídu Timeout.
  • Tento časovač vyvolá přerušení po uplynutí dané doby, MCU může mezitím v klidu spát.

Možné řešení

Opakovač

  • Vytvořte program, který zaznamená jak uživatel mačkal tlačítko.
  • Vytvořte si pole, které vyplníte vzorky stavu tlačítka.
  • Každý vzorek bude reprezentovat stejný časový úsek.
  • Po naplnění celého pole vzorky přehrajte na LED diodě.
  • Hrajte si s velikostí časového okna, počtem vzorků.
  • Uvědomte si, kolik paměti máme k dispozici a kolik zabírá pole vzorků.
  • Jak uložit informaci o stisknutí efektivně?

Možné řešení

Efektivní opakovač

  • Využije paměť efektivně: Nechť je jeden vzorek stavu tlačítka kódovaný jediným bitem.

Uložení informace

  • Vytvořte pole typu uint32_t.
  • Každý jeden index pole (každý uint32_t) může kódovat až 32 různých booleovských hodnot.
  • Podle požadovaného počtu vzorků vypočítejte délku pole. (Zaokrouhlit nahoru!)

Možné řešení

Bitwise operace

  • Vytvořte funkci, která podle zadaného čísla vzorku vybere správný index v paměti a v něm vyčte / nastaví správný bit.
  • Čtení (maskování) bitu x
    • varianta 1
      bit = (number >> x) & 1;
    • varianta 2
      bit = (number) & (x << 1);
    • jaký je rozdíl mezi variantou 1 a variantou 2? Kdy použijeme kterou z nich?
  • Nastavení bitu x na 1
    number |= 1 << x;
  • Nastavení bitu x na 0
    number &= ~(1 << x);
  • Přepínání bitu
    number ^= 1 << x;
  • Nastavení bitu x podle hodnoty proměnné v
    number = (number & ~(1U << x)) | (v << x);

Obojí dohromady

Možná kostra řešení

courses/b3b36prg/labs/lab11.txt · Last modified: 2023/02/17 10:00 by faiglj