
Rostislav Vyroubal, Rostislav Nunvář UREL, FEEC, VUT Brno
xvyrou00
stud.feec.vutbr.cz
xnunva00
stud.feec.vutbr.cz

/*
********************************************************************************
** Nazev souboru : MMIA1.c
** Mikrokontroler : ATmega16
** Popis : Srovnani hodin s PCF8563 a SW hodin s 16MHz krystalem
** Autor : Rostislav Vyroubal, Rostislav Nunvar
** Predmet : Mikroprocesorova technika
** Posledni zmena : 19.4.2010
********************************************************************************
*/
/*******************************************************************************
pouzite veci
- krystal 16MHz
- funkce
- pouziva 16 bit citac1
fosc= fclk/(2*N*(1+OCR)) ; N= 1 8 32 64 128 256 1024
fosc= 16000000/(2*256*(1+31249))=1Hz
- pocet cyklu citace pro jednu sekundu je 15624 = 0011 1101 0000 1000
********************************************************************************
*/
#include "lcd_h.h"
#include "lcd_c.c"
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#define PCF8563 0xA2 // adresa PCF8563
#define I2C_READ 1 // PCF8563 cteni
#define I2C_WRITE 0 // PCF8563 zapis
#define sekundyRTC 0x02
#define minutyRTC 0x03
#define hodinyRTC 0x04
#define dnyRTC 0x05
#define den_v_tydnuRTC 0x06
#define mesiceRTC 0x07
#define rokyRTC 0x08
char buffer1[20];
char rozdil;
unsigned char DEC;
// promenny pro RTC
unsigned int BCD;
unsigned char sekundy;
unsigned char minuty;
unsigned char hodiny;
unsigned char dny;
unsigned char den_v_tydnu;
unsigned char mesice;
unsigned char roky;
// promenné pro SW hodiny
char sekunda =0;
char minuta =0;
char hodina =0;
char den =0;
char mesic =0;
int rok =0;
unsigned char read(bunka)
{
i2c_start_wait(PCF8563+I2C_WRITE); // zapis do PCF8563
i2c_write(bunka); // adresa bunky
i2c_rep_start(PCF8563+I2C_READ); // cteni z PCF8563
BCD=i2c_readNak();
i2c_stop(); // stop
};
unsigned char write(DEC,bunka)
{
// Prevede DEC do BCD
BCD = ((((DEC/10) <<4) & 0xF0) | ((DEC% 10) & 0x0F));
i2c_start_wait(PCF8563+I2C_WRITE);
i2c_write(bunka); // vyber adresy( hodiny minuty atd)
i2c_write(BCD); // zapise BCD na vybranou adresu
i2c_stop(); // stop
};
ISR(TIMER1_COMPA_vect)
{
// Zacatek RTC hodin
read(rokyRTC); // cte roky z RTC
roky = (((BCD & 0xf0)>>4)*10 + (BCD & 0x0f));
read(mesiceRTC); // cte mesice z RTC
mesice = ((((BCD & 0b10011111) & 0xf0)>>4)*10 + (BCD & 0x0f));
read(den_v_tydnuRTC); // cte tydny z RTC
den_v_tydnu = BCD & 0b00000111;
read(dnyRTC); // cte dny z RTC
dny = ((((BCD & 0b00111111) & 0xf0)>>4)*10 + (BCD & 0x0f));
read(hodinyRTC); // cte hodiny z RTC
hodiny = ((((BCD & 0b00111111) & 0xf0)>>4)*10 + (BCD & 0x0f));
read(minutyRTC); // cte minuty z RTC
minuty = ((((BCD & 0b01111111) & 0xf0)>>4)*10 + (BCD & 0x0f));
read(sekundyRTC); // cte sekundy z RTC
sekundy = ((((BCD & 0b01111111) & 0xf0)>>4)*10 + (BCD & 0x0f)) ;
// Konec RTC hodin
// Zacatek SW hodin
sekunda++;
if (sekunda>=60)
{
sekunda=0;
minuta++;
};
if (minuta>=60)
{
minuta=0;
hodina++;
};
if (hodina>=24)
{
den++;
hodina=0;
};
switch (mesic)
{
case 1:
if (den==31)
{
den=1;
mesic++;
};
break;
case 2:
if ( (rok % 4)==0 )
{ //zbytek po deleni 4 je 0
if (den==30)
{
den=1;
mesic++;
}
}
else{
if (den==29)
{
den=1;
mesic++;
};
};
break;
case 3:
if (den==31)
{
den=1;
mesic++;
};
break;
case 4:
if (den==30)
{
den=1;
mesic++;
};
break;
case 5:
if (den==31)
{
den=1;
mesic++;
};
break;
case 6:
if (den==30)
{
den=1;
mesic++;
};
break;
case 7:
if (den==31)
{
den=1;
mesic++;
};
break;
case 8:
if (den==31)
{
den=1;
mesic++;
};
break;
case 9:
if (den==30)
{
den=1;
mesic++;
};
break;
case 10:
if (den==31)
{
den=1;
mesic++;
};
break;
case 11:
if (den==30)
{
den=1;
mesic++;
};
break;
case 12:
if (den>=31)
den=1;
mesic=1;
rok++;
break;
};
// Konec SW hodin
rozdil = sekunda - sekundy; // sekunda patří SW sekundy RTC
// Zacatek zapisu na LCD
lcd_gotoxy(0,0);
sprintf(buffer1,"RTC:%u:%u:%u ",hodiny,minuty,sekundy);
lcd_puts(buffer1);
sprintf(buffer1,"SW: %u:%u:%u ", hodina, minuta, sekunda);
lcd_gotoxy(0,1);
lcd_puts(buffer1);
sprintf(buffer1,"D:%u W:%u M:%u R:20%u ",dny,den_v_tydnu, mesice, roky);
lcd_gotoxy(0,2);
lcd_puts(buffer1);
sprintf(buffer1,"Rozdil sekund: %d ", rozdil);
lcd_gotoxy(0,3);
lcd_puts(buffer1);
// konec zapisu na lcd
};
int main(void)
{
DDRA=0b00000000; // PORTA vstupni
TCCR1A= 0b00000000; // konfigurace c/c
TCCR1B= 0b00001101; //konfigurace c/c
TIMSK = (1<<OCIE1A); //povoleni preruseni
OCR1AH =0b00111101; //pocet cyklu citace pro jednu sekundu (15624)
OCR1AL =0b00001000;
sei(); // povoleni globalniho preruseni
i2c_init(); // inicializace I2C
lcd_init(); // inicializace LCD
//* Konfigurace hodin**********************************************************
write(10,rokyRTC); // Rok je od 00 do 99
write(4,mesiceRTC);
write(1,den_v_tydnuRTC);//0 PO, 1 Ut, ...
write(20,dnyRTC);
write(21,hodinyRTC); // Bohuzel PCF8563 umoznuje mit den s 32hodinami:-)
write(35,minutyRTC);
write(0,sekundyRTC);
//****************************************************************************
//
// Na zacatku ulozime cas z RTC do SW hodin
read(hodinyRTC); // cte hodiny z RTC
// prevod bcd do bin s osetrenim ignorovanych bitu
hodina = ((((BCD & 0b00111111) & 0xf0)>>4)*10 + (BCD & 0x0f));
read(minutyRTC); // cte minuty z RTC
minuta = ((((BCD & 0b01111111) & 0xf0)>>4)*10 + (BCD & 0x0f));
read(sekundyRTC); // cte sekundy z RTC
sekunda = ((((BCD & 0b01111111) & 0xf0)>>4)*10 + (BCD & 0x0f)) ;
while(1) // cekaci smycka
{
if (bit_is_clear(PINA,PA7)) // Manualni reinicializace lcd pri jeho odpojeni
{
lcd_init();
lcd_clrscr();
lcd_puts("Loading");
};
asm ("nop");
asm ("nop");
};
}
