logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Mega16] [C] - RTC DS1337C (tryb 12/24h)

JmL(TM) 30 Cze 2008 13:57 3870 29
  • #1 5299470
    JmL(TM)
    Poziom 24  
    Witam!

    Walcze z tym juz od kilku dni i nie moge przestawic DS1337C na tryb zliczania 12 godz. W trybie 24 godz. wszystko smiga ale na 12 godz. nie chce "przejsc"! W datasheet'cie jest napisane:

    Cytat:
    The DS1337 can be run in either 12-hour or 24-hour mode. Bit 6 of the hours register is defined as the 12- or 24-hour mode-select bit. When high, the 12-hour mode is selected. In the 12-hour mode, bit 5 is the AM/PM bit with logic high being PM. In the 24-hour mode, bit 5 is the second 10-hour bit (20–23 hours). All hours values, including the alarms, must be reinitialized whenever the 12/24-hour mode bit is changed. The century bit (bit 7 of the month register) is toggled when the years register overflows from 99–00.


    Czyli zeby ustawic tryb 12h musze zmienic bit 6 rejestru pod adresem 0x02 [godzina]. Ale jesli to robie to zamiast przestawienia trybu godziny zmienia mi sie godzina 12:30:00 na 52:30:00! Czy ktos jest mi w stanie pomoc?

    Oto kod:

    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/pgmspace.h>
    #include <compat/deprecated.h>
    
    #include "global.h"
    #include "string.h"
    #include "i2c_master.h"
    //*======================================================================*//
    
    #define bit_get(p,m) ((p) & (m))
    #define bit_set(p,m) ((p) |= (m))
    #define bit_clear(p,m) ((p) &= ~(m))
    #define bit_flip(p,m) ((p) ^= (m))
    #define bit_write(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m))
    #define BIT(x) (0x01 << (x))
    #define LONGBIT(x) ((unsigned long)0x00000001 << (x))
    
    #define DS1337C				0xD0	//1101 0000B   - adres hardware'owy zegara DS1337C
    
    #define bcd2dec(bcd)			(((((bcd) >> 4) & 0x0F) * 10) + ((bcd) & 0x0F))
    #define dec2bcd(dec)			((((dec) / 10) << 4) | ((dec) % 10))
    
    //---------------------
    // Adresy w DS1337C
    //---------------------
    #define REG_SEKUNDA			0x00
    #define REG_MINUTA				0x01
    #define REG_GODZINA			0x02
    
    #define	REG_DZIEN_TYG		0x03
    
    #define REG_DZIEN				0x04
    #define REG_MIESIAC			0x05
    #define REG_ROK				0x06
    
    #define REG_ALARM1_SEKUNDA		0x07
    #define REG_ALARM1_MINUTA		0x08
    #define REG_ALARM1_GODZINA		0x09
    
    #define REG_ALARM1_DZIEN_TYG	0x0A
    #define REG_ALARM1_DZIEN		0x0B
    
    #define	MAX_SIZE				0x1E
    
    #define RTC_DTYG_1	PSTR("Poniedzialek")
    #define RTC_DTYG_2	PSTR("Wtorek")
    #define RTC_DTYG_3	PSTR("Sroda")
    #define RTC_DTYG_4	PSTR("Czwartek")
    #define RTC_DTYG_5	PSTR("Piatek")
    #define RTC_DTYG_6	PSTR("Sobota")
    #define RTC_DTYG_7	PSTR("Niedziela")
    
    char bufor[MAX_SIZE];
    
    typedef struct {
    	u08	godzina;
    	u08	minuta;
    	u08	sekunda;
    } strCzas;
    
    typedef struct {
    	u08	dzien_tyg;
    
    	u08	dzien;
    	u08	miesiac;
    	u08	rok;
    } strData;
    
    strCzas	czas;
    strData	data;
    
    u08	prv_sec;
    //*======================================================================*//
    
    void delay1s(void)
    {
    	for (int x=0; x<10; x++) {
    		_delay_ms(100);
    	}
    }
    //*======================================================================*//
    
    void writeByteI2C(u08 DevAddress, int Address, u08 Data)
    {
    	i2c_start_wait(DevAddress + I2C_WRITE);
    
    	i2c_write(Address);
    	i2c_write(Data);
    
    	i2c_stop();
    }
    //*======================================================================*//
    
    u08 readByteI2C(u08 DevAddress, int Address)
    {
    	u08 i2c_byte = 0x00;
    
    	i2c_start_wait(DevAddress + I2C_WRITE);
    	i2c_write(Address);
    
    	i2c_rep_start(DevAddress + I2C_READ);
    	i2c_byte = i2c_readNak();
    
    	i2c_stop();
    
    	return i2c_byte;
    }
    //*======================================================================*//
    
    void SetTime(void)
    {
    	//ustaw INTCN i A1IE, zeruj A2IE, wylacz oscylator
    	writeByteI2C(DS1337C, 0x0E, 0x85);
    
    	czas.godzina |= (1 << 6);			//ustaw tryb 12h
    
    	writeByteI2C(DS1337C, REG_SEKUNDA, dec2bcd(czas.sekunda));
    	writeByteI2C(DS1337C, REG_MINUTA, dec2bcd(czas.minuta));
    	writeByteI2C(DS1337C, REG_GODZINA, czas.godzina);
    
    	//startuj ponownie oscylator i kasuj status
    	//ustaw INTCN i A1IE, zeruj A2IE, wlacz oscylator
    	writeByteI2C(DS1337C, 0x0E, 0x05);
    
    	//kasuj flagi
    	writeByteI2C(DS1337C, 0x0F, 0x00);
    }
    //*======================================================================*//
    
    void SetDate(void)
    {
    	writeByteI2C(DS1337C, REG_DZIEN_TYG, dec2bcd(data.dzien_tyg));
    
        writeByteI2C(DS1337C, REG_DZIEN, dec2bcd(data.dzien));
        writeByteI2C(DS1337C, REG_MIESIAC, dec2bcd(data.miesiac));
        writeByteI2C(DS1337C, REG_ROK, dec2bcd(data.rok));
    }
    //*======================================================================*//
    
    void GetTime(void)
    {
    	czas.sekunda = readByteI2C(DS1337C, REG_SEKUNDA);
    	czas.minuta   = readByteI2C(DS1337C, REG_MINUTA);
    	czas.godzina  = readByteI2C(DS1337C, REG_GODZINA);
    }
    //*======================================================================*//
    
    void GetDate(void)
    {
    	data.dzien_tyg = readByteI2C(DS1337C, REG_DZIEN_TYG);
    
    	data.dzien	   = readByteI2C(DS1337C, REG_DZIEN);
    	data.miesiac = readByteI2C(DS1337C, REG_MIESIAC);
    	data.rok	   = readByteI2C(DS1337C, REG_ROK);
    }
    //*======================================================================*//
    
    int main(void)
    {
    	lcdInit();
    	lcdClear();
    
    	i2c_init();                             // initialize I2C library
    
    	czas.godzina	= 12;
    	czas.minuta	= 30;
    	czas.sekunda	= 0;
    
    	data.dzien_tyg	= 1;
    
    	data.dzien		= 30;
    	data.miesiac	= 6;
    	data.rok		= 8;
    
    	SetTime();
    	SetDate();
    
    	while(1)
    	{
    		GetTime();
    
    		if (czas.sekunda != prv_sec)
    		{
    			lcdGotoXY(0,0);
    
    			sprintf(bufor, "  %.2d:%.2d:%.2d  %.2d-%.2d-20%.2d  ",	bcd2dec(czas.godzina), bcd2dec(czas.minuta), bcd2dec(czas.sekunda), \
    																	bcd2dec(data.dzien), bcd2dec(data.miesiac), bcd2dec(data.rok));
    			lcdPrintData(bufor, strlen(bufor));
    		}
    
    		prv_sec = czas.sekunda;
    
    		GetDate();
    
    		switch (data.dzien_tyg)
    		{
    			case 1: strcpy_p(bufor, RTC_DTYG_1); break;
    			case 2: strcpy_p(bufor, RTC_DTYG_2); break;
    			case 3: strcpy_p(bufor, RTC_DTYG_3); break;
    			case 4: strcpy_p(bufor, RTC_DTYG_4); break;
    			case 5: strcpy_p(bufor, RTC_DTYG_5); break;
    			case 6: strcpy_p(bufor, RTC_DTYG_6); break;
    			case 7: strcpy_p(bufor, RTC_DTYG_7); break;
    		}
    
    		lcdGotoXY(0,1);
    		lcdPrintData(bufor, strlen(bufor));
    
    		_delay_ms(1000);
    	}
    
    	return 0;
    }
    //*======================================================================*//
  • Pomocny post
    #3 5299533
    skywalker
    Poziom 22  
    Witam mogę się mylić ale wg mnie kluczowe jest to :

    Cytat:
    The DS1337 can be run in either 12-hour or 24-hour mode. Bit 6 of the hours register is defined as the 12- or 24-hour mode-select bit. When high, the 12-hour mode is selected. In the 12-hour mode, bit 5 is the AM/PM bit with logic high being PM.


    Wg mnie w trybie 12h należy przy odczycie zamaskować dziesiątki godzin tj starszą połówkę rejestru hours DS1337.
    Dokładnie bity 7 , 6 i 5 należy "wyzerować " przy odczycie.
  • Pomocny post
    #5 5299768
    don diego
    Poziom 32  
    Bit piąty można zostawić. Jest w nim informacja o AM/PM, którą można odpowiednio spożytkować :)
  • #6 5300041
    JmL(TM)
    Poziom 24  
    No faktycznie z tym maskowaniem to nie pomyslalem ale to sa moje poczatki wiec wybaczcie raczkujacemu :D

    Zmodyfikowalem kod:

    void SetTime(void)
    {
    	//ustaw INTCN i A1IE, zeruj A2IE, wylacz oscylator
    	writeByteI2C(DS1337C, 0x0E, 0x85);
    
    	sbi(czas.godzina, 6);	//ustaw tryb 12h
    	cbi(czas.godzina, 5);	//AM
    
    	writeByteI2C(DS1337C, REG_SEKUNDA, dec2bcd(czas.sekunda));
    	writeByteI2C(DS1337C, REG_MINUTA, dec2bcd(czas.minuta));
    	writeByteI2C(DS1337C, REG_GODZINA, czas.godzina);
    
    	//startuj ponownie oscylator i kasuj status
    	//ustaw INTCN i A1IE, zeruj A2IE, wlacz oscylator
    	writeByteI2C(DS1337C, 0x0E, 0x05);
    
    	//kasuj flagi
    	writeByteI2C(DS1337C, 0x0F, 0x00);
    }


    oraz:

    char	pm;
    
    int main(void)
    {
    	char	ReceivedString[100];
    
    	lcdInit();
    	lcdClear();
    
    	i2c_init();                             // initialize I2C library
    
    	UART_init();
    
    	strcpy(bufor, "oczekiwanie na dane...");
    	lcdPrintData(bufor, strlen(bufor));
    
    	UART_get_str(ReceivedString);
    
    	sscanf(ReceivedString, "%d:%d:%d %d %d-%d-%d", &czas.godzina, &czas.minuta, &czas.sekunda, &data.dzien_tyg, &data.dzien, &data.miesiac, &data.rok);
    
    	SetTime();
    	SetDate();
    
    	while(1)
    	{
    		GetTime();
    		GetDate();
    
    		lcdGotoXY(0,0);
    
    		pm = ((czas.godzina & 0x20) == 0) ? 'A' : 'P';
    
    		cbi(czas.godzina, 7);
    		cbi(czas.godzina, 6);
    		cbi(czas.godzina, 5);
    		cbi(czas.godzina, 4);
    
    		sprintf(bufor, "%.2d:%.2d:%.2d %cM   %.2d-%.2d-20%.2d",	bcd2dec(czas.godzina), bcd2dec(czas.minuta), bcd2dec(czas.sekunda), pm, bcd2dec(data.dzien), bcd2dec(data.miesiac), bcd2dec(data.rok));
    		lcdPrintData(bufor, strlen(bufor));
    
    		switch (data.dzien_tyg)
    		{
    			case 1: strcpy_p(bufor, RTC_DTYG_1); break;
    			case 2: strcpy_p(bufor, RTC_DTYG_2); break;
    			case 3: strcpy_p(bufor, RTC_DTYG_3); break;
    			case 4: strcpy_p(bufor, RTC_DTYG_4); break;
    			case 5: strcpy_p(bufor, RTC_DTYG_5); break;
    			case 6: strcpy_p(bufor, RTC_DTYG_6); break;
    			case 7: strcpy_p(bufor, RTC_DTYG_7); break;
    		}
    
    		lcdGotoXY(0,1);
    		lcdPrintData(bufor, strlen(bufor));
    
    		_delay_ms(1000);
    	}
    
    	return 0;
    }


    I teraz jak przykladowo przez terminal ustawiam godz: 11:59:57 to pozniej wskakuje 04:00:00. Przed wyswietleniem maskuje [tak jak mi powiedzieliscie] starsza czesc bajtu godziny:

    cbi(czas.godzina, 7);
    cbi(czas.godzina, 6);
    cbi(czas.godzina, 5);
    cbi(czas.godzina, 4);


    ale to nic nie zmienia. Wciaz na 24h dziala ok a na 12 nie... :cry:

    W sumie to sobie mysle, ze chyba szybciej zrobilbym to programowo tzn. ustawic zegar na 24h i dzielic godz. przez 2. spr reszte z dzielenia i ustawiac AM/PM. Ale skoro ten RTC ma mozliwosc ustawienia trybu 12h to fajnie byloby to "uruchomic" ;)
  • Pomocny post
    #7 5300091
    don diego
    Poziom 32  
    Bit 4 to dziesiątki godzin, nie powinieneś go maskować.
  • Pomocny post
    #8 5300229
    BoskiDialer
    Poziom 34  
    dzielić przez 2 to chyba nie ma sensu, chyba że chcesz mieć zmianę AM/PM co 60 minut.. prosty warunek if(godzina>=12) { godzina -= 12; pm='P'; } else pm='A'; i juz masz wszystko z głowy.
  • #9 5300326
    JmL(TM)
    Poziom 24  
    BoskiDialer napisał:
    dzielić przez 2 to chyba nie ma sensu, chyba że chcesz mieć zmianę AM/PM co 60 minut.. prosty warunek if(godzina>=12) { godzina -= 12; pm='P'; } else pm='A'; i juz masz wszystko z głowy.


    Heh!

    Wlasnie w tym samym momencie to samo zrobilem... jednak z niewielka roznica:

    if (czas.godzina >= 13)
    {
         czas.godzina -= 12;
         pm = 'P';
    }
    else
         pm = 'A';


    W Twoim przypadku gdy godzina wynosila 12:00 w poludnie zegar pokazywalby 00:00 :D Ale dzieki za odpowiedz. Jak widac programowe rozwiazanie jest banalne jednak z "hardware'm" nie moge sobie poradzic choc na pewno jest rownie proste...
  • Pomocny post
    #10 5300454
    Balu
    Poziom 38  
    Cytat:

    cbi(czas.godzina, 7);
    cbi(czas.godzina, 6);
    cbi(czas.godzina, 5);
    cbi(czas.godzina, 4);

    lepiej tak...
    
    czas.godzina&=0x0f;
    
  • #11 5300900
    JmL(TM)
    Poziom 24  
    Tak wiem Balu ale to bylo tak na szybko i chcialem zeby wszystko bylo widoczne jak u wrozki na dloni :D Ale masz racje optymalizacja ponad wszystko!!!

    Znalazlem przykladowy kod na stronie Dallas'a ale tam jest to zrobione w trybie 24h ale moze ktos sie dopatrzy co ja robie zle bo juz mi rece opadaja...

    Pozdrawiam!
  • #12 5301400
    Balu
    Poziom 38  
    if ((czas.godzina&0x3f)>0x12) czas.godzina-=0x20;

    Imo powinno działać.

    @BoskiDialer i JmL... oba wasze rozwiązania są ok... tylko te rtce są paskudne i wszystkie w BCD podają:P
  • #13 5301760
    BoskiDialer
    Poziom 34  
       czas.godzina   = 12; 
       czas.minuta   = 30; 
       czas.sekunda   = 0;

       czas.sekunda = readByteI2C(DS1337C, REG_SEKUNDA); 
       czas.minuta   = readByteI2C(DS1337C, REG_MINUTA); 
       czas.godzina  = readByteI2C(DS1337C, REG_GODZINA);

    Czyli czas jest zapisany w jednym formacie, raz w drugim. Warto by to poprawić poprzez zamianę bcd na dec zaraz przy odczycie.
    JmL(TM): optymalizacja ponad wszystko, więc masz to (powinno działać):
    
    #define bcd2dec(bcd) ((((bcd)&0xF0) >> 1) + (((bcd)&0xF0) >> 3) + ((bcd)&0x0F))
    
  • #14 5302925
    JmL(TM)
    Poziom 24  
    A widzisz BoskiDialerze jedno spojrzenie w kod, ktory podalem na poczatku i:

    #define bcd2dec(bcd)         (((((bcd) >> 4) & 0x0F) * 10) + ((bcd) & 0x0F))
    #define dec2bcd(dec)         ((((dec) / 10) << 4) | ((dec) % 10))


    mino tego, iz najpierw przypisuje wartosci normalnie jako "pelen" bajt to pozniej konwertuje do BCD:

    czas.godzina   = 12;
    czas.minuta   = 30;
    czas.sekunda   = 0;
    
    ...
    
    void SetTime(void)
    {
       ...
    
       writeByteI2C(DS1337C, REG_SEKUNDA, dec2bcd(czas.sekunda));
       writeByteI2C(DS1337C, REG_MINUTA, dec2bcd(czas.minuta));
       writeByteI2C(DS1337C, REG_GODZINA, czas.godzina);
    
       ...
    }


    co nie zmienia faktu, ze to nadal nie dziala poprawnie. Chcialbym rowniez wziac sie za programowanie alarmow ale zastanawiam sie czy zrobienie tego programowo nie wyjdzie mi na lepsze [czytaj szybciej & latwiej] ;) ale to kolejne rozwiazanie nie godne elektronika!
  • Pomocny post
    #16 5303979
    BoskiDialer
    Poziom 34  
    Nie trzeba próbować aby stwierdzić, że ten kod jest zły. Jeśli godzina jest podawana jako bcd, to już dla 0x13 wynik będzie niepoprawny (0xF3). Najłatwiej jest zamienić na zwykłą liczbę w reprezentacji wewnętrznej.
  • Pomocny post
    #18 5304000
    BoskiDialer
    Poziom 34  
    JmL(TM): a czemu nie zamieniasz godziny na bcd podczas zapisu? wpisanie 0x0C(=12) jako liczby bcd może być różnie potraktowane.

    Dodano po 1 [minuty]:

    Balu: a w tym sensie.. ale to w takim razie to masz to samo co kasowanie tego bitu, a tu nie o to chodzi
  • Pomocny post
    #20 5304045
    BoskiDialer
    Poziom 34  
    Nikt mi nie broni, tylko można to łatwiej rozwiązać. Zastanawiam się teraz nad konsekwencjami wpisywania liczby dec (0x0C) do rejestru bcd - szacuję, że właśnie to jest problemem.. najlepiej było by bezpośrednio przy każdym odczycie i zapisie robić stosowne konwersje żeby nie zapomnieć o tym w dalszej części programu i uniknąć wpisywania owego 0x0C do rejestru godzin.
  • Pomocny post
    #21 5304063
    Balu
    Poziom 38  
    To na bank jest problem. Jeśli gdzieś jest wpisywane 0x0c gdzieś w datasheecie piszą że jest to niedkońca znane działanie układu wtedy (ne wiem czy tego RTC ale w którymś na penwo to było).
  • #22 5304260
    JmL(TM)
    Poziom 24  
    Przy godz. nie zmieniam na BCD poniewaz starsza czesc bitu zawiera informacje o trybie 12/24h wiec jak zamienie na BCD to strace ta starsza czesc bajtu i nie zmienie trybu [chyba, ze zupelnie zle to pojmuje]

    Tutaj jest tabela rejestrow:
    [Mega16] [C] - RTC DS1337C (tryb 12/24h)

    A tu konwersja BCD:

    BCD Excess-3 BCD BCD IBM 1401
    Wagi: 8421 2421 84-2-1 8421
    -------------------------------------------------
    0 0000 0011 0000 0000 1010
    1 0001 0100 0001 0111 0001
    2 0010 0101 0010 0110 0010
    3 0011 0110 0011 0101 0011
    4 0100 0111 0100 0100 0100
    5 0101 1000 1011 1011 0101
    6 0110 1001 1100 1010 0110
    7 0111 1010 1101 1001 0111
    8 1000 1011 1110 1000 1000
    9 1001 1100 1111 1111 1001
  • Pomocny post
    #23 5304273
    Balu
    Poziom 38  
    Źle rozumiesz, jak nie zrobisz konwersji na bcd to wpisujesz do rej 0x02 0x0B(11DEC powiedzmy), a BCD zakłada maxymalnie 0x09 w którymś datasheecie pisało, że wpisując coś takiego robi się syf i nie wiadomo jak będzie działać rtc.
    Weź zrób sobie konwersję na bcd normalnie a potem dodaj na sztywno do starszej tetrady 0x04|0x02 (jesli PM) i masz bcd|12godzinnytryb|AM/PM

    a przy odczycie poprostu na chwilę zamaskuj sobie tamte bity od AM i 12h trybu i zapisz godzine gdzie tam chcesz (przekonwertowaną na dec) i jeszcze raz badając ustaw Sobie flagę AM/PM:)
    Czy jakkkolwiek inaczej ale biorąc po uwagę te rzeczy.

    Dodano po 1 [minuty]:

    Ah używasz BCD z tego pierwszego słupka konwersji :)
  • Pomocny post
    #24 5304305
    BoskiDialer
    Poziom 34  
    void SetTime(void) 
    { 
    (...)
       unsigned char __godzina = dec2bcd(czas.godzina);
       __godzina |= (1 << 6);         //ustaw tryb 12h
    
       writeByteI2C(DS1337C, REG_SEKUNDA, dec2bcd(czas.sekunda)); 
       writeByteI2C(DS1337C, REG_MINUTA, dec2bcd(czas.minuta)); 
       writeByteI2C(DS1337C, REG_GODZINA, __godzina);
    (...)
    }
    
    void GetTime(void) 
    { 
       czas.sekunda = bcd2dec(readByteI2C(DS1337C, REG_SEKUNDA)); 
       czas.minuta   = bcd2dec(readByteI2C(DS1337C, REG_MINUTA));
       
       unsigned char __godzina = readByteI2C(DS1337C, REG_GODZINA);
       czas.godzina  = bcd2dec(__godzina & 0x1F);
       if(__godzina & 0x20)
          pm = 'P';
       else
          pm = 'A';
    }

    Coś tego rodzaju powinno działać. Późna godzina więc nie sprawdzałem jak bardzo pewnie to będzie działać.
  • #26 5304326
    JmL(TM)
    Poziom 24  
    Balu zrobilem dokladnie tak jak napisales i... mam ustawiony tryb 12h!!!!! Jestes wielki!!!!! W koncu po tak dlugich meczarniach mam tryb 12h :D

    DZiEKUJE ZA POMOC BoskiemuDialerowi a w szczegolnosci OGROMNE PODZIEKOWANIA dla BALU!!!!!
  • #28 5305057
    JmL(TM)
    Poziom 24  
    Musialem z tym zaczekac do rana bo niestety wczoraj w nocy .NET mi padl :| Mam nadzieje, ze ktos to spozytkuje...

    #define DS1337C				0xD0	//1101 0000B   - adres hardware'owy zegara DS1337C
    
    #define bcd2dec(bcd)			(((((bcd) >> 4) & 0x0F) * 10) + ((bcd) & 0x0F))
    #define dec2bcd(dec)			((((dec) / 10) << 4) | ((dec) % 10))
    
    //---------------------
    // Adresy w DS1337
    //---------------------
    #define REG_SEKUNDA			0x00
    #define REG_MINUTA			0x01
    #define REG_GODZINA			0x02
    
    #define SUB_REG_GODZINA_PM		0x20
    
    #define	REG_DZIEN_TYG			0x03
    
    #define REG_DZIEN			0x04
    #define REG_MIESIAC			0x05
    #define REG_ROK				0x06
    
    #define REG_ALARM1_SEKUNDA		0x07
    #define REG_ALARM1_MINUTA		0x08
    #define REG_ALARM1_GODZINA		0x09
    
    #define REG_ALARM1_DZIEN_TYG		0x0A
    #define REG_ALARM1_DZIEN		0x0B
    
    #define	MAX_SIZE			0x1E
    
    prog_char dni_po[] = "Poniedzialek";
    prog_char dni_wt[] = "Wtorek      ";
    prog_char dni_sr[] = "Sroda       ";
    prog_char dni_cz[] = "Czwartek    ";
    prog_char dni_pt[] = "Piatek      ";
    prog_char dni_so[] = "Sobota      ";
    prog_char dni_ni[] = "Niedziela   "; 
    
    prog_char* dni_tyg[7] = {
       dni_po, dni_wt, dni_sr, dni_cz, dni_pt, dni_so, dni_ni
    };
    //*======================================================================*//
    
    char bufor[MAX_SIZE];
    
    typedef struct {
    	u08	godzina;
    	u08	minuta;
    	u08	sekunda;
    
    	u08 pm;
    } strCzas;
    
    typedef struct {
    	u08	dzien_tyg;
    
    	u08	dzien;
    	u08	miesiac;
    	u08	rok;
    } strData;
    
    strCzas	czas;
    strData	data;
    
    char	pm;
    
    //*======================================================================*//
    void SetTime(void)
    {
    	u08	godz_bcd = dec2bcd(czas.godzina);
    
    	godz_bcd |= (1 << 6); //ustaw tryb 12h 
    
    	if (czas.pm)
    		godz_bcd |= (1 << 5); //ustaw PM
    
    	//ustaw INTCN i A1IE, zeruj A2IE, wylacz oscylator
    	writeByteI2C(DS1337C, 0x0E, 0x85);
    
    	writeByteI2C(DS1337C, REG_SEKUNDA, dec2bcd(czas.sekunda));
    	writeByteI2C(DS1337C, REG_MINUTA, dec2bcd(czas.minuta));
    	writeByteI2C(DS1337C, REG_GODZINA, godz_bcd);
    
    	//startuj ponownie oscylator i kasuj status
    	//ustaw INTCN i A1IE, zeruj A2IE, wlacz oscylator
    	writeByteI2C(DS1337C, 0x0E, 0x05);
    
    	//kasuj flagi
    	writeByteI2C(DS1337C, 0x0F, 0x00);
    }
    //*======================================================================*//
    
    void SetDate(void)
    {
    	writeByteI2C(DS1337C, REG_DZIEN_TYG, dec2bcd(data.dzien_tyg));
    
    	writeByteI2C(DS1337C, REG_DZIEN, dec2bcd(data.dzien));
    	writeByteI2C(DS1337C, REG_MIESIAC, dec2bcd(data.miesiac));
    	writeByteI2C(DS1337C, REG_ROK, dec2bcd(data.rok));
    }
    //*======================================================================*//
    
    void GetTime(void)
    {
    	czas.sekunda = bcd2dec(readByteI2C(DS1337C, REG_SEKUNDA));
    	czas.minuta = bcd2dec(readByteI2C(DS1337C, REG_MINUTA));
    
    	u08 godzina_bcd = readByteI2C(DS1337C, REG_GODZINA);
    	czas.godzina = bcd2dec(godzina_bcd & 0x1F);
    
    	pm = (godzina_bcd & 0x20) ? 'p' : 'a';
    }
    //*======================================================================*//
    
    void GetDate(void)
    {
    	data.dzien_tyg = readByteI2C(DS1337C, REG_DZIEN_TYG);
    
    	data.dzien = bcd2dec(readByteI2C(DS1337C, REG_DZIEN));
    	data.miesiac = bcd2dec(readByteI2C(DS1337C, REG_MIESIAC));
    	data.rok = bcd2dec(readByteI2C(DS1337C, REG_ROK));
    }
    //*======================================================================*//
    
    int main(void)
    {
    	lcdInit();
    	lcdClear();
    
    	SetTime(); // ustawiamy czas
    	SetDate(); // -II- date
    
    	while(1)
    	{
    		GetTime();
    		GetDate();
    
    		lcdGotoXY(0, 0);
    
    		sprintf(bufor, "%.2d:%.2d:%.2d%cm   %.2d-%.2d-20%.2d", czas.godzina, czas.minuta, czas.sekunda, pm, data.dzien, data.miesiac, data.rok);
    		lcdPrintData(bufor, strlen(bufor));
    
    		lcdGotoXY(0, 1);
    
    		strcpy_p(bufor, dni_tyg[data.dzien_tyg - 1]);
    		lcdPrintData(bufor, strlen(bufor));
    
    		_delay_ms(1000);
    	}
    
    	return 0;
    }


    I tu jeszcze raz wielkie podziekowania dla was chlopaki za pomoc :please:. Wiele sie nauczylem siedzac nad tym zegarkiem [w koncu dopiero raczkuje w uC]. W czasie pisania odpowiedzi nie widzialem, ze BoskiDialer rowniez odpowiedzial w tym samym czasie i dodal kod [oczywiscie poprawny :D] wiec teraz uwzglednilem to w programie i dziala dokladnie tak jak chcialem! 8)




    Dodam jeszcze schemat wyprowadzen wersji 'C' i przykladowy schemat [w wersji 'C' bez kwarcu]

    [Mega16] [C] - RTC DS1337C (tryb 12/24h)

    [Mega16] [C] - RTC DS1337C (tryb 12/24h)

    I teraz temat chyba wyczerpany choc ciagle chodzi mi po glowie ten fragment kodu:

    #define RTC_DTYG_1   PSTR("Poniedzialek")
    #define RTC_DTYG_2   PSTR("Wtorek      ")
    #define RTC_DTYG_3   PSTR("Sroda       ")
    #define RTC_DTYG_4   PSTR("Czwartek    ")
    #define RTC_DTYG_5   PSTR("Piatek      ")
    #define RTC_DTYG_6   PSTR("Sobota      ")
    #define RTC_DTYG_7   PSTR("Niedziela   ") 
    
    switch (data.dzien_tyg)
    {
       case 1: strcpy_p(bufor, RTC_DTYG_1); break;
       case 2: strcpy_p(bufor, RTC_DTYG_2); break;
       case 3: strcpy_p(bufor, RTC_DTYG_3); break;
       case 4: strcpy_p(bufor, RTC_DTYG_4); break;
       case 5: strcpy_p(bufor, RTC_DTYG_5); break;
       case 6: strcpy_p(bufor, RTC_DTYG_6); break;
       case 7: strcpy_p(bufor, RTC_DTYG_7); break;
    }


    Czy nie mozna tego napisac w jakis bardziej "poetycki" sposob? Mam na mysli bardziej elegancki np. w petli :D
  • #29 5305851
    BoskiDialer
    Poziom 34  
    Niepokoi mnie nadmiarowa konwersja bcd2dec - przy odczycie godzina jest zamieniana na dec, więc później już nie ma potrzeby. Akurat w tym przypadku nic się nie powinno stać (górny nibble jest zawsze równy zero), to po po co obciążać procek dodatkowymi obliczeniami oraz narażać się na błędy przy zmianie trybu na 24 godziny.. wszystkie konwersje najlepiej robić przy odczycie..

    Dodano po 23 [minuty]:

    #include <avr/pgmspace.h>
    
    prog_char dni_po[] = "Poniedzialek";
    prog_char dni_wt[] = "Wtorek      ";
    prog_char dni_sr[] = "Sroda       ";
    prog_char dni_cz[] = "Czwartek    ";
    prog_char dni_pt[] = "Piatek      ";
    prog_char dni_so[] = "Sobota      ";
    prog_char dni_ni[] = "Niedziela   ";
    
    prog_char* dnityg[7] = {
    	dni_po, dni_wt, dni_sr, dni_cz, dni_pt, dni_so, dni_ni
    };
    
    
     strcpy_p(bufor, dnityg[data.dzien_tyg-1]);
    

    Powinno działać. Tablica wskaźników na ciągi znaków w pamięci programu, a później tylko indeksowanie komórek tablicy..
  • #30 5306318
    JmL(TM)
    Poziom 24  
    I dziala mistrzu! Poprawki uwzglednilem w poprzednim listingu zeby nie robic smietnika. Konwersje z BCD na DEC rowniez zrobilem przy odczycie.

    Tematu nie zamykam bo pewnie jeszcze jakas poprawka bedzie... :D
REKLAMA