Digitální hodiny s ATmega8

Toto zapojení využívá k řízení hodin mikroprocesor od firmy Atmel - ATmega8. Originální realizace pochází z Daqq.eu. 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 nebo si ho můžete za pár korun koupit například zde. My jsme si pak na kroužku postavili tento 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, 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 (2), na které máme i nakreslený plošný spoj. Mikroprocesor je 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

Schéma.

Plošný spoj

Plošný spoj
Hodiny - pohled na součástky Plošky připravené k pájení - spojení dvou DPS

Zdrojové soubory

Schéma: eagle, PDF Plošný spoj: eagle, PDF 1:1 Osazovací plán: PDF

Celý projekt: ZIP

Projekt na GitLabu digitalni-hodiny-s-atmega8.git

Aktuální zdrojový kód naleznete na našem GitLabu, kde také naleznete přeložený zdojový kód do formátu HEX.

Deska byla vyrobena metodou nažehlením tonneru.

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 tme.eu
IC4 ATmega8A-PU ATmega8a.pdf tme.eu
D1 LED displej CA56-21SRWA.pdf tme.eu
Q1 14,7456 MHz tme.eu
SW1, SW2 mikrotlačítka s delším hmatníkem

Video

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.

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;
        }
    }
}