#include <stdint.h>
#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
//********** funcje obsługi TWI dla rtc
#define zegar 0xA2 // A0 rtc do plusa
#define ACK 1
#define NOACK 0
static void TWI_start(void)
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)));
}
static void TWI_stop(void)
{
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}
void TWI_write(unsigned char scalak,unsigned char adres_rejestru,unsigned char liczba)
{
TWCR =(1 << TWINT) | (1 << TWSTA) | ( 1 << TWEN );
while(!(TWCR & (1 << TWINT)));
TWDR =scalak;
TWCR =(1 << TWINT) | (1 << TWEN);
while(!(TWCR & (1 << TWINT)));
TWDR =adres_rejestru;
TWCR =(1 << TWINT) | (1 << TWEN);
while(!(TWCR & (1 << TWINT)));
TWDR =liczba;
TWCR =(1 << TWINT) | (1 << TWEN);
while(!(TWCR & (1 << TWINT)));
TWCR =(1 << TWINT) | (1<<TWEN) | (1<<TWSTO);
}
unsigned char TWI_read(unsigned char scalak,unsigned char adres_rejestru)
{
unsigned char odczyt;
TWCR =(1 << TWINT) | (1 << TWSTA) | ( 1 << TWEN );
while(!(TWCR & (1 << TWINT)));
TWDR =scalak;
TWCR =(1 << TWINT) | (1 << TWEN);
while(!(TWCR & (1 << TWINT)));
TWDR =adres_rejestru;
TWCR =(1 << TWINT) | (1 << TWEN);
while(!(TWCR & (1 << TWINT)));
TWCR =(1 << TWINT) | (1 << TWSTA) | ( 1 << TWEN );
while(!(TWCR & (1 << TWINT)));
TWDR =scalak | 0x01;
TWCR =(1 << TWINT) | (1 << TWEN);
while(!(TWCR & (1 << TWINT)));
TWCR =(1 << TWINT) | (1 << TWEN);
while(!(TWCR & (1 << TWINT)));
odczyt =TWDR;
TWCR =(1 << TWINT) | (1<<TWEN) | (1<<TWSTO);
return(odczyt);
}
//********** funkcje konwersji
char dec_na_bcd(char num) {return ((num/10 * 16) + (num % 10));} //set = dec_na_bcd(set);
char bcd_na_dec(char num) {return ((num/16 * 10) + (num % 16));} //set = bcd_na_dec(set);
//********** definicje zmiennych dla zegara
unsigned char PCF_tmp;
unsigned char PCF_dl,PCF_jl,PCF_dmc,PCF_jmc,PCF_ddni,PCF_jdni; //odczyt daty
unsigned char PCF_dg,PCF_jg,PCF_dm,PCF_jm,PCF_ds,PCF_js,PCF_dss,PCF_jss;//odczyt czasu
unsigned char dutc,jutc,leddis1,leddis2,leddis3,leddis4,leddis5,leddis6;//czas i data po konwersji
//********** definicje zmiennych dla menu
unsigned char wyswietlacz,leddis,funkcja,tryb,enter;
unsigned char set_h,set_hh,set_hhh,set_m,set_mm,set_mmm;
//********** define segmentów wyświetlacza
const unsigned char cyfra[12]={
0xC0,/*cyfra 0 A */
0xF9,/*cyfra 1 --- */
0xA4,/*cyfra 2 | | */
0xB0,/*cyfra 3 F | | B */
0x99,/*cyfra 4 | | */
0x92,/*cyfra 5 G --- */
0x82,/*cyfra 6 | | */
0xF8,/*cyfra 7 E | | C */
0x80,/*cyfra 8 | | */
0x90,/*cyfra 9 --- */
0x7F,/*kropka D # H */
0xFF,/*segmenty wygaszone */
};
//***** MAIN
int main()
{
DDRA=0xFF; //wyjścia - segmenty wyświetlaczy wyś_1 oraz wyś_2
DDRB=0xFF; //wyjścia - cyfry wyświetlacza czasu lokalnego
DDRC=0xFC; //wyjścia pomocnicze- wejścia - SCL SDA układu rtc8583
PORTC=0x03; //pull-up - dla SCL SDA INT1 układu rtc8583
DDRD=0x00; //wejścia - klawiatura
PORTD=0xF8; //pull-up - klawiatura
//----- TWI init
TWSR=0x00;
TWBR=0x48; //preskaler I2C - ((F_CPU / 100000UL - 16)
TCCR1B |= (1 << WGM12); //ustawia timer1 w tryb CTC
OCR1A = 5000; //ustawia wartość 50Hz na segment wyświetlacza
TCCR1B |= (1 << CS10); //ustawia timer z preskalerem Fcpu/1
TIMSK |= (1 << OCIE1A); //zezwolenie na przerwania dla CTC
sei();
//********** pętla główna progranu
while(1)
{
PCF_tmp=TWI_read(zegar,0x01); PCF_dss=PCF_tmp >>4; PCF_jss=PCF_tmp & 0x0F; //odczyt setnych sekund
if(PCF_jss==0)//jeżeli setne sekundy zero to odczyt z PCF-a
{
PCF_tmp=TWI_read(zegar,0x10); PCF_dl=PCF_tmp >>4; PCF_jl=PCF_tmp & 0x0F; //odczyt lat
PCF_tmp=TWI_read(zegar,0x06); PCF_dmc=PCF_tmp >>4; PCF_jmc=PCF_tmp & 0x0F; //odczyt miesięcy
PCF_tmp=TWI_read(zegar,0x05); PCF_ddni=PCF_tmp >>4; PCF_jdni=PCF_tmp & 0x0F;//odczyt dni
PCF_tmp=TWI_read(zegar,0x04); PCF_dg=PCF_tmp >>4; PCF_jg=PCF_tmp & 0x0F; //odczyt godzin
PCF_tmp=TWI_read(zegar,0x03); PCF_dm=PCF_tmp >>4; PCF_jm=PCF_tmp & 0x0F; //odczyt minut
PCF_tmp=TWI_read(zegar,0x02); PCF_ds=PCF_tmp >>4; PCF_js=PCF_tmp & 0x0F; //odczyt sekund
}
//********** obsługa klawiszy
if(!(PIND & _BV(5))) { _delay_ms(50); funkcja++; while(!(PIND & _BV(5))) _delay_ms(50); }
if(!(PIND & _BV(6)))
{
if((funkcja==1)||(funkcja==5))
{
_delay_ms(300);
if(++set_hhh >= 24) { set_hhh = 0; }
if(++set_h >= 10) { set_hh++; set_h = 0; }
if((set_hh>=2)&&(set_h>=4)){ set_h=0; set_hh=0; }//jeżeli 24 godziny to wyzeruj
}
if(funkcja==2)
{
_delay_ms(300);
if(++set_hhh >= 60) { set_hhh = 0; }
if(++set_h >= 10) { set_hh++; set_h = 0; }
if((set_hh>=6)&&(set_h>=0)){ set_h=0; set_hh=0; }//jeżeli 60 minut to wyzeruj
}
if(funkcja==3)
{
_delay_ms(300);
if(++set_hhh >= 32) { set_hhh = 0; }
if(++set_h >= 10) { set_hh++; set_h = 0; }
if((set_hh>=3)&&(set_h>=2)){ set_h=0; set_hh=0; }//jeżeli 32 dni to wyzeruj
}
if(funkcja==4)
{
_delay_ms(300);
if(++set_hhh >= 32) { set_hhh = 0; }
if(++set_h >= 10) { set_hh++; set_h = 0; }
if((set_hh>=1)&&(set_h>=2)){ set_h=0; set_hh=0; }//jeżeli 12 miesięcy to wyzeruj
}
}
if(!(PIND & _BV(7))) { enter=1; }
//********** funkcje wyswietlania i programowania
switch(funkcja)
{
case 0://********** czas lokalny gmt oraz data
if(!(PIND & _BV(4))) { _delay_ms(50); tryb++; while(!(PIND & _BV(4))) _delay_ms(50); }
if(tryb==0)//czas lokalny
{
leddis1=bcd_na_dec(PCF_dg); leddis2=bcd_na_dec(PCF_jg); //konwersja na dec godziny
leddis3=bcd_na_dec(PCF_dm); leddis4=bcd_na_dec(PCF_jm); //konwersja na dec minuty
leddis5=bcd_na_dec(PCF_ds); leddis6=bcd_na_dec(PCF_js); //konwersja na dec sekundy
}
if(tryb==1)//czas gmt
{
dutc=bcd_na_dec(PCF_dg); jutc=bcd_na_dec(PCF_jg); //konwersja na dec godziny
if((dutc==0)&&(jutc==0)) { leddis1=2; leddis2=3; }
if((dutc==0)&&(jutc==1)) { leddis1=0; leddis1=0; leddis2=2; }
if((dutc==0)&&(jutc==2)) { leddis1=0; leddis2=1; }
if((dutc==0)&&(jutc==3)) { leddis1=0; leddis2=2; }
if((dutc==0)&&(jutc==4)) { leddis1=0; leddis2=3; }
if((dutc==0)&&(jutc==5)) { leddis1=0; leddis2=4; }
if((dutc==0)&&(jutc==6)) { leddis1=0; leddis2=5; }
if((dutc==0)&&(jutc==7)) { leddis1=0; leddis2=6; }
if((dutc==0)&&(jutc==8)) { leddis1=0; leddis2=7; }
if((dutc==0)&&(jutc==9)) { leddis1=0; leddis2=8; }
//------------------------------------------------------
if((dutc==1)&&(jutc==0)) { leddis1=0; leddis2=9; }
if((dutc==1)&&(jutc==1)) { leddis1=1; leddis2=0; }
if((dutc==1)&&(jutc==2)) { leddis1=1; leddis2=1; }
if((dutc==1)&&(jutc==3)) { leddis1=1; leddis2=2; }
if((dutc==1)&&(jutc==4)) { leddis1=1; leddis2=3; }
if((dutc==1)&&(jutc==5)) { leddis1=1; leddis2=4; }
if((dutc==1)&&(jutc==6)) { leddis1=1; leddis2=5; }
if((dutc==1)&&(jutc==7)) { leddis1=1; leddis2=6; }
if((dutc==1)&&(jutc==8)) { leddis1=1; leddis2=7; }
if((jutc==1)&&(jutc==9)) { leddis2=1; leddis1=8; }
//------------------------------------------
if((dutc==2)&&(jutc==0)) { leddis1=1; leddis2=9; }
if((dutc==2)&&(jutc==1)) { leddis1=2; leddis2=0; }
if((dutc==2)&&(jutc==2)) { leddis1=2; leddis2=1; }
if((dutc==2)&&(jutc==3)) { leddis2=2; leddis1=2; }
leddis3=bcd_na_dec(PCF_dm); leddis4=bcd_na_dec(PCF_jm); //konwersja na dec minuty
leddis5=bcd_na_dec(PCF_ds); leddis6=bcd_na_dec(PCF_js); //konwersja na dec sekundy
}
if(tryb==2)//data
{
leddis1=bcd_na_dec(PCF_dmc); leddis2=bcd_na_dec(PCF_jmc); //konwersja na dec miesięcy
leddis3=bcd_na_dec(PCF_ddni); leddis4=bcd_na_dec(PCF_jdni); //konwersja na dec dni
leddis5=bcd_na_dec(PCF_dl); leddis6=bcd_na_dec(PCF_jl); //konwersja na dec lat
_delay_ms(2000); tryb=0;
}
break;
case 1://********** ustaw czas lokalny godziny
leddis1=set_hh; leddis2=set_h; leddis3=11; leddis4=10; leddis5=11; leddis6=10;//LED DISPALY
if(enter==1)
{
TWI_write(zegar,0x04,dec_na_bcd(set_hhh));
_delay_ms(200); set_h=0; set_hh=0; set_hhh=0; enter=0; funkcja=2;
}
break;
case 2://********** ustaw czas lokalny minuty
leddis1=11; leddis2=10; leddis3=set_hh; leddis4=set_h; leddis5=11; leddis6=10;//LED DISPALY
if(enter==1)
{
TWI_write(zegar,0x03,dec_na_bcd(set_hhh)); _delay_ms(100);
_delay_ms(200); set_h=0; set_hh=0; set_hhh=0; enter=0; funkcja=0;
}
break;
case 3://********** ustaw date dni
leddis1=set_hh; leddis2=set_h; leddis3=11; leddis4=10; leddis5=11; leddis6=10;//LED DISPALY
if(enter==1)
{
TWI_write(zegar,0x05,dec_na_bcd(set_hhh)); _delay_ms(100);
_delay_ms(200); set_h=0; set_hh=0; set_hhh=0; enter=0; funkcja=4;
}
break;
case 4://********** ustaw date miesiące
leddis1=11; leddis2=10; leddis3=set_hh; leddis4=set_h; leddis5=11; leddis6=10;//LED DISPALY
if(enter==1)
{
TWI_write(zegar,0x06,dec_na_bcd(set_hhh)); _delay_ms(100);
_delay_ms(200); set_h=0; set_hh=0; set_hhh=0; enter=0; funkcja=5;
}
break;
case 5://********** ustaw date lata
if(!(PIND & _BV(5))) { _delay_ms(50); funkcja=8; while(!(PIND & _BV(5))) _delay_ms(50); }
leddis1=11; leddis2=10; leddis3=11; leddis4=10; leddis5=set_hh; leddis6=set_h;//LED DISPALY
if(enter==1)
{
TWI_write(zegar,0x10,dec_na_bcd(set_hhh)); _delay_ms(100);
_delay_ms(200); set_h=0; set_hh=0; set_hhh=0; enter=0; funkcja=0;
}
break;
case 8:
funkcja=0;
break;
}
}
return 0;
}
//********** wyswietlanie multipleksowane
ISR(TIMER1_COMPA_vect)
{
switch(wyswietlacz)
{
case 0://------cyfra nr 1 port PB2
PORTC=0xFC;
PORTB = 0xFB; PORTA = cyfra[leddis1]; wyswietlacz++;
break;
case 1://------cyfra nr 2 port PB3
PORTB = 0xF7; PORTA = cyfra[leddis2]; wyswietlacz++;
break;
case 2://------cyfra nr 3 port PB4
PORTB = 0xEF; PORTA = cyfra[leddis3]; wyswietlacz++;
break;
case 3://------cyfra nr 4 port PB5
PORTB = 0xDF; PORTA = cyfra[leddis4]; wyswietlacz++;
break;
case 4://------cyfra nr 5 port PB6
PORTB = 0xBF; PORTA = cyfra[leddis5]; wyswietlacz++;
break;
case 5://------cyfra nr 6 port PB7
PORTB = 0x7F; PORTA = cyfra[leddis6]; wyswietlacz++;
break;//----------------------------------------------
case 6:
wyswietlacz=0;
break;
}
if(tryb==0)//diody led informujace o trybie wyświetlania
{
PORTC &=~ _BV(5);//czerwona czas lokalny
}
if(tryb==1)
{
PORTC &=~ _BV(6);//zielona czas gmt
}
if(tryb==2)
{
PORTC |= _BV(5);//obie wygaszone
PORTC |= _BV(6);
}
}