AVR - LED panel - #6 Program Tisk
Koutek AVR -
Napsal uživatel Michal, OK1WMR   
Neděle, 10 Duben 2011 07:33

Kompatibilní zapojení: LED panel s ATmega8

Ke stažení: LED_006.c == LED_006.pdf == LED_006.htm
.
.

Untitled
/*
V minulém programu jsme si ukázali, jak pomocí tla?ítka ovliv?ovat b?h programu. 
Tento program však m?l jeden velký nedostatek. Když jsme totiž pomocí konstanty
"RYCHLOST" zvýšili rychlost b?hu hada, zvýšila se zárove? i rychlost, kterou program
"?etl" zda je stisknuté tla?ítko. Pokud jsme tedy nastavili rychlost kup?íkladu na 
20 krok? za sekundu, tak program také 20x za jednu vte?inu zjiš?oval, jestli
n?kdo nedrží stisknuté tla?ítko. Pak se stalo, že b?hem jednoho stisku tla?ítka 
(který trvá asi 0,5 vte?iny) program 10x zjistil, že je tla?ítko stisknuté a 
prodloužil hada. P?i vyšších rychlostech bylo tedy tém?? nemožné p?esn? nastavit 
délku hada.
Pot?ebovali bychom tedy, aby se tyto dva d?je (b?h hada a testování tla?ítka)
odehrávaly nezávisle na sob?. Tento problém lze vy?ešit pomocí ?asova?e.
?asova? je za?ízení, které b?ží nezávisle na b?hu programu a jednou za ur?itý ?as
vygeneruje p?erušení. P?erušení je vlastn? takové upozorn?ní pro procesor, že je 
t?eba n?co ud?lat. Jakmile procesor obdrží požadavek o p?erušení, tak dokoná práv?
rozd?lanou instrukci, a "odsko?í si" ud?lat co je pot?eba. Poté co vykoná vše 
pot?ebné, se program op?t vrátí k rozd?lané práci a pokra?uje v normálním b?hu.
Pro nás to znamená, že náš program m?že být kdykoli v jakémkoli míst? p?erušen. 
Z tohoto d?vodu je pot?eba obsluhu p?erušení (to co má program vykonat, když jej 
?asova? p?eruší) psát co nejkratší, aby co nejmén? ovliv?ovala b?h hlavního programu.
*/

/*
Mikrokontrolér ATmega8 má zabudované dva osmibitové a jeden šestnáctibitový
?íta?/?asova?. ?íta?e/?asova?e se nazývají proto, že se dají použít nejen k p?esnému
?asování programu, ale také mohou sloužit jako ?íta? vn?jších impulz?. 
?asova? funguje tak, že je do n?j p?iveden hodinový signál, který si lze p?edstavit 
jako obdélníkové pulzy. ?asova? s každým pulzem zvýší hodnotu ve svém registru o 1.
Vlastn? funguje jako ?íta? hodinového signálu (po?ítá pulzy). Nejd?ležit?jší ale je,
že jakmile tento ?íta? dojde ke své maximální hranici (p?ete?e), vyvolá p?erušení, 
vynuluje se, a po?ítá zase od za?átku. Maximální hodnota, ke které m?že ?íta? dojít,
je dána velikostí jeho registru. Pro osmibitový ?íta? je to ?íslo 255 a pro 
16. bitový je to ?íslo 65535. 
Toto ?íslo se nachází v registru TCNT. Podle ?ísla použitého ?asova?e se pak m?ní 
koncovka jeho názvu - TCNT0 = ?asova? 0, TCNT1 = ?asova? 1 a TCNT2 je ?asova? 2.
Pokud tedy chceme nastavit ?as, za jaký nám registr ?asova?e p?ete?e a vyvolá 
p?erušení, sta?í pouze do registru TCNT zapsat n?jaké ?íslo. ?asova? pak nepo?ítá od 
nuly, ale od tohoto ?ísla, a p?ete?e tedy d?ív.
Jako zdroj hodinového signálu v?tšinou slouží vlastní hodinový signál procesoru.
Protože však hodinový signál procesoru kmitá miliónkrát za vte?inu (1 MHz), 
p?etekl by ?asova? tém?? 4 000x za jednu vte?inu. Protože však pot?ebujeme nastavit 
mnohem delší ?asy, musíme použít takzvanou p?edd?li?ku. 
P?edd?li?ka je za?azená mezi zdrojem hodinového signálu a samotným ?asova?em.
Jak již její název napovídá, p?edd?li?ka slouží k tomu, aby hodinový signál pro 
?asova? vyd?lila n?jakým ?íslem. Funguje to tak, že nap?íklad p?edd?li?ka osmi
propustí každý osmý impulz, p?edd?li?ka 64 propustí každý 64. impulz, atd.
K ?ízení ?asova?e a p?edd?li?ky se používá registr TCCR (op?t na konci opat?en
?íslem ?asova?e). Podívejme se nyní, jak se nastavuje nap?íklad ?asova? 0:
*/
/*
TCCR0 = 0   - ?íta? je vypnut
TCCR0 = 1   - ?íta? je zapnut, a pracuje p?ímo s hodinovým signálem (bez p?edd?li?ky)
TCCR0 = 2   - ?íta? je zapnut s p?edd?li?kou osmi (hodinový signál/8)
TCCR0 = 3   - ?íta? je zapnut s p?edd?li?kou 64
TCCR0 = 4   - ?íta? je zapnut s p?edd?li?kou 256
TCCR0 = 5   - ?íta? je zapnut s p?edd?li?kou 1024
*/
/*
Nyní tedy umíme zapnout ?asova? a nastavit mu p?edd?li?ku (TCCR). Dokážeme také
jemn? nastavit ?as, za který nám ?asova? p?ete?e. To d?láme pomocí registru ?asova?e
(TCNT), do kterého nahrajeme hodnotu, od které má za?ít po?ítat.
Jediné co tedy pot?ebujeme ješt? ud?lat, je povolit p?erušení od ?asova?e. Musíme
vlastn? procesoru ?íct, aby toto p?erušení akceptoval. Implicitn? je totiž 
mikrokontrolér nastaven tak, že všechna p?erušení (krom? resetu) ignoruje. Atmega8
má totiž 19 r?zných možných zdroj? p?erušení jako: reset, ?íta?e, vn?jší p?erušení,
A/D p?evodník, sériové kanály a další. Všechna tato za?ízení mohou vyvolat p?erušení.
K povolování nebo zakazování p?erušení od ?asova?? slouží registr TIMSK.
Nastavením n?kterých bit? v registru TIMSK na "1" lze povolit p?erušení od 
jednotlivých ?asova??:
*/
/*
bit TIMSK:		?asova?: 		vektor:
 	0		   ?asova? 0	ISR(TIMER0_OVF_vect)
	2		   ?asova? 1	ISR(TIMER1_OVF_vect)
	6		   ?asova? 2	ISR(TIMER2_OVF_vect)

Nakonec je ješt? pot?eba nastavit 7. bit registru SREG. Tento bit slouží ke globálnímu
povolení nebo zakázání všech p?erušení najednou.
*/
/*
Vektor je místo, kam program p?esko?í, když je aktivováno p?erušení. Zápis je 
následující:

ISR(TIMER0_OVF_vect)
	{
	p?íkazy obsluhy p?erušení;
	}

Po provedení p?íkaz? obsluhy p?erušení se program vrátí zp?t na místo, odkud byl
p?erušen, a pokra?uje v normální ?innosti.
*/
/*
Nyní bychom se tedy mohli pustit do psaní programu, ale jak již bylo minule patrné,
?ím delší program píšeme, tím je mén? p?ehledný.Proto je lépe si jej rozložit na 
jednotlivé díl?í problémy, a ty pak zapsat pomocí funkcí.
Nap?íklad program:
*/
/*
...
PORTB = 0xff;	//nastav všechny bity portu "B" na "1"
waitms(5);		//po?kej 5 milisekund

PORTD = 0b00000001;	//nastav nultý bit portu "D" na "1"
waitms(2);			//po?kej 2 milisekundy
PORTD = 0b00000010;	//nastav první bit portu "D" na "1"

PORTB = 0x00;	//nastav všechny bity portu "B" na "0"
waitms(5);		//po?kej 5 milisekund
...
*/
/*
Tento program by šel p?epsat jednodušeji a p?ehledn?ji takto:
*/
/*
...
zapni_portb();		//nastav všechny bity portu "B" na "1" a po?kej 5 milisekund
prepni_portd();		//p?epni první a druhý bit portu "D" s prodlevou 2 milisekundy
vypni_portb();		//nastav všechny bity portu "B" na "0" a po?kej 5 milisekund
...
*/
/*
Program je nyní jednodušší. ?ada p?íkaz? byla nahrazena jednoduchými funkcemi.
Aby však program mohl fungovat, musíme tyto funkce nadefinovat. Definice funkce
se provádí tak, že napíšeme hlavi?ku funkce (jméno funkce a typy hodnot, které
funkce p?ijímá, pop?ípad? vrací. Definice funkce vypadá takto:

typ_navratove_hodnoty nazev_funkce (definice prom?nných, které funkce p?ijímá)
{
t?lo funkce
}

Protože nyní pro náš p?íklad nepot?ebujeme p?edávat žádné parametry, napíšeme místo
návratové hodnoty a p?ijímaných hodnot slovo "void".
Definice našich nových funkcí je tedy následující:
*/
/*
void zapni_portb(void)	//hlavi?ka funkce "zapni_portb"
	{  					//za?átek t?la funkce
	PORTB = 0xff;	//nastav všechny bity portu "B" na "1"
	waitms(5);		//po?kej 5 milisekund
	}					//konec t?la funkce
*/
/*
Nyní máme nadefinovanou funkci "zapni_portb". Pokud tedy v hlavním programu 
napíšeme:

zapni_portb();

//spustí se tato funkce, a provede p?íkazy ve svém t?le:

PORTB = 0xff;	//nastav všechny bity portu "B" na "1"
waitms(5);		//po?kej 5 milisekund

//po provedení t?chto p?íkaz? se program vrátí zp?t a pokra?uje dalším p?íkazem,
//tedy:

prepni_portd() 

//Tuto funkci zatím ale nemáme definovanou. Její definice by vypadala takto: 
*/
/*
void prepni_portd(void) //hlavi?ka
	{
	PORTD = 0b00000001;	//nastav nultý bit portu "D" na "1"
	waitms(2);			//po?kej 2 milisekundy
	PORTD = 0b00000010;	//nastav první bit portu "D" na "1"
	}
*/
/*
Podobným zp?sobem by se nadefinovala i funkce "vypni_portb". Tento program by se 
pak choval stejn?, jako p?vodní program bez funkcí.
*/
/*
Nyní se podíváme na to, jak by se zapisovala funkce, která p?ebírá a p?edává
parametry:
M?jme prom?nné "cislo1", "cislo2" a "vysledek":

unsigned char cislo1, cislo2, vysledek;

Nyní si p?edstavme, že v programu budeme pot?ebovat vykonat tuto operaci:

vysledek = (cislo1 + cislo2) * cislo1;  //do prom?nné "vysledek" se uloží sou?et
										//prom?nných "cislo1" a "cislo2" vynásobený
										//prom?nnou "cislo1"

Tuto operaci m?žeme nahradit funkcí:

vysledek = funkce_vypocet();

Protože však pot?ebujeme, aby tato funkce po?ítala s n?jakými prom?nnými ("cislo1" 
a "cislo2") musíme jí tyto prom?nné p?edat jako parametry:

vysledek = funkce_vypocet(cislo1, cislo2);

Tento p?íkaz by se nyní vykonal následovn?:
Program zjistí, že má n?co p?i?adit do prom?nné "vysledek" jde tedy do prava, a 
narazí na funkci s parametry. Zapamatuje si tedy tyto 2 parametry ("cislo1", "cislo2")
a p?esko?í do funkce "funkce_vypocet()". Této funkci p?edá oba parametry a funkci 
vykoná. Na konci funkce obdrží jedno ?íslo (návratovou hodnotu). Tuto hodnotu si 
zapamatuje, a sko?í zpátky k našemu p?íkazu:

vysledek = funkce_vypocet(cislo1, cislo2);

Nyní již má ale funkci vypo?tenou, a má v pam?ti uloženou její návratovou hodnotu.
Nahradí tedy p?vodní zápis: "funkce_vypocet(cislo1, cislo2)" pouze návratovou 
hodnotou a vznikne:

vysledek = navratova_hodnota;

Tento p?íkaz pak vy?eší jako prosté p?i?azení - zapíše do prom?nné "vysledek" 
návratovou hodnotu funkce.
Takže p?íkaz:

vysledek = funkce_vypocet(cislo1, cislo2);

se vykoná stejn? jako p?íkaz:

vysledek = (cislo1 + cislo2) * cislo1;
*/
/*
Nyní si ale musíme naší funkci ješt? nadefinovat:
Napíšeme zase hlavi?ku funkce, a blok p?íkaz? do t?la funkce:

char funkce_vypocet(char vstup1, char vstup2);
	{
	char vystup; //nadefinujeme si výstupní prom?nnou (sem budeme ukládat výsledek)
	
	vystup = (vstup1 + vstup2) * vstup1;	//do prom?nné "vystup" vypo?teme operaci
	
	return vystup;		//a ?ekneme, že se má jako návratová hodnota použít hodnota 
						//prom?nné "vystup"
	}
*/
/*
Nyní si rozebereme hlavi?ku funkce:
Slovo "char" p?ed názvem funkce ?íká, jakého typu bude návratová hodnota (kolik 
místa zabere v pam?ti - char = 8 bit?) Pak následuje název funkce "funkce_vypocet"
(to je název, pomocí kterého funkci voláme v programu). Za názvem následují v 
závorkách parametry funkce. 
Zápis:

char funkce_vypocet(char vstup1, char vstup2);

?íká, že funkce o?ekává 2 parametry typu char a vrací ?íslo typu char.
T?lo funkce je vytvo?eno stejn?, jako tomu bylo v minulých p?ípadech. Jedinou novinkou
je p?íkaz "return", za který se napíše, co má funkce vrátit. Tento p?íkaz zárove? 
funkci ukon?uje.
*/
/*
Nyní už tedy víme, jak používat ?asova? a jak rozepsat program do jednotlivých funkcí.
Ješt? by se hodila jedna poznámka, a to že každá funkce musí být p?ed svým použitím
definovaná. V opa?ném p?ípad? hlásí p?eklada? chybu, že tuto funkci nezná. Prozatím 
to tedy vy?ešíme tak, že všechny funkce budeme definovat ješt? p?ed hlavní funkcí 
("main"). Funkce main (ve které budeme naše nadefinované funkce používat) bude tedy 
nadefinovaná až jako poslední (na konci zdrojového kódu).
*/
/*
M?žeme se tedy pustit do psaní programu. Náš program by m?l um?t blikat ledkami v 
r?zných režimech a rychlostech. Režimy blikání by mohly být:
- jednoduché blikání 		(svítí nesvítí)
- stroboskopické blikání 	(rozsvícení ledek na velmi krátkou dobu)
- maják						(ledky dvakrát rychle po sob? krátce bliknou)
- b?žící sv?tlo				(n?co podobného, jako m?l KIT - sv?tlo b?há zleva 
							 doprava a zprava doleva)
- had						(náš starý známý)

Program by se m?l ovládat pomocí 2 tla?ítek (PD2 a PD3), p?i?emž jedním tla?ítkem by 
se m?nil režim blikání, a druhým rychlost.
Program by m?l fungovat tak, jednotlivé režimy blikání budou uloženy jako samostatné 
funkce. Hlavhí smy?ka pak zjistí, jaký režim blikání je vybrán, a podle toho spustí 
požadovanou funkci. Funkce pak provede jeden krok (posunutí hada, bliknutí, atd.)
a skon?í. ?ekání mezi jednotlivými kroky bude zajiš?ovat hlavní smy?ka.
Mezitím se bude pomocí ?asova?e0 provád?t testování klávesnice, a p?ípadné nastavování 
prom?nných "rychlost" a "rezim".
*/
//Náš program by tedy mohl vypadat takto:

#define F_CPU 1000000UL  // 1 MHz (základní frekvence) kv?li delay.h

#include <avr/io.h>		//Knihovna vstup? a výstup? (PORT, DDR, PIN)
#include <util/delay.h>	//Knihovna ?ekacích funkcí
#include <avr/interrupt.h> //Knihovna p?erušení (kv?li vektoru ISR(TIMER0_OVF_vect))

#define RYCHLOST_MIN   	2	//Minimální po?et krok? (bliknutí) za sekundu
#define RYCHLOST_MAX   	100 //Maximální po?et krok? (bliknutí) za sekundu


#define POCET_REZIMU 	15	//po?et režim? (režim? je 5, zbylé režimy slouží k 
							//prodlužování hada)

#define BLIKANI 0b00010111	//ur?uje, které ledky se mají st?ídat p?i režimu 
							//jednoduchého blikání

#define STROBO_CAS 	10	//(ms) - Ur?uje, kolik milisekund budou svítit ledky p?i 
						//strobo efektu. Využívá se i v režimu "maják".

#define MAJAK 	50	//definuje, kolik milisekund je mezi dvojicí bliknutí ve funkci 
					//maják

//Vytvo?íme si tzv. globální prom?nné (jsou deklarované mimo všechny funkce, 
//díky ?emuž jsou ve všech funkcích "viditelné"
//B?žná prom?nná totiž platí jen mezi složenými závorkami {}, mezi kterými byla 
//vytvo?ena (to znamená pouze uvnit? funkce).

unsigned char rychlost; //globální prom?nná - rychlost blikání
unsigned char rezim;	//globální prom?nná - režim blikání
unsigned char zmena;	//globální prom?nná - Sem budeme ukládat informaci, že byl 
						//práv? zm?n?n režim blikání (n?které funkce se budou p?i 
						//svém prvním spušt?ní pot?ebovat inicializovat(nastavit 
						//základní hodnoty)
//Tyto prom?nné musejí být globální, protože se nastavují ve vektoru p?erušení,
//a ?tou se v hlavní funkci. Musejí tedy být p?ístupné z obou t?chto míst.

//nyní si tedy nadefinujeme jednotlivéfunkce, které pak budeme v hlavní funkci volat:

/*****************************/
/*      Vektor p?erušení     */
/*****************************/
ISR(TIMER0_OVF_vect)
	{
	static unsigned char tlacitko;	//statická prom?nná - uchovává si hodnotu mezi 
								//jednotlivými voláními funkce
								//Pro nás slouží jako informace, že minule bylo 
								//stisknuto tla?ítko (abychom p?edešli necht?nému
								//p?e?tení jednoho stisku 2x)

	TCNT0=157;	//?asova? za?ne po?ítat od 157 (255-157=98) p?edd?li?ka je 1024.
				//Hodinový kmito?et procesoru je 1MHz. Takže: 
				//1 000 000 / 1024 / 98 = 10 Hz (klávesnice se kontroluje p?ibližn?
				//10x za vte?inu)
	if (tlacitko)	//pokud bylo minule stisknuto tla?ítko...
		{
		tlacitko=0;	//...tak prom?nnou "tlacitko" vynulujeme...
		return;		//...a pro jistotu ukon?íme cyklus (uživatel by mohl tla?ítko 
		}			//stále držet)
	
	if (!(PIND&0b00000100)) 	//pokud je stisknuté tla?ítko 1 (režim)
		{
		rezim++;	//zm?níme režim
		zmena=1;	//práv? jsme provedli zm?nu režimu
		tlacitko=1;	//uložíme si informaci, že bylo stisknuto tla?ítko
		}
		
	if (!(PIND&0b00001000))	//pokud je stisknuté tla?ítko 2 (rychlost)
		{
		rychlost*=2;	//p?idáme rychlost (2x zrychlíme je to totéž jako: rychlost<<1;)
		tlacitko=1;	//uložíme si informaci, že bylo stisknuto tla?ítko
		}

	if (rezim>POCET_REZIMU) //pokud jsme již p?ekro?ili povolený po?et režim?...
		{
		rezim=1;			//...za?neme zase od za?átku (1. režim)
		}

	if (rychlost>RYCHLOST_MAX)	//pokud jsme již p?ekro?ili maximální rychlost...
		{
		rychlost=RYCHLOST_MIN; //...nastavíme rychlost zpátky na minimum
		}
	
	
	}//Konec vektoru p?erušení - program se m?že vrátit zp?t ke své práci.

/*****************************/
/*funkce jednoduchého blikání*/
/*****************************/
void blik (void)	
	{
	if (zmena)  //pokud je funkce spušt?na poprvé
		{
		PORTB= BLIKANI;	//nastav do portu "B" po?áte?ní hodnotu 
		zmena=0;	//vynuluj prom?nnou "zmena" (p?íšt? už to nebude poprvé)
		}
	else		//pokud to není poprvé... 
		{
		PORTB=~PORTB; //do poru "B" dáme jeho bitový komplement - vym?níme "0" za "1"
		}
	} // konec funkce "blik"


/*****************************/
/*    funkce  stroboskopu    */
/*****************************/
void strobo (void)
	{
	PORTB=0xff;	//rozsvítíme všechny ledky...
	_delay_ms(STROBO_CAS);	//...po?káme malou chvilku...
	PORTB=0;	//...a zhasneme všechny ledky
	}


/*****************************/
/*           Maják           */
/*****************************/ 
void majak (void)
	{
	for(char n=0;n<2;n++) //cyklus o 2 opakováních:
		{
		PORTB=0xff;				//rozsvítíme všechny ledky...
		_delay_ms(STROBO_CAS);	//...chvilku po?káme...
		PORTB=0;				//...zhasneme všechny ledky...
		_delay_ms(MAJAK);			//...a  po?káme delší chvilku (50 ms)
		}

	} //konec funkce "majak"


/*****************************/
/*       B?žící sv?tlo       */
/*****************************/ 
void semtam (void)
	{
	static unsigned char pozice;	//statická prom?nná - uchovává si hodnotu mezi 
								//jednotlivými voláními funkce
								//nám bude sloužit jako ukazatel, kde zrovna je ledka
								//1-8 = 1.-8. ledka. 9-15 = 6.-1. ledka (jede zpátky) 
	if (zmena) //pokud je funkce volána poprvé
		{
		PORTB=1;	//zhasneme všechny ledky a rozsvítíme pouze jednu (PB0)...
		pozice=1; 	//...a nastavíme pozici na za?átek (1.ledka)
		zmena=0;	//vynuluj prom?nnou zmena (p?íšt? už to nebude poprvé)
		return;     //ukon?íme funkci (1. ledka už svítí, p?íšt? ji budeme posouvat
		}
	if (pozice<8)	//pokud pozice ješt? není 8 (ješt? jsme nedošli k 8. ledce)
		{
		PORTB<<=1;	//posu? ledku o 1 doleva.
		}
	else	//pozice je v?tší nebo rovna 8, (už jsme dojeli k levému kraji) 
		{
		PORTB>>=1;	//posu? ledku o 1 doprava (jedeme zase na za?átek)
		}
	
	pozice++; //posunuli jsme ledku, tak musíme také posunout ukazatel
	if(pozice>=15)	//pokud je ledka na 15. pozici (zpátky na za?átku)
		{
		pozice=1;	//p?epíšeme ukazatel na "1" (za?átek)
		}
	} //konec funkce "semtam"


/*****************************/
/*            Had            */
/*****************************/ 
void had (unsigned char delka)	//náš starý známý had
	{				//Funkce "had" p?ebírá parametr délka. P?i volání funkce tedy 
					//m?žeme (nebo spíš musíme) zadat délku hada.
	
	static unsigned char pozice;	//statická prom?nná - ukazatel na pozici hada
									//(stejn? jako u b?žícího sv?tla)	

	if (zmena) //pokud je funkce volána poprvé (stejn? jako u b?žícího sv?tla)
		{
		PORTB=0;	//zhasneme všechny ledky ...
		pozice=0; 	//...a nastavíme pozici na za?átek (1.ledka)
		zmena=0;	//vynuluj prom?nnou "zmena" (p?íšt? už to nebude poprvé)
		}
//Dosavadní ?ást je vlastn? stejná, jako byla použita ve funkci "B?žící sv?tlo"
//Následující ?ást funkce "had" je vícemén? stejná, jako v našem minulém programu.	
	
	if (pozice<delka)	//pokud jsme rozsvítili mén? ledek než je délka hada
		{
		PORTB <<=1;	//p?idáme ?lánek hada (bity se posunou doleva a 
					//vpravo se doplní "0"
		
		PORTB ++;	//p?i?teme "1" (nastavíme nultý bit na "1")
		}			
	else			//pokud není po?et opakování menší než délka hada
		{			//to znamená, že hada už jsme nakreslili..
		
		PORTB <<=1;	//pouze posuneme bity (hada) doleva a doplní se nula...
		}
	
	pozice++; //posunuli jsme ledku, tak musíme také posunout ukazatel
	
	if(pozice>(delka+8))	//pokud had dolezl na konec (poslední ?lánek už zmizel,
		{
		pozice=0;	//p?epíšeme ukazatel na "0" (za?átek)
		}
	
	} //konec funkce "had"

/************************************************/
		/*****************************/
		/**       Hlavní funkce     **/
		/*****************************/ 
int main (void)
{
DDRB = 0xff;			//Nastavíme port  "B" jako výstupní
TIMSK|=1; 	//nastavíme nultý bit na "1" a ostatní necháme (povolíme p?erušení 
			//od ?asova?e "0")
TCCR0 = 5;	//Zapneme ?asova? "0" s p?edd?li?kou 1024.

SREG  |= (1<<7); //povolení p?erušení (nastavíme 7. bit registru SREG)

rezim=1;	//nastavíme režim blikání na 1. možnost (jednoduché blikání)
zmena=1;	//nastavíme, jako že jsme práv? zm?nili režim (funkce blik bude spušt?na 
			//poprvé)

rychlost=RYCHLOST_MIN; //nastavíme rychlost na minimum

// nyní máme vše pot?ebné nastaveno, a m?žeme spustit hlavní smy?ku:

for(;;) //hlavní smy?ka
	{	//Tato smy?ka bude pouze zajiš?ovat výb?r správné funkce (podle nastaveného
		//režimu blikání, a ?ekání mezi jednotlivými kroky.
	
	//Výb?r správné funkce provedeme pomocí p?íkazu "switch".Switch je vlastn? 
	//n?co jako vícenásobný "if"
	
	switch (rezim) 	//budeme rozhodovat podle toho, co je v prom?nné "rezim"...
		{
		case 1: 	//...v p?ípad? že je to ?íslo "1"...
			blik(); //...zavoláme funkci "blik()" (1. režim)...
		break;		//...a vysko?íme z p?íkazu switch (jinak by se provedly všechny 
					//následující instrukce - switch by už další podmínky netestoval.
		
		case 2:			//...v p?ípad? že je to ?íslo "2"...
			strobo();	//...zavoláme funkci "strobo()" (2. režim)...
		break;
		
		
		case 3:		//...v p?ípad? že je to ?íslo "3"...
			majak();//...zavoláme funkci "majak()"
		break;
		
		
		case 4:		//...v p?ípad? že je to ?íslo "4"...
			semtam();//...zavoláme funkci "semtam()"
		break;
		
		
		default: 	//Pokud nevyhovoval ani jeden z p?edchozích p?ípad? - zbývá už 
					//jen funkce "had" (5. a vyšší režim)
			
			had(rezim-4); 	//zavoláme funkci "had" a jako parametr jí p?edáme ?íslo 
							//režimu bez 4. To znamená, že funkce m?že obdržet ?íslo
							//jedna až n?co, které pak použije k nastavení délky hada
		} //konec p?íkazu switch 
						
	//úsp?šn? jsme tedy vybrali jakou funkci má program provést a nyní nám už zbývá 
	//jen po?kat požadovanou dobu, než se program pustí do dalšího kroku:	

	_delay_ms (1000/rychlost);	//?ekání (1000 ms = 1 sekunda) 
	
	}	//konec hlavní smy?ky

} //konec funkce main



//Pro radioklub OK1KVK naspal Vašek Král