DS1307 to bardzo dobry i tani zegar czasu rzeczywistego. Posiada swój własny kwarc oraz baterię niezależną od pozostałych części naszego urządzenia, dzięki czemu jest niezależny i działa zawsze, nawet w przypadku awarii nadrzędnego procesora. Układ ma także kalendarz z obsługą lat przestępnych i jest bardzo prosty w obsłudze - działa na magistrali I2C, która jest wspierana sprzętowo przez mikrokontrolery AVR. DS1307 umożliwia także wygenerowanie sygnału prostokątnego o częstotliwości 1Hz, 4kHz, 8kHz, 32kHz.
Układ DS1307 wykorzystuje tani i łatwo dostępny rezonator kwarcowy 32kHz. Należy go podłączyć do wejść X1 i X2 bez dodatkowych kondensatorów. Zaleca się położyć ten kwarc w pozycji poziomej i jego obudowę połączyć z masą układu. Do zasilania awaryjnego można wykorzystać popularną baterię CR2023 podłączoną do nóżki VBAT, która wystarczy na kilka lat. W przypadku kiedy układ nie ma baterii, wejście VBAT należy podłączyć do masy, bo w przeciwnym razie DS1307 nie będzie działać. Wyjścia SDA, SCL i SQW są wyjściami z otwartym kolektorem, więc należy zastosować odpowiednie rezystory podciągające, typowo 4,7k.
Przykładowy schemat DS1307
Zapis do DS1307
Nie będę tutaj omawiał tajników komunikacji przez I2C, a jedynie samą procedurę zapisu. Na początek zobaczmy mapę pamięci RAM tego układu, która ma 64 bajty. Jak widać wykorzystywane jest tylko 8 bajtów, a resztę możemy sobie wykorzystać do własnych celów.
Koniecznie należy zwrócić uwagę na to, że DS1307 zapisuje liczby w postaci BCD a nie binarnej! Czyli w jednym bajcie zapisywane są dwie cyfry - pierwsza na bitach od 0 do 3, a druga cyfra jest zapisana w bitach od 4 do 7.
Procedura zapisu godziny do pamięci wygląda w ten sposób:
- Zainicjalizuj I2C (chyba, że już wcześniej zostało zainicjalizowane)
- Wyślij sygnał START
- Wyślij adres zapisu 208 - to adres DS1307 na magistrali I2C
- Wyślij adres pierwszego bajtu, który będzie zapisywany. Najczęściej zapisujemy całą pamięć od początku, czyli od zera.
- Wyślij sekundy
- Wyślij minuty
- Wyślij godziny - bit 6 decyduje czy zapisujemy godzinę w formacie 24h czy 12h. Jeżeli bit 6 jest ustawiony, to bit 5 decyduje czy mamy czas przed południem AM, czy po południu PM. Aby było "po naszemu", nie zawracamy sobie głowy bitem 6 i wpisujemy godziny tak samo jak minuty i sekundy.
- Wyślij dzień tygodnia - ważne: niedziela oznaczona jest przez 1, poniedziałek przez 2, wtorek przez 3...
- Wyślij dzień miesiąca
- Wyślij miesiąc
- Wyślij dwie ostatnie cyfry roku
- Wyślij bajt konfiguracyjny (jeśli trzeba)
- Dalsze komórki pamięci RAM można wypełnić swoimi danymi
- Wyślij sygnał STOP
Bajt konfiguracyjny decyduje o roli wyjścia SQW. Aby uruchomić wyjście generatora, należy bit SQWE ustawić na 1, a bity RS0 i RS1 ustawić wg poniższej tabelki. Jeżeli nie chcemy włączyć generatora, bo bierze on dodatkowy prąd z baterii, ustawiamy go na 0, a wtedy możemy sterować stanem wyjścia SQW poprzez bit OUT. Szczegóły wyjaśnia tabela poniżej.
Przykład funkcji, która zapisuje godzinę do DS1307:
void ds1307_write(uint8 h, uint8 m, uint8 dd, uint8 mm, uint8 yy, uint8 dt) { // dt to dzień tygodnia (poniedziałek=2) i2c_init(100); // częstotliwość SCL 100kHz i2c_start(); i2c_write(208); // adres DS1307 if(TWSR != 0x18) { // sprawdzanie czy DS1307 odpowiada t("zegar nie odpowiada"); return 0; } i2c_write(0); // zapis od poczatku pamieci // sekundy i2c_write(0); // minuty i2c_write(((m/10)<<4)+(m%10)); // godziny i2c_write(((h/10)<<4)+(h%10)); // dzień tygodnia i2c_write(dt); // dzień i2c_write(((dd/10)<<4)+(dd%10)); // miesiąc i2c_write(((mm/10)<<4)+(mm%10)); // rok i2c_write(((yy/10)<<4)+(yy%10)); i2c_stop(); return; }
Odczyt z DS1307
Jak to zwykle bywa w układach I2C, najpierw należy zapisać adres, od którego będziemy odczytywać pamięć, zresetować transmisję i dopiero potem odczytywać dane.
- Zainicjalizuj I2C (chyba, że już wcześniej zostało zainicjalizowane)
- Wyślij sygnał START
- Wyślij adres zapisu 208 - to adres DS1307 na magistrali I2C
- Wyślij adres pierwszego bajtu, od którego będziemy odczytywać pamięć. Najczęściej odczytujemy całą pamięć od początku, czyli od zera.
- Wyślij ponownie sygnał START
- Wyślij adres odczytu 209
- Odczytuj po kolei wszystkie komórki pamięci
- Przy odczytywaniu ostatniej komórki nie należy wysyłać sygnały potwierdzenia
- Wyślij sygnał STOP
Przykład funkcji odczytującej godzinę i datę z DS1307:
void ds1307_read(void) { uint8_t sek, min, godz, dztyg, dzien, mies, rok; i2c_init(100); i2c_start(); i2c_write(208); // adres zapisu DS1307 if(TWSR != 0x18) { // sprawdzanie czy DS1307 odpowiada t("zegar nie odpowiada"); return; } i2c_write(0); i2c_start(); i2c_write(209); // adres odczytu DS1307 sek = i2c_read(); min = i2c_read(); godz = i2c_read(); dztyg = i2c_read(); dzien = i2c_read(); mies = i2c_read(); rok = i2c_read_nack(); i2c_stop(); // wszystkie zmienne przechowują wartości w kodzie BCD // jeżeli w programie masz gdzieś funkcje wyświetlającą liczbę // szesnastkową, to możesz ją tutaj wykorzystać out_hex(godz); t(":"); out_hex(min); t(":"); out_hex(sek); t(" "); out_hex(dzien); t("."); out_hex(mies); t(".20"); out_hex(rok); t(" "); switch(dztyg) { case 1: t("nd"); break; case 2: t("pn"); break; case 3: t("wt"); break; case 4: t("sr"); break; case 5: t("cz"); break; case 6: t("pt"); break; case 7: t("sb"); break; } return; }
2 komentarze :
Mógłbyś podać linka do biblioteki i2c którą wykorzystałeś ?
W dużej mierze są to funkcje skopiowane prosto z dokumentacji Atmela. Szukaj w rozdziale o TWI (to podróbka I2C ale działa tak samo)
Prześlij komentarz
Skomentuj!