diff --git a/articles/2011/avr-led-panel-7-program.md b/articles/2011/avr-led-panel-7-program.md new file mode 100644 index 0000000000000000000000000000000000000000..4aafbba0356fb497294b7bcceb59e9b0e70078d7 --- /dev/null +++ b/articles/2011/avr-led-panel-7-program.md @@ -0,0 +1,275 @@ ++++ + +title = "AVR - LED panel - #7 Program" +perex_e = " + +KompatibilnĂ zapojenĂ: LED panel s ATmega8 + +Ke staĹľenĂ: LED_007.c == LED_007.pdf == LED_007.htm +. +. +" +tags = ["ÄŚlánek"] ++++ + + + +KompatibilnĂ zapojenĂ: LED panel s ATmega8 + +Ke staĹľenĂ: LED_007.c == LED_007.pdf == LED_007.htm +. +. + +* * * + +<title>Untitled</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="generator" content="SynEdit HTML exporter"> <style type="text/css">&lt;!-- body { color: #000000; background-color: #FFFFFF; } .cpp1-assembler { } .cpp1-brackets { } .cpp1-comment { color: #008000; font-style: italic; } .cpp1-float { color: #000080; } .cpp1-hexadecimal { color: #000080; } .cpp1-character { } .cpp1-identifier { } .cpp1-illegalchar { } .cpp1-number { color: #000080; } .cpp1-octal { color: #0000FF; } .cpp1-preprocessor { } .cpp1-reservedword { font-weight: bold; } .cpp1-space { color: #008080; } .cpp1-string { color: #800000; } .cpp1-symbol { } --&gt;</style> + +``` +/* +NynĂ jiĹľ umĂme pouĹľĂvat pĹ™Ăkazy k vÄ›tvenĂ programu (podmĂnky) "if" a "switch". UmĂme +takĂ© rozloĹľit program na jednoduchĂ© funkce a pouĹľĂvat cyklus "for". Co se týče cyklĹŻ, +zbĂ˝vá nám ještÄ› vysvÄ›tlit cyklus "while" a "do-while" a pĹ™Ăkazy "break" a "continue". +*/ +/* +Cyklus "while" je velmi podobnĂ˝ cyklu "for". RozdĂl mezi cyklem "for" a "while" je +ten, Ĺľe cyklus "for" má pĹ™edem danĂ˝ poÄŤet opakovánĂ, cyklus "while" jej pĹ™edem danĂ˝ +mĂt nemusĂ. Funguje to tak, Ĺľe cyklus "while" má ve svĂ© hlaviÄŤce zadanou podmĂnku, +která se pĹ™i kaĹľdĂ©m prĹŻchodu cyklem testuje. Jakmile tedy program narazĂ na cyklus +"while", otestuje jestli platĂ podmĂnka (podobnÄ› jako u "if") a pokud platĂ, vykoná +pĹ™Ăkazy ve svĂ©m tÄ›le. PotĂ© se program pĹ™esune zpÄ›t na začátek, a znovu otestuje +podmĂnku. Pokud je podmĂnka vyhodnocena jako neplatná, pĹ™Ăkazy v tÄ›le cyklu se +nevykonajĂ. RozdĂl mezi "for" a "while" tedy spoÄŤĂvá v tom, Ĺľe pokud bude podmĂnka +vyhodnocena jako neplatná hned napoprvĂ©, pĹ™Ăkazy v tÄ›le cyklu se neprovedou vĹŻbec. +Zápis je následujĂcĂ: + +while (podmĂnka) + { + pĹ™Ăkazy; + } +*/ +/* +Cyklus "do-while" se od cyklu "while" lišà tĂm, Ĺľe pĹ™Ăkazy v tÄ›le cyklu "do-while" +se minimálnÄ› jednou provedou. +Zápis je následujĂcĂ: + +do { + pĹ™Ăkazy; + } while (podmĂnka); + +PodmĂnka je u tohoto cyklu zapsána aĹľ na konci, a program tedy pĹ™ed jejĂm otestovánĂm +musĂ vykonat pĹ™Ăkazy v tÄ›le cyklu. Na konci cyklu narazĂ na podmĂnku, kterou otestuje. +Pokud je podmĂnka platná, cyklus se opakuje (od začátku), pokud ne, je cyklus ukonÄŤen, +a program pokraÄŤuje za cyklem. +*/ +/* +S pĹ™Ăkazem "break" jsme se setkali jiĹľ u podmĂnÄ›nĂ©ho pĹ™Ăkazu "switch". PodobnÄ› jako u +pĹ™Ăkazu "switch", se i u cyklĹŻ dá pouĹľĂt pĹ™Ăkaz "break" k jejich okamĹľitĂ©mu ukonÄŤenĂ. +PĹ™Ăkaz break se vÄ›tšinou zadává jako jedna vÄ›tev podmĂnky ("if" nebo "switch"). +Zápis: + +while (1) + { + pĹ™Ăkazy; + if (podmĂnka) + break; + } + +V tomto pĹ™ĂpadÄ› pĹ™Ăkaz break sloužà k "vyskoÄŤenĂ" z nekoneÄŤnĂ© smyÄŤky. PĹ™Ăkazy v tÄ›le +smyÄŤky se tedy budou vykonávat do tĂ© doby, dokud nebude platná podmĂnka +"if". +Ve výše uvedenĂ©m pĹ™Ăkladu si lze takĂ© povšimnout, Ĺľe pĹ™Ăkaz "break" nenĂ zapsán +ve sloĹľenĂ˝ch závorkách, jak by se v tÄ›le pĹ™Ăkazu "if" dalo oÄŤekávat. +Pokud totiĹľ do tÄ›la nÄ›jakĂ© podmĂnky nebo cyklu zapisuje pouze jeden pĹ™Ăkaz, +nenĂ nutnĂ© jej psát do sloĹľenĂ˝ch závorek {}. Pokud bychom do tÄ›la nÄ›jakĂ© podmĂnky +nebo smyÄŤky zapsali vĂce pĹ™ĂkazĹŻ bez sloĹľenĂ˝ch závorek, bral by se jako tÄ›lo pouze +prvnĂ pĹ™Ăkaz. OstatnĂ by se vykonaly aĹľ za tĂmto cyklem nebo podmĂnkou. +NapĹ™Ăklad: + +if (n<5) + n++; + b=n; + +je totĂ©Ĺľ co: + +if (n<5) + { + n++; + } +b=n; + +*/ +/* +PĹ™Ăkaz "continue" zpĹŻsobĂ skok na začátek smyÄŤky. NeukonÄŤĂ tedy smyÄŤku jako "break", +ale pouze vynechá všechny pĹ™Ăkazy, kterĂ© po nÄ›m následujĂ aĹľ do konce tÄ›la smyÄŤky. +Cyklus pak pokraÄŤuje zase od začátku, jako by se nic nedÄ›lo. +Zápis: + +while (1) + { + pĹ™Ăkazy; + if (podmĂnka) + continue; + pĹ™Ăkazy; //tyto pĹ™Ăkazy budou vynechány, pokud bude platit podmĂnka + } + +*/ +/* +DoteÄŹ jsme se zabĂ˝vali, jak na našem pĹ™Ăpravku "ATmega8_LED_start_2" rozsvÄ›covat +a zhasĂnat ledky. Co kdyĹľ ale budeme chtĂt Ĺ™Ădit jejich jas? +Jas ledky je moĹľnĂ© Ĺ™Ădit tak, Ĺľe ji rozsvÄ›cujeme a zhasĂnáme tak rychle, Ĺľe to +lidskĂ© oko nepostĹ™ehne. KdyĹľ potom budeme rĹŻznÄ› mÄ›nit periodu svÄ›tla a tmy, bude +se zdát, Ĺľe ledka svĂtĂ vĂce ÄŤi mĂ©nÄ› jasnÄ›. Tato metoda se oznaÄŤuje PWM a je to +vlastnÄ› jeden ze zpĹŻsobĹŻ, jak pĹ™evĂ©st digitálnĂ signál (nuly a jedniÄŤky) na +analogovĂ˝ (jas žárovky, vĂ˝kon motoru, aj.). +*/ +/* +MĹŻĹľeme si tedy vyzkoušet, jak bude regulace jasu fungovat u našeho starĂ©ho známĂ©ho +hada. Program had bude podobnĂ˝ jako v minulĂ˝ch programech, pouze mĂsto pĹ™ĂkazĹŻ: +PORTB=...; +_delay_ms(...); + +zamÄ›nĂme za funkci: +rozsvit(...). + +Funkce "rozsvit()" bude zajišťovat rychlĂ© blikánĂ ledek (viz výše). DĂ©lku periody +svÄ›tla vĹŻÄŤi periodÄ› tmy, bude tato funkce pĹ™ebĂrat z promÄ›nnĂ© "jas". +*/ +/* +Program by mohl vypadat tĹ™eba 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 VZOR 0b00000111 //tato konstanta urÄŤuje dĂ©lku hada + +#define DOBA 50 //tato konstanta ovlivĹuje rychlost hada + //(ÄŤas na jeden krok v ms) + +volatile unsigned char jas=64; /*tato promÄ›nná je globálnĂ, protoĹľe se nastavuje v +pĹ™erušenĂ (ÄŤtenĂ tlaÄŤĂtek) a zároveĹ ji potĹ™ebujeme ÄŤĂst ve funkci "rozsvit". +V tĂ©to promÄ›nnĂ© bude uloĹľeno ÄŤĂslo (0-128), kterĂ© bude urÄŤovat jas ledek.*/ + +/********************************************/ +/* **************************** */ +/* * Deklarace funkcĂ * */ +/* **************************** */ +/********************************************/ +/* +Deklarace funkce je vlastnÄ› hlaviÄŤka funkce, se stĹ™ednĂkem. HlaviÄŤka se pĂše tak jak +je uvedena v definici. PomocĂ deklarace funkce, dáváme pĹ™ekladaÄŤi najevo, Ĺľe daná +funkce existuje. Od tohoto mĂsta dále tedy mĹŻĹľeme funkci volat, i kdyĹľ je ve +skuteÄŤnosti nadefinovaná aĹľ na konci programu. +*/ +void rozsvit(unsigned char co, unsigned char jakdlouho); +/* +Nadeklarujeme si funkci, která zaĹ™ĂdĂ regulaci jasu ledek, jak bylo popsáno výše. +Tato funkce bude pĹ™ebĂrat parametry: +"co" = ledky kterĂ© budou svĂtit, +"jakdlouho" = jak dlouho budou svĂtit [ms] +Dále tuto funkci ovlivĹuje globálnĂ promÄ›nná "jas", která udává jas +ledek v procentech (0 - 128) */ + +/********************************************/ +/* **************************** */ +/* * HlavnĂ funkce * */ +/* **************************** */ +/********************************************/ + +int main (void) +{ +unsigned char had=0; //nadefinujeme si promÄ›nnou, ve kterĂ© bude uloĹľen had + +DDRB = 0xff; //všechny piny na portu "B" budou vĂ˝stupnĂ + +/*NynĂ si nastavĂme pĹ™erušenĂ od ÄŤasovaÄŤe "0" - bude ÄŤasovat ÄŤtenĂ klávesnice*/ +TIMSK|= 1; //nastavĂme nultĂ˝ bit na "1" (vybereme pĹ™erušenĂ od ÄŤasovaÄŤe "0") +SREG |=(1<<7); //"globálnĂ" povolenĂ pĹ™erušenĂ (nastavĂme 7\. bit registru SREG) +TCCR0 = 5; //Zapneme ÄŤasovaÄŤ "0" s pĹ™eddÄ›liÄŤkou 1024. + +for(;;) + { //hlavnĂ smyÄŤka + + had<<=1; //posuneme hada + if (had<VZOR) //pokud jsme rozsvĂtili mĂ©nÄ› ledek neĹľ je dĂ©lka hada + had++; //rozsvĂtĂme poslednĂ ledku + + rozsvit(had, DOBA);//zavoláme funkci "rozsvit" a Ĺ™ekneme jĂ kterĂ© ledky má rozsvĂtit + + } //konec hlavnĂ smyÄŤky +} //konec funkce main + +/********************************************/ +/* **************************** */ +/* * Definice funkcĂ * */ +/* **************************** */ +/********************************************/ + +/*****************************/ +/* Rozsvit */ +/*****************************/ +void rozsvit(unsigned char co, unsigned char jakdlouho) + { + + for(unsigned char i=0; i<jakdlouho; i++) //jeden cyklus trvá cca 1 ms + { + for (unsigned char j=1;j<=128;j++) + { + if(jas>=j) //pokud je v promÄ›nnĂ© "j" menšà čĂslo neĹľ v promÄ›nnĂ© "jas" + PORTB=co; //RozsvĂtĂme poĹľadovanĂ© ledky + else //jinak + PORTB = 0; //zhasneme všechny ledky + _delay_us(7); //poÄŤkáme 7 us + } + + } + /* + Je snahou, aby tato smyÄŤka obsahovala co nejmĂ©nÄ› pĹ™ĂkazĹŻ, protoĹľe vykonánĂ + kaĹľdĂ©ho pĹ™Ăkazu zabere procesoru nÄ›jakĂ˝ ÄŤas. + Jeden cyklus tedy netrvá pouze 128 * 7 us = 896 us, nĂ˝brĹľ o nÄ›co dĂ©le. + */ + } + +/*****************************/ +/* ÄŚtenĂ tlaÄŤĂtek */ +/*****************************/ +ISR(TIMER0_OVF_vect) + { + 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, neboli jednou za cca 100 ms) + + if (!(PIND&0b00000100)) //pokud je stisknutĂ© tlaÄŤĂtko 1 (jas+) + { + if (jas==0) //pokud je jas "0" + jas=1; + else //pokud jas nenĂ "0" + { + if(jas<128) //pokud je menšà neĹľ 128 (maximálnĂ jas) + jas<<=1; //zvýšĂme jas na dvojnásobek (bitovĂ˝ posun doleva) + /* + PromÄ›nná "jas" tedy mĹŻĹľe nabĂ˝vat hodnot: + 0, 1, 2, 4, 8, 16, 32, 64 a 128 + */ + } + + TCNT0=60; //ÄŚasovaÄŤ zaÄŤne poÄŤĂtat od 60 mĂsto 157 (poÄŤĂtá do 255), takĹľe + } + + if (!(PIND&0b00001000)) //pokud je stisknutĂ© tlaÄŤĂtko 2 (jas-) + { + jas>>=1; //snĂĹľĂme jas na polovinu (bitovĂ˝ posun doprava) + + TCNT0=60; //ÄŚasovaÄŤ zaÄŤne poÄŤĂtat od 60 mĂsto 157 (poÄŤĂtá do 255), takĹľe + //přÚtĂ ÄŤtenĂ tlaÄŤĂtka bude za cca 200 ms mĂsto pĹŻvodnĂch 100 ms. + + } + + } + +//Pro radioklub OK1KVK naspal Vašek Král + +``` \ No newline at end of file