LED a tlačítko on/off

Ja by som do toho prerusenie vobec netahal. Cela uloha zbehne do par desiatok mikrosekund. Staci nastavit casovac na 1ms a potom len sledovat uplynutie nastavenych milisekund. Po 1000 prechodoch by som invertoval LEDku, a tak podobne. Z tejto cakacej slucky sa po nastavenom pocte prechodov postupne pospustaju vsetky funkcie. Ak uzivatel potrebuje, tak dalsi test tlacitka zavola az po 5000 prechodoch touto sluckou.
Na kazdu cinnost by som spravil zvlast funkciu a tej priradil periodu v ms pod ktorou sa ma spustat. Ziadna z tych funkcii nema preco trvat viac ako par us, takze do 1ms sa urcite stihnu spravit. Ak sa to niekomu nevidi, nech si nastavi zakladny cyklus na 10ms. Osobne pracujem so 100us a 1ms cyklom. Pod tymito “casovymi zakladnami” spustam niekolko (vela) programov na bars co, vratane 1-wire, Uartu, atd, atd. A procesor ma stale este dost casu skrabat sa v kremikovom zadocku ROHS nozickou. :slight_smile:

Funkcia vsak nesmie obsahovat while(1) {}, ci nieco podobne.
Funkcie musia bytnapisane tak, aby vedeli v kratkomcase rozoznat ci sa maju spustit a aku cinnost maju vykonat a co najskor svoju cinnost ukoncit.
Pred kratkym casom sa to tu cele rozoberalo aj so vzorovymi kusmi kodu myslim ze aj vratane toho na testovanie stavu tlacitka.

_delay_ms(50) a dokonca aj 5000 ako sme prave svedkami urcite fungovat bude, ale je to nabeh na velmi ale fakt velmi zly navyk.

Vy mu to teda komplikujete. :slight_smile: Začátečník to nemusí hned ze začátku řešit jak profík a nejoptimálněji. K tomu se dopracuje časem, až zjistí proč to takto složitě dělat.

Už jsem toho hodně přečetl a vím jaký má vliv _delay_ms na chod programu, ale bohužel ješte jsem nepochopil přerušení, časovač atd.
Každopádně u mého případu je to lepší, protože občas dělám menší akce a hodně ne zrovna střízlivých kamarádů furt všechno mačká, takže to zaroven slouží i jako ochrana proti nustálemu zapinani a vypinani zesilovače v intervalu 1 sekundy nebo méně.
Pokoušel jsem se to udělat tak, aby změna stavu reagovala jen na sestupnou/vzestupnou hranu. Tak jak to mám to dělá to, že když se tlačítko drží seplé tak se to zapíná a vypíná v intervalu ve funkci _delay_ms.

A jen tak mimochodem vůbec nerozumím těm slohům co jste tady psali, ale vážím si toho! :smiley:

EDIT: Tet jsem něco našel a jestli to chápu, tak pokud chci reagovat na změnu stavu, nebo sestupnou, vzestupnou hranu, tak musím použít přerušení, a tlačítka zapojit na INT0, INT1 je to tak ?

Tak to je pádný důvod pro umrtvení na 5sec! :mrgreen:

Alespoň trošku tím ten zesík ochráním :smiley:

Jinak k tématu, našel jsem návod na externí přerušení a dá se tim nastavit naběžná hrana, ale nechápu jak rozliším INT0 od INT1

MCUCR |= (1 << ISC01); // dobežná hrana INT0 MCUCR |= (1 << ISC11); // dobežná hrana INT1

Pokud sem to pochopil, tak pomocí ISCxx se nastavuje způsob přerušení (nabežna hrana, sestupna, změna stavu…)
ale jak poznám co je INT0 a INT1 ?

Jinak ohledně toho uspání nevim jestli to mam nějak vyřešit, protože i když bude zesilovač vyplý, tak MCU stále poběží (bude mít vlastní malý transformátor) a nemám představu, kolik to tak může žrát, co myslíte ? (jinak mám Attiny2313 myslím že jsem to zatím nezmínil)

INT0 a INT1 jsou 2 různé nožičky IO. Ale POZOR ! Pokud chceš použít INT0 nebo INT1, je potřeba mít ošetřené zákmity na úrovni HW, jinak se Ti může stávat, že se Ti přerušení vyvolá několikrát po sobě při jednom stisku - záleží na délce obsluhy, ale protože obsluhy přerušení by měla být vždy co nejkratší, tak i několikamilisekundové zákmity tlačítka vyvolají přerušení celkem dostkrát.

Ano to samozřejmě vím, ale jak rozeznám v programu, která je která ? Nebo když mám nadefinvanou jen jednu, tak to je INT0 a když 2 tak první je INT0 a druhá INT1 ?

Donře - tak příklad : Nadefinuješ si INT0 tak, aby vyvolávalo přerušení na náběžnou i sestupnou hranu. Předpoklad je (jak jsem napsal výše) HW ošetřené zákmity. Po vyvolání přerušení si zjistíš stav pinu. Je-li PIN v log. 1, pak byl INT vyvolán náběžnou hranou, je-li v log. 0, byl vyvolán sestupnou.

OK ?

My jsme se špatně pochopili, nebo sem to špatně napsal :smiley:

MCUCR |= (1 << ISC01); // dobežná hrana INT0 MCUCR |= (1 << ISC11); // dobežná hrana INT1

Tyto zápisy jsou úplně stejné, až na ISC, ale pokud jsem to dobře pochopil, tak ISC se nastavuje jen druh přerušení (sestupna,nabežna hrana, změna stavu…)
Takže nechápu jak nastavim, jestli chci přerušení na INT0 nebo INT1

Vyvolá se jiný vektor přerušení (jiná adresa v tabulce skoků).

Ošetření zákmitů by bylo možné softwarově kombinací s přerušením od časovače, který bude odečítat čas od posledního přerušení od tlačítka. Podobnou službu (jen méně přesně) může udělat i měření času hlavní smyčkou.

Ještě dovysvětlím :

ISC01:ISC00 určuje, za jakých podmínek se vyvolává INT0
ISC11:ISC10 určuje, za jakých podmínek se vyvolává INT1

INTx se vyvolá :
ISCx1:ISCx0 = 00 = hladinou log. 0
ISCx1:ISCx0 = 01 = jakákoliv změna na pinu INTx
ISCx1:ISCx0 = 10 = sestupnou hranou na pinu INTx
ISCx1:ISCx0 = 11 = náběžnou hranou na pinu INTx

Ty jsou v registru MCUCR.

K tomu je potřeba v registru GIMSK povolit bity INT0 a/nebo INT1 podle toho, které přerušení máš v plánu použít.

Samozřejmě musíš ještě procesoru povolit přerušení všeobecně (instrukcí sei).

Přerušení pak volá rutiny na příslušných adresách (viz datasheet - Interrupts → Interrupt vectors)

**Balů: **To je ono, to jsem chtěl vědět, díky za vysvětlení :wink:

Ještě k ošetření zákmitů - podívej se sem : https://forum.mcontrollers.com/t/osetreni-zakmitu-tlacitka-na-ext-preruseni/2818/1

Hodnoty součástek (je to tam taky na konci diskuze, ale abys to nemusel hledat) :
R 68-100 Ohmů
C 10n
Zapnutý Pull-Up v MCU.