DS1307 zegar czasu rzeczywistego (RTC)
… o niskim poborze mocy, pełne dziesiętne kodowane binarne (BCD) zegar / kalendarz oraz 56 bajtów NV SRAM. Adres i dane przesyłane są szeregowo przez dwukierunkową magistralę I²C. Zegar / kalendarz zapewnia obsługę sekund, minut, godzin, dnia tygodnia, dnia miesiąca, miesięcy i informacje o latach, zaprojektowany do 2100. Ostatni dzień, miesiąca jest automatycznie dostosowywany do miesięcy krótszych niż 31 dni, łącznie z korektami dla lat przestępnych. Zegar działa zarówno w trybie 24-godzinnym lub 12-godzinnym ze wskaźnikiem AM / PM. DS1307 posiada wbudowany układ power-sense, który wykrywa przerwy zasilania głównego i automatycznie przełącza się na zasilanie zapasowe. Obsługa pomiaru czasu w dalszym ciągu funkcjonuje z zasilania zapasowego. Działając z podtrzymania bateryjnego, programowalny prostokątny sygnał wyjściowy, zużywa mniej niż 500nA w trybie rezerwowym przy uruchomionym oscylatorze. Zakres temperatur: -40°C do +85°C. SCL Clock Frequency 100 kHz.
Supply Voltage VCC min 4.5 typowo 5.0 max 5.5V
Battery Voltage VBAT min 2.0 typowo 3 max 3.5 V
Bardzo istotny jest dobry kondensator blokujący blisko pinów zasilania głównego USC, oraz odpowiednia mozaika PCB koło pinów rezonatora.
Układ posiada jedno wyjście programowalne SQW/OUT, na którym może generować jedną z czterech częstotliwości przebiegu prostokątnego 1Hz, 4kHz, 8kHz, 32kHz. Aby uaktywnić tą funkcjonalność bit SQWE ustawiamy na 1. Wyjście jest typu otwarty dren i wymaga zewnętrznego rezystora pullup. Napięcie pullup może wynosić do 5,5 V, niezależnie od napięcia na VCC. Jeśli nie używany tej funkcjonalności, to można pozostawić ten pin jako „pływający”. SQW / OUT działa zarówno z VCC jak i VBAT.
Dla przypomnienia:
gdy VCC spadnie poniżej 1,25 x VBAT, układ w trakcie pracy przerywa dostęp i resetuje licznik adresowy. Operacje wejściowe do urządzenia w tym momencie nie są rozpoznawane, aby uniknąć błędnych danych zapisywanych na urządzeniu z nieprawidłowymi poziomami logicznymi. Gdy VCC spadnie poniżej VBAT, układ przełącza się w tryb niskiego poboru mocy z zasilaniem rezerwowym z baterii . W momencie włączenia zasilania, gdy napięcie VCC +0,2V jest większe niż VBAT urządzenie przełącza się z akumulatora do VCC, oraz załącza obsługę wejść kiedy VCC jest większa niż 1,25 x VBAT.
Precyzja zegara jest zależna od dokładności kryształu i kompatybilności pomiędzy obciążeniem pojemnościowym układu oscylatora i pojemnościowego obciążenia dla którego kwarc został zaprojektowany.
Dodatkowy błąd będzie generowany pływaniem częstotliwości, spowodowanym zmianami temperatury kwarcu. Szum zewnętrznego obwodu w połączeniu z obwodem oscylatora może powodować spieszenie zegara.
Czyli warto wyizolować układ zegara, jeśli to możliwe albo go ekranować.
Opiszę króciutko mapę adresową RTC DS1307 i rejestrów RAM. Rejestry RTC są pod adresami: 00h do 07h, a rejestry RAM 08h do 3FH. Podczas wielobajtowego dostępu, gdy wskaźnik osiągnie adres 3FH (koniec przestrzeni RAM), zostanie przekierowany na początek przestrzeni adresowej do 00h (zegar).
Czas i kalendarz są ustawiane lub inicjowane przez zapis odpowiednich bajtów rejestru. Czas i kalendarz w rejestrach są zapisywane w formacie BCD. Przyrosty dzień tydzień rejestrowane są o północy. Wartości, które odpowiadają poszczególnym dniom tygodnia są definiowane przez użytkownika, ale muszą to być wartości następujące po sobie (tj. jeżeli 1 jest równe Niedziela, następnie 2 równe Poniedziałek, i tak dalej). Bit 7 rejestru 0 służy do zatrzymania zegara (CH bit). Kiedy ten bit jest ustawiony na 1, oscylator jest wyłączony. Po skasowaniu (wpisaniu 0), oscylator jest włączony. Przy pierwszym włączeniu zasilania urządzenie rejestruje godziny i daty są zwykle ustawiane na 01/01/00 01 00:00:00 (MM / DD / RR DOW HH: MM: SS). Bit CH w rejestrze sekund zostanie ustawiony na 1. Zegar może zostać zatrzymany, gdy nie jest wymagane rejestrowanie czasu, spowoduje to mniejsze zużycie prądu (IBATDR).
DS1307 może pracować w trybie 12-godzinnym lub w trybie 24-godzinnym. Bit 6 rejestru godzin definiuje ten tryb pracy (mode-select-bit). Gdy ma stan wysoki, wybrany jest tryb 12-godzinny. W trybie 12-godzinnym, bit 5 jest znacznikiem AM / PM z logicznym przełącznikiem PM. W trybie 24-godzinnym, bit 5 jest bitem „dwudziestek” godzin (20 do 23 godzina). Gdy bit trybu 12/24-hour ulega zmianie, wartość godziny musi być wprowadzona ponownie. W trakcie powtórnych odczytów lub zapisów rejestrów czasu i daty przez użytkownika, są wykorzystywane bufory celem uniknięcia błędów podczas automatycznej aktualizacji rejestrów wewnętrznych. Podczas operacji odczytu, bufory użytkownika są zsynchronizowane do wewnętrznych rejestrów przy każdej operacji START I2C. Informacja o czasie jest czytana z tych właśnie rejestrów wtórnych podczas kiedy zegar kontynuuje pracę.
Każdy transfer zapisu występujący na I2C jest potwierdzany przez DS1307. Ilekroć rejestr sekund jest zapisywany dzielnik łańcucha licznika czasu zostanie zresetowany. Kiedy dzielnik łańcucha zostanie zresetowany aby uniknąć problemów z rollover, pozostałe rejestry czasu i daty muszą być zapisane w ciągu jednej sekundy.
Rejestry zegara:
Rejestr sterujący DS1307 służy do konfiguracji wyjścia SQW OUT.
Bit 7: Output Control (OUT).
Za jego pośrednictwem mamy możliwość ustawienia poziomu logicznego stanu spoczynkowego pinu gdy nie korzystamy z funkcjonalności generatora przebiegu prostokątnego. I tak jeśli bit konfiguracyjny OUT = 1 pin SQW/OUT jest w stanie wysokim i jeżeli bit OUT = 0 wyjście jest w tanie niskim.
Bit 4: Square-Wave Enable (SQWE).
Gdy bit ten = 1, załącza wyjście oscylatora. Częstotliwość wyjściowego sygnału prostokątnego zależy od wartości bitów RS0 i RS1. Kiedy częstotliwość na wyjściu jest ustawiona na 1 Hz, rejestr zegara aktualizuje przebieg prostokątny na opadającym zboczu. Konfiguracja bitu po załączeniu zasilania = 0.
Bits 1 and 0: Rate Select (RS[1:0]).
Bity kontrolują częstotliwość przebiegu prostokątnego na wyjściu, gdy wyjście zostało aktywowane. Przy początkowym włączeniu zasilania, bity te są zazwyczaj ustawione na 1.
Adres sprzętowy układu RTC
1 2 |
Const Ds1307w = &HD0 ' Adres DS 1307 Write Const Ds1307r = &HD1 ' Adres DS 1307 Read |
Układ nie jest skomplikowany w obsłudze a dodatkowo całą sprawę upraszczają możliwości BASCOM AVR. Poniżej kawałek programu gdzie zapoznawałem się z obsługą zegara RTC. Widoczne są również funkcje zbędne dla działania obsługi zegara.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
$regfile = "m8adef.dat" $crystal = 1000000 $lib "I2C_TWI.LBX" 'oszczędzamy kod załączamy sprzętowe TWI ;-) '$lib "ds1307clock.lib" $hwstack = 128 ' w tym kawałku nie jest niezbędne $swstack = 128 $framesize = 128 Config Submode = New 'nowy tryb deklaracji procedur Config Sda = Portc.4 Config Scl = Portc.5 Config 1wire = Portb.1 ' DS18b20 Config Portb.0 = 1 'status LED 'Config Adc = Single , Prescaler = Auto , Reference = Avcc ' przetwornik A/C Config Clock = User ' this will dim the bytes automatic Config Date = Ymd , Separator = Minus 'konfigurujemy format daty - kolejność wyświetlania danych y - rok, m - miesiąc, d - dzień 'oraz znak oddzielający poszczególne wartości (można użyć . [kropki], , [przecinka], / [ukośnika] lub - [myślnika]) Const Ds1307w = &HD0 ' Adres DS 1307 Write Const Ds1307r = &HD1 ' Adres DS 1307 Read 'Time$ = "23:02:00" ' ustawiamy godzinę 'Date$ = "14-07-27" ' ustawiamy Datę Dim Weekday As Byte , Dzientyg As String * 2 ' uzupełnienie datoczasowych Dim Old_sek As Byte , Czas As String * 8 Dim Sys_sec As Long , W As Byte '31%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% $baud = 9600 'Echo Off Print "puk puk ;-)" Do Waitms 100 Czas = Time$ If Old_sek <> _sec Then Old_sek = _sec Toggle Portb.0 ' Decr Weekday Dzientyg = Lookupstr(weekday , Weekstrdays) Print Time$ ; " " ; Dzientyg ; " 20" ; Date$ Print "syssec " ; Syssec() ; " sec of day " ; Secofday() Print ; "Sysday " ; Sysday() ; " Dayofyear " ; Dayofyear() End If Input "nastawiamy -> y? " , Czas If Czas = "y" Then Input "dzien ->" , _day Input "miesiac ->" , _month 'Noecho Input "rok ->" , _year Input "godzina ->" , _hour Input "minuty ->" , _min Gosub Setdate Gosub Settime Print Dzientyg ; " 20" ; _year ; "-" ; _month ; "-" ; _day ; " " ; _hour ; ":" ; _min ; "." ; _sec End If Loop End ' @@@@@@@@@@@@@@@@@@@@@@@@@@@ ZEGAR @@@@@@@@@@@@@@@@@@@@@@@@@@@@ Getdatetime: I2cstart ' start magistrali I2cwbyte Ds1307w ' wysłanie adresu RTC do zapisu I2cwbyte 0 ' adres rejestru I2crepstart ' Generate start code I2cwbyte Ds1307r ' wysłanie adresu RTC do odczytu I2crbyte _sec , Ack ' odczyt SECONDS I2crbyte _min , Ack ' MINUTES I2crbyte _hour , Ack ' HOURS I2crbyte Weekday , Ack ' DAY OF WEEK I2crbyte _day , Ack ' DAY OF MONTH I2crbyte _month , Ack ' MONTH I2crbyte _year , Nack ' YEAR I2cstop Gosub Smh_dec ' przywrócenie zmienntym nornalnych wartości Gosub Dmy_dec If Weekday = 1 Then 'dopasowanie zakresu do potrzeb programu i zakresu RTC Weekday = 6 Else Weekday = Weekday - 2 End If Dzientyg = Lookupstr(weekday , Weekstrdays) Return Setdate: Weekday = Dayofweek() 'automatyczne wyliczenie dnia tygodnia 'zwracana wartość z zakresu 0 do 6 , gdzie poniedziałek = 0. 'Funkcja jest prawidłowa dla 21 wieku (od 2000-01-01 do 2099-12-31). 'w RTC zakres 1 do 7, gdzie 1 to niedziela, 2 poniedziałek ... If Weekday = 6 Then 'dopasowanie zakresu do potrzeb programu i zakresu RTC Weekday = 1 Else Weekday = Weekday + 2 End If _day = Makebcd(_day) : _month = Makebcd(_month) : _year = Makebcd(_year) I2cstart ' start magistrali I2cwbyte Ds1307w ' wysłanie adresu RTC do zapisu I2cwbyte 3 ' adres rejestru I2cwbyte Weekday ' wysyłamy dane DAYS OF WEEK I2cwbyte _day ' DAYS I2cwbyte _month ' MONTHS I2cwbyte _year ' YEARS I2cstop Gosub Dmy_dec ' przywrócenie zmienntym nornalnych wartości ' Dzientyg = Lookupstr(weekday , Weekstrdays) Return Settime: '_sec = 0 : _min = Makebcd(_min) : _hour = Makebcd(_hour) I2cstart ' start magistrali I2cwbyte Ds1307w ' wysłanie adresu RTC do zapisu I2cwbyte 0 ' adres rejestru I2cwbyte 0 ' wysyłamy dane SECONDS I2cwbyte _min ' MINUTES I2cwbyte _hour ' HOURS I2cstop Gosub Smh_dec ' przywrócenie zmienntym nornalnych wartości Return Dmy_dec: _day = Makedec(_day) : _month = Makedec(_month) : _year = Makedec(_year) Return Smh_dec: _sec = Makedec(_sec) : _min = Makedec(_min) : _hour = Makedec(_hour) Return Weekstrdays: Data "Pn" , "Wt" , "Sr" , "Cz" , "Pt" , "So" , "Nd" |
Trochę się „bawiłem”, efekt jest wyśmienity. Na samym początku testów dołączyłem bibliotekę
1 |
$lib ds1307clock.lib |
nie potrafiłem znaleźć o niej żadnych informacji. Nie działała mi również konfiguracja
1 |
Config Date = Ymd , Separator = Minus |
Dopiero po odłączeniu tej biblioteki wspomniana funkcjonalność działa jak należy. Użycie dyrektywy Config Clock = User odwala cała robotę z obsługą zmiennych powiązanych z domierzaniem czasu (zarówno zegar jak i kalendarz). Należy jedynie zadbać o dopisanie procedur odpowiedzialnych za zapis i odczyt danych z układu scalonego RTC. Reszta dzieje się samodzielnie, podczas używania funkcji Date$ Time$. Dane są wtedy „automatycznie” zapisywane lub odczytywanie z IC. Wszystkie lata przestępne i długości miesięcy pilnowane są przez układ – o czym pisałem już wcześniej. Możliwości te czynią tą konstrukcję bardzo wygodną w użyciu. Niestety automatyzacja obsługi generuje „trochę” kodu. Nie napotkałem problemów podczas uruchamiania układu. Będę chciał uruchomić funkcjonalność generatora przebiegu prostokątnego aby korzystać z takiej możliwości w układzie bez zajmowania timerów odmierzaniem czasu.
Dodatkowe informacje o funkcjonalności Config Clock = User można zdobyć przeglądając mój artykuł Real Time Counter prawie jak RTC
Witam odpalałem DS1337 to prawie to samo.
Niestety akurat na ATmega328p taktowaną 16MHz – i tu pomogło „Config Twi = 100000” (przy hardwarowym twi $lib „I2C_TWI.LBX”) czyli 100kHz sprawdzałem oscylkiem bez tego clk był okolo 900 paru kHz hihi… Jeszcze nie bawiłem się na 400kHz. Software czyli $forcesofti2c : $lib „i2c.lbx” działało od razu (clock oscylkiem było około 45kHz to co tu się dziwić)
to mnie dopiero nakierowało, że tu coś za szybko leci zamiast od razu oscyloskopem sprawdzić no trudno ech (hihi oczywistych rzeczy się nie sprawdza) pozdrowienia serdeczne!
Witam uprzejmie.
Wiem jedno, z Twojego opisu emanuje mnustwo szczęścia (euforii). Ale chyba … chyba zapomniałeś o przekazie jaki miał nieść – czym się chciałeś podzielić. Treść jest na tyle skrótowa, że nie do końca rozumiem w czym rzecz.
Na ewentualne perypetie z obsługą magistrali TWI mogę polecić abyś zapoznał się z opisem moich doświadczeń:
I²C TWI – jak kaktus „dawał po garach” ;-D
Pozdrawiam serdecznie i życzę wielu udanych projektów.
ps.
Co do $forcesofti2c polecę Ci zapoznanie się z opisem tej dyrektywy na witrynie MCS.
jest tam między innymi taka wzmianka:
The $forcesofti2c directive force the ATXMEGA to use software I2C/TWI Library instead of the hardware I2C registers of ATXMEGA.
Masz rację zapomniałem o przekazie… dzięki Tobie odgrzałem stare zabawki, za co dzięki wielkie!
Mam nadzieję, że ta super stronka będzie z nami zawsze Pozdrawiam serdecznie.
A teraz ja podziękuję za ciepłe słowo.
Ostatnimi czasy pochłonął mnie jeden projekt, no i nie ukrywam kondycja „psychofizyczna” poleciała na ryjek …
O projekcie pewno niebawem będzie „głośno” na zielonej 😉
A witrynki nie odpuszczę, choć by się waliło, paliło itp.