V předchozím díle jsme si vyzkoušeli chování GPIO jako výstupu typu push-pull. Dalším logickým krokem bude vyzkoušet si chování GPIO nastaveného jako vstup. Přesněji řečeno jako logický vstup. Pomocí něj může mikrokontrolér sledovat logické úrovně které mu přivádí na piny buď lidská obsluha (například pomocí tlačítek a přepínačů) a nebo jiné elektrické obvody jako třeba různé snímače.
Na našem kitu máme modré tlačítko označené B1, které je připojené na pin PE4 podle schematu níže. VDD je napájecí napětí našeho MCU, tedy 5V. Rezistor R6 je zapojen jako takzvaný "pull-up" a slouží k tomu aby na pin přiváděl 5V v situaci kdy je tlačítko (B1) rozpojené. Kondenzátor C5 a odpor R5 slouží k potlačování zákmitů a povíme si o nich něco jindy. Jak už jsem napsal, když je tlačítko uvolněné, naměříme na PE4 napětí 5V (zkuste si). Stisknutím tlačítka zkratujeme PE4 se zemí a přivedeme na něj tak 0V (zkuste si). Dokud je tlačítko stisknuté, teče skrze pullup rezistor (R6) proud (přibližně 5V/4k7 = 1mA). Pokud máme pin PE4 nastavený jako obyčejný vstup, chová se jako takzvaná "vysoká impedance" (HiZ). Jinak řečeno jako by tam vůbec nebyl. To ale platí jen pokud dodržíme některé podmínky. První z nich je ta že na něj nesmíme přivést napětí větší jak 5.3V a ani nesmí být menší jak -0.3V (při 5V napájení). Jinak řečeno nepřivádějte tam větší napětí jak napájecí napětí čipu (zde 5V) a rozhodně ne záporné.
Konfiguraci jako vstup provádíme naší známou funkcí GPIO_Init argumentem GPIO_MODE_IN_FL_NO_IT. Přečíst si log. úroveň na pinu pak můžeme funkcí GPIO_ReadInputPin. Argumenty této funkce jsou port a pin, stejně jako u všech předchozích funkcí které jsme používali. Funkce vrací hodnotu RESET pokud je na vstupu úroveň "Low" (log.0) nebo cokoli jiného (!) pokud je na vstupu úroveň "High" (log.1). Pojďme si to procvičit.
void main(void){ GPIO_Init(GPIOC,GPIO_PIN_5,GPIO_MODE_OUT_PP_LOW_SLOW); // nastavíme PC5 jako výstup typu push-pull (LEDka) GPIO_Init(GPIOE, GPIO_PIN_4,GPIO_MODE_IN_FL_NO_IT); // nastavíme PE4 jako vstup (tlačítko) while (1){ // stále dokola if(GPIO_ReadInputPin(GPIOE,GPIO_PIN_4)==RESET){ // kontrolujeme zda je tlačítko stisknuté... (je na PE4 log.0) GPIO_WriteHigh(GPIOC,GPIO_PIN_5); // pokud ano tak rozsvěcíme LED (zapisujeme log.1) }else{ GPIO_WriteLow(GPIOC,GPIO_PIN_5); // pokud ne tak zhasneme LED (zapisujeme log.0) } } }
#include "stm8s.h" uint8_t minuly_stav=1; // zde si budeme ukládat minulý stav tlačítka (1=tlačítko stisknuté, 0=tlačítko uvolněné) uint8_t aktualni_stav=1; // zde si budeme ukládat aktuální stav tlačítka (1=tlačítko stisknuté, 0=tlačítko uvolněné) // u funkce GPIO_ReadInputPin, hodnota RESET znamená log.0 a tedy stisknuté tlačítko void main(void){ GPIO_Init(GPIOC,GPIO_PIN_5,GPIO_MODE_OUT_PP_LOW_SLOW); // nastavíme PC5 jako výstup typu push-pull (LEDka) GPIO_Init(GPIOE, GPIO_PIN_4,GPIO_MODE_IN_FL_NO_IT); // nastavíme PE4 jako vstup (tlačítko) while (1){ // stále dokola // načteme aktuální stav tlačítka if(GPIO_ReadInputPin(GPIOE,GPIO_PIN_4)==RESET){ // zjisti jestli je tlačítko stisknuté aktualni_stav=1; // pokud ano ulož že je stisknuté } else{ aktualni_stav=0;// jinak ulož že je uvolněné } // teď budeme kontrolovat jestli nenastal "okamžik stisku" nebo "okamžik uvolnění" if(minuly_stav==1 && aktualni_stav==0){ // je to okamžik stisku ? GPIO_WriteHigh(GPIOC,GPIO_PIN_5); // pokud ano rozsvítíme LEDku } if(minuly_stav==0 && aktualni_stav==1){ // je to okamžik uvolnění ? GPIO_WriteLow(GPIOC,GPIO_PIN_5); // pokud ano zhasneme LEDku } minuly_stav = aktualni_stav; // aktuální stav tlačítka už se stal "minulostí" // teď je z něj minulý stav tlačítka a my si jdeme přečíst nový aktuální stav } }
#include "stm8s.h" uint8_t minuly_stav=0; // zde si budeme ukládat minulý stav tlačítka (1=tlačítko stisknuté, 0=tlačítko uvolněné) uint8_t aktualni_stav=0; // zde si budeme ukládat aktuální stav tlačítka (1=tlačítko stisknuté, 0=tlačítko uvolněné) uint8_t stav_ledky=0; // tady si pamatujeme jestli LEDka svítí nebo je zhasnutá (1=svítí, 0=nesvítí) void main(void){ GPIO_Init(GPIOC,GPIO_PIN_5,GPIO_MODE_OUT_PP_LOW_SLOW); // nastavíme PC5 jako výstup typu push-pull (LEDka) GPIO_Init(GPIOE, GPIO_PIN_4,GPIO_MODE_IN_FL_NO_IT); // nastavíme PE4 jako vstup (tlačítko) while (1){ // stále dokola // načteme aktuální stav tlačítka if(GPIO_ReadInputPin(GPIOE,GPIO_PIN_4)==RESET){ // zjisti jestli je tlačítko stisknuté aktualni_stav=1; // pokud ano ulož že je stisknuté } else{ aktualni_stav=0;// jinak ulož že je uvolněné } if(minuly_stav==0 && aktualni_stav==1){ // je to okamžik stisku ? // přepneme stav LEDky if(stav_ledky==1){ // pokud je LEDka rozsvícená GPIO_WriteLow(GPIOC,GPIO_PIN_5); // zhasneme ji... stav_ledky=0; // ...a zapamatujeme si že je zhasnutá }else{ // jinak je LEDka zhasnutá, takže... GPIO_WriteHigh(GPIOC,GPIO_PIN_5); // ...ji rozsvítíme ... stav_ledky=1; // ... a zapamatujeme si že je rozsvícená } } minuly_stav = aktualni_stav; // aktuální stav tlačítka se stal minulým } }
Jistě jste si všimli že přinejmenším program pro poslední cvičení by šel napsat v mnoha ohledech efektivněji. Že docela plýtváme pamětí když použijeme celý bajt na zapamatování stavu 1 nebo 0 (na to by přece stačil jediný bit). Podobně je na tom i proměnná stav_ledky,která také zbytečně zabírá jeden bajt paměti, protože tuto informaci už máme ve skutečnosti uloženou jinde. Chápejte to jako daň za to že se jazyk i práci teprve učíme (a navíc máme paměti dost). Kdo by přece jen chtěl trochu "optimalizovanější" kód, je mu k dispozici.
Home
| V1.01 27.4.2020 /
| By Michal Dudka (m.dudka@seznam.cz) /