Vstupy a výstupy AVR: Rozdiel medzi revíziami
Zo stránky SensorWiki
Riadok 61: | Riadok 61: | ||
== Digitálne vstupy (Tlačidlá) == | == Digitálne vstupy (Tlačidlá) == | ||
Chceli by sme ďalej naprogramovať zapínanie a vypínanie jedným tlačítkom. Ak si to skúsite, zistíte, že to ako tak funguje, ale viacmenej len náhodne. Je to spôsobené javom, ktorý sa volá ''zákmity''. | Chceli by sme ďalej naprogramovať zapínanie a vypínanie jedným tlačítkom. Na predmete Základy počítačov sme tento problém riešili pomocou stavového diagramu. | ||
<div style='text-align: center;'> | |||
[[Súbor:MIPS_StavovyDiagram01.png|300px]] | |||
''Stavový diagram pre tlačítko.'' | |||
</div> | |||
K nemu zodpovedajúci program môže vyzerať napríklad takto | |||
<tabs><tab name="program03-1.c"> | |||
<source lang="c++"> | |||
#include <avr/io.h> | |||
#include <util/delay.h> | |||
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT)) | |||
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT)) | |||
#define LED1 PB5 // zabudovana dioda | |||
#define SW1 PB4 // tlacitko | |||
enum states { On, Off }; | |||
int main(void) | |||
{ | |||
enum states State = Off; | |||
set_bit(DDRB,LED1); // set pin LED1 as output | |||
set_bit(PORTB,SW1); // pull-up resistor ON | |||
while(1) | |||
{ | |||
if ( (State == Off) && bit_is_clear(PINB,SW1) ) | |||
{ | |||
State = On; | |||
set_bit(PORTB,LED1); // LED1 = log.1 | |||
} | |||
else if ( (State == On) && bit_is_clear(PINB,SW1) ) | |||
{ | |||
State = Off; | |||
clear_bit(PORTB,LED1); // LED1 = log.0 | |||
} | |||
} | |||
return(0); // sem nikdy neprideme | |||
} | |||
</source></tab></tabs> | |||
Ak si to skúsite, zistíte, že to ako tak funguje, ale viacmenej len náhodne. Je to spôsobené javom, ktorý sa volá ''zákmity''. | |||
Sem príde obrázok a ukážeme si to aj na osciloskope. | Sem príde obrázok a ukážeme si to aj na osciloskope. | ||
Verzia z 16:31, 8. február 2021
Digitálne výstupy (LED)
Teraz už vieme celkom dobre ovládať výstupy, takže by sme mohli skúsiť ten obligátny príkaz na blikanie LED diódou, potrebujeme už len nejaké oneskorenie. Vedeli by sme to robiť pomocou funkcie napísanej v assembleri, ako sme to robili na prvom cvičení. Trocha (ale len trocha) si to zjednodušíme a využijeme už zadefinovanú funkciu _delay_ms()
Využívanie funkcie _delay_ms()
#define F_CPU 16000000UL // toto je lepsie vlozit do parametrov pre kompilator
#include <avr/io.h>
#include <util/delay.h>
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define LED1 PB5 // zabudovana dioda
void delay(int delay) // vlastna funkcia pre dlhsie casy
{
for (int i=1; i<=delay; i++)
_delay_ms(1);
}
int main(void)
{
set_bit(DDRB,LED1); // set pin LED1 as output
while(1)
{
delay(250); // 250 ms delay
set_bit(PORTB,LED1); // LED1 = log.1
delay(250); // 250 ms delay
clear_bit(PORTB,LED1); // LED1 = log.0
}
return(0); // sem nikdy neprideme
}
void setup()
{
pinMode(LED_BUILTIN, OUTPUT); // initialize digital pin LED_BUILTIN as an output.
}
void loop()
{
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
Prečo je tento program napísaný práve takto, s pomocnou funkciou delay
a prečo nepoužijeme rovno _delay_ms()
sa dočítate v podrobnejšom texte Oneskorenia_s_AVR.
Digitálne vstupy (Tlačidlá)
Chceli by sme ďalej naprogramovať zapínanie a vypínanie jedným tlačítkom. Na predmete Základy počítačov sme tento problém riešili pomocou stavového diagramu.
K nemu zodpovedajúci program môže vyzerať napríklad takto
#include <avr/io.h>
#include <util/delay.h>
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define LED1 PB5 // zabudovana dioda
#define SW1 PB4 // tlacitko
enum states { On, Off };
int main(void)
{
enum states State = Off;
set_bit(DDRB,LED1); // set pin LED1 as output
set_bit(PORTB,SW1); // pull-up resistor ON
while(1)
{
if ( (State == Off) && bit_is_clear(PINB,SW1) )
{
State = On;
set_bit(PORTB,LED1); // LED1 = log.1
}
else if ( (State == On) && bit_is_clear(PINB,SW1) )
{
State = Off;
clear_bit(PORTB,LED1); // LED1 = log.0
}
}
return(0); // sem nikdy neprideme
}
Ak si to skúsite, zistíte, že to ako tak funguje, ale viacmenej len náhodne. Je to spôsobené javom, ktorý sa volá zákmity. Sem príde obrázok a ukážeme si to aj na osciloskope.
Aby nám všetko správne fungovalo, musíme tieto zákmity ošetriť (angl. termín debouncing).
Ošetrenie zákmitov (debouncing)
a) Hardvérové
Jeden spôsob, ako sa vysporiadať so zákmitmi je pridať okolo tlačítka niekoľko ďalších súčiastok, ktoré zákmity eliminujú.
ToDo obrazok
b) Softvérové
Jednoduchší a lacnejší spôsob je ošetriť zákmity softvérovo, ale za cenu zdržania programu. Princíp je jednoduchý, ak zistíme, že sa stav tlačítka zmenil, počkáme nejaký čas na ustálenie a potom overíme, či je tento stav stabilný, alebo to bol len náhodný impulz. Realizácia je možná napríklad takto:
Literatúra:
- Jack G. Ganssle: A Guide to Debouncing. The Ganssle Group, Rev 2: April, 2007.
- Elliot Williams: Embed With Elliot:Debounce Your Noisy Buttons, Part I. Hackaday, 2015.
- Elliot Williams: Embed With Elliot:Debounce Your Noisy Buttons, Part II. Hackaday, 2015.