``` title = "Digitální hodiny s ATmega8" perex = "Zapojení jednoduchých digitálních hodin s mikroprocesorem ATmega8." tags = ["Článek", "Bastlení", "AVR", "Pro začátečníky"] image = "lead.png" lang="c" ```  Toto zapojení využívá k řízení hodin mikroprocesor od firmy Atmel - ATmega8. Originální realizace pochází z [Daqq.eu](http://www.daqq.eu/?p=283). Celé zapojení je poměrně jednoduché, jediná záludnost může nastat při programování mikroprocesoru. Způsobů jak toho úspěšně dosáhnout je mnoho. Pokud nechce stavět něco složitého, tak jeden jednoduchý programátor je [zde](http://pandatron.cz/?166&avr_programator) nebo si ho můžete za pár korun koupit například [zde](http://aukro.cz/listing/listing.php?string=usbasp&search_scope=). My jsme si pak na kroužku postavili [tento](/clanek/2011/usbasp-programator-avr/) do USB. Všechny součástky jsou vývodové a pod mikroprocesor jsme zatím dali raději patici pro snažší manipulaci s mikroprocesorem. Toto zapojení jsme pojali jako motivační, postavit si něco praktického s využitím mikroprocesoru. Celé hodiny jsou tvořeny dvěma [DPS](http://cs.wikipedia.org/wiki/Plo%C5%A1n%C3%BD_spoj), které jsou na sebe navzájem kolmé. V místě kontaktu desek jsou sletovány pájecí plošky a tím je zaručen přenost signálů pro displej. Ihned po zapojení na napájení by se na hodinách měl objevit čas 00:00 a čítání času běží (pokud máte samozřejmě správně zapojení a naprogramován mikroprocesor). Aktuální čas nastavíte pomocí tlačítek SW1 (minuty) a SW2 (hodiny). Celé hodiny je pak možné zabudovat do krabičky a lze je napájet 9V baterií nebo lépe adaptérem ze sítě (spotřeba 100 mA). Displej jsme použili [CA56-21SRWA](http://www.tme.eu/cz/katalog/artykuly.phtml?search=CA56-21SWRA&idp=1#cleanParameters%3D1%26search%3DCA56-21SRWA%26bf_szukaj%3D+) ([2](http://www.hledejsoucastky.cz/Hledani.aspx?lastsearch=CA56-21SRWA)), na které máme i nakreslený plošný spoj. Mikroprocesor je [ATmega8a-PU](http://www.hledejsoucastky.cz/Hledani.aspx?lastsearch=ATMEGA8a-PU) v pouzdru DIL28. **Pro správnou funkci hodin je zapotřebí naprogramovat pojistky (fuses).** Pojistkami nastavíte, aby mikroprocesor bral hodinový signál z externího krystalu 14.7456 MHz, jinak by běžěl na standardní frekvenci 1 MHz a nefungovalo by správně zobrazování ani počítání času. Naše doporučené hodnoty pojistek jsou: `hfuse=C9, lfuse=FF`. # Schéma . # Plošný spoj    # Zdrojové soubory **Schéma:** [eagle](https://git.ok1kvk.cz/krouzek/digitalni-hodiny-s-atmega8/raw/master/HW/digitalni-hodiny.sch), [PDF](https://git.ok1kvk.cz/krouzek/digitalni-hodiny-s-atmega8/raw/master/schema.pdf) **Plošný spoj:** [eagle](https://git.ok1kvk.cz/krouzek/digitalni-hodiny-s-atmega8/raw/master/HW/digitalni-hodiny.brd), [PDF 1:1](https://git.ok1kvk.cz/krouzek/digitalni-hodiny-s-atmega8/raw/master/plosny-spoj.pdf) **Osazovací plán:** [PDF](https://git.ok1kvk.cz/krouzek/digitalni-hodiny-s-atmega8/raw/master/osazovaci-plan.pdf) **Celý projekt:** [ZIP](https://git.ok1kvk.cz/krouzek/digitalni-hodiny-s-atmega8/repository/archive.zip?ref=master) **Projekt na GitLabu** [digitalni-hodiny-s-atmega8.git](https://git.ok1kvk.cz/krouzek/digitalni-hodiny-s-atmega8) Aktuální zdrojový kód naleznete na našem [GitLabu](https://git.ok1kvk.cz/krouzek/digitalni-hodiny-s-atmega8/blob/master/SW/hodiny.c), kde také naleznete [přeložený zdojový kód](https://git.ok1kvk.cz/krouzek/digitalni-hodiny-s-atmega8/builds) do formátu [HEX](https://cs.wikipedia.org/wiki/Intel_HEX). Deska byla vyrobena [metodou nažehlením tonneru](/clanek/2008/vyroba-plosnych-spoju/). # Seznam součástek: | Označení | Hodnota | Datasheet | Odkaz do obchodu | |----------|--------------|-----------|------------------| | R1 - R8 | 330 Ω | | | | R9 - R11 | 10 kΩ | | | | C1, C2 | 22 pF | | | | C3 | 100 nF | | | | C4, C5 | 100 µF | | | | IC1 | 7805 (TO220) | [LM7805.pdf](https://www.sparkfun.com/datasheets/Components/LM7805.pdf) | [tme.eu](http://www.tme.eu/cz/details/l7805acv/stabilizatory-napeti-neregulovane/st-microelectronics/) | | IC4 | ATmega8A-PU | [ATmega8a.pdf](http://www.atmel.com/images/atmel-8159-8-bit-avr-microcontroller-atmega8a_datasheet.pdf) | [tme.eu](http://www.tme.eu/cz/details/atmega8a-pu/mikroprocesory-atmel-avr-tht/atmel/) | | D1 | LED displej | [CA56-21SRWA.pdf](http://www.tme.eu/cz/Document/fd133b55ab2a5f9e4bf70453b9a4fb6d/BC56-12.pdf) | [tme.eu](http://www.tme.eu/cz/details/ca56-21srwa/ctyrmistne-led-displeje/kingbright-electronic/) | | Q1 | 14,7456 MHz | | [tme.eu](http://www.tme.eu/cz/details/hc49us-ff3f14.7456/krystalove-rezonatory-tht/ilsi/hc49us-ff3f18-147456/) | | SW1, SW2 | mikrotlačítka s delším hmatníkem | | | # Video <iframe src="https://www.youtube.com/embed/CAZYkOt0Mgk" frameborder="0" height="315" width="560"></iframe> # Dejte nám vědět! Jestli narazíte u tohoto zapojení na nějaký problém, tak nám napište na [fórum](https://ok1kvk.cz/forum/viewtopic.php?f=24&t=120). # Program v jazyce C ``` #include <avr/io.h> #include <avr/interrupt.h> #include <avr/wdt.h> #include <stdio.h> #define _s_A 2 #define _s_B 0 #define _s_C 6 #define _s_D 4 #define _s_E 3 #define _s_F 1 #define _s_G 7 #define _s_dot 5 const unsigned char segs[] = { _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F), //0 _BV(_s_B) | _BV(_s_C), //1 _BV(_s_A) | _BV(_s_B) | _BV(_s_D) | _BV(_s_E) | _BV(_s_G), //2 _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_G), //3 _BV(_s_B) | _BV(_s_C) | _BV(_s_F) | _BV(_s_G), //4 _BV(_s_A) | _BV(_s_C) | _BV(_s_D) | _BV(_s_F) | _BV(_s_G), //5 _BV(_s_A) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //6 _BV(_s_A) | _BV(_s_B) | _BV(_s_C), //7 _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //8 _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_F) | _BV(_s_G), //9 _BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //A _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //B _BV(_s_A) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F), //C _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_G), //D _BV(_s_A) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), //E _BV(_s_A) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G) //F }; #define _ms(n) (17*n) void wait(unsigned int a) //basic wait { volatile unsigned int b,c; for(b=0;b!= a; b++)for(c=0;c!= 50;c++); return; } unsigned char prescale=0; unsigned char sec=0; unsigned char min_1=0; unsigned char min_10=0; unsigned char hour_1=0; unsigned char hour_10=0; unsigned char show_t=0; ISR(TIMER1_OVF_vect) { if(++prescale == 225){prescale = 0;sec++;}; if(sec>59){min_1++;sec=0;}; if(min_1>9){min_1=0;min_10++;}; if(min_10>5){min_10=0;hour_1++;}; if(hour_1>9){hour_1=0;hour_10++;}; if(hour_10>1 && hour_1>3){hour_1=0;hour_10=0;}; if(++show_t==4) show_t=0; switch(show_t) { case 0: //show minutes PORTC = 0x04; PORTD = (~segs[min_1]) & ~_BV(_s_dot); break; case 1: //show 10 minutes PORTC = 0x08; PORTD = (~segs[min_10]) & ~_BV(_s_dot); break; case 2: //show hours PORTC = 0x10; PORTD = (~segs[hour_1]) & ~_BV(_s_dot); break; case 3: //show 10hours PORTC = 0x20; PORTD = (~segs[hour_10]) & ~_BV(_s_dot); break; default: show_t = 0; break; } return; } #define B1() (bit_is_clear(PINB,3)) #define B2() (bit_is_clear(PINB,4)) #define B_WAIT 300 #define nop() asm volatile ("nop;") int main(void) { TIMSK = 0x04; TCCR1B = 0x01; DDRD = 0xFF; DDRC = 0x3F; DDRB = 0x00; PORTB = 0xFF; sei(); while(1) { if(B1()) { wait(_ms(B_WAIT)); min_1++; sec=0; } if(B2()) { wait(_ms(B_WAIT)); hour_1++; sec=0; } } } ```