Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

PCF8583 - pełna obsługa daty i godziny

Villen 26 Apr 2011 17:30 16115 68
Optex
  • #31
    007mirek
    Level 11  
    tak używam tego

    u8 bin2bcd(u8 bin)
    {
    u8 a;
    a=(((bin/10)<<4)|(bin%10));

    return (a);
    }

    u8 bcd2bin(u8 bcd)
    {
    u8 a;
    a=((bcd>>4)*10|(bcd&0x0f));

    return (a);

    co ciekawe liczy mi czas tylko np. 00:00 upłynie 1 min i jest 00:20 pozniej 00:40 itd.
  • Optex
  • #32
    michalko12
    MCUs specialist
    bin = ((bcd>>4)*10|(bcd&0x0f));

    BCD -> 22
    Bin -> 0x16

    (22 >> 4)*10 | ( 22 & 0x0f)=
    (2*10) | 2=
    20 | 2=
    0x14 | 2 = 0x16 czyli 22
    OK

    BCD -> 15
    Bin -> 0xF

    (15 >> 4) *10 | (15 & 0x0f) =
    (1*10) | 5 =
    0xA | 5 = 0xF czyli 15
    OK


    BCD -> 19
    Bin -> 0x13

    (19 >> 4) *10 | (19 & 0x0f) =
    (1*10) | 9 =
    0xA | 9 = 0xB czyli 11
    Ups! error....
  • #33
    007mirek
    Level 11  
    Czyli procedura konwertowania z bin2bcd oraz bcd2bin jest błędna, może ktoś podpowie jak powinna wyglądać prawidłowa

    Z góry dziękuje
  • Optex
  • #35
    michalko12
    MCUs specialist
    007mirek wrote:
    Czyli procedura konwertowania z bin2bcd oraz bcd2bin jest błędna, może ktoś podpowie jak powinna wyglądać prawidłowa

    Z góry dziękuje


    No wiesz co? Dostałeś odpowiedź na talerzu, ale tu chyba trzeba jeszcze cię nakarmić 8-O

    (19 >> 4) *10 | (19 & 0x0f) =
    (1*10) | 9 =
    0xA | 9 = 0xB czyli 11
    Ups! error....

    (19 >> 4) *10 + (19 & 0x0f) =
    (1*10) + 9 =
    0xA + 9 = 0x13 czyli 19
    OK
  • #36
    007mirek
    Level 11  
    Dzięki to też już próbowałem kiedyś i dalej to samo.
    odczytuje z PCF (BCD) 128 przerabia na (BIN) 80 i mam minutu lub
    odczytuje z PCF (BCD) 224 przerabia na (BIN) 140 i mam minutu
    i już nie wiem czy to wina kwarca czy wadliwego PCF-a
  • #38
    007mirek
    Level 11  
    jeszcze przepatrzę jak nic nie znajdę to wkleję kod :).
  • #40
    007mirek
    Level 11  
    Witam

    Używam kodu z https://www.elektroda.pl/rtvforum/topic1824574.html
    dodatkowo

    #define ONE_I2C_PIO AT91C_BASE_PIOA
    #define I2C_SDA AT91C_PIO_PA5
    #define I2C_SCL AT91C_PIO_PA6

    #define PIO_INIC {ONE_I2C_PIO->PIO_PER = I2C_SDA; ONE_I2C_PIO->PIO_PER = I2C_SCL;}
    #define SCL_SET_HIGH ONE_I2C_PIO->PIO_ODR = I2C_SCL
    #define SCL_SET_LOW ONE_I2C_PIO->PIO_OER = I2C_SCL
    #define SET_OUT_SCL ONE_I2C_PIO->PIO_CODR = I2C_SCL
    #define GET_SCL (ONE_I2C_PIO->PIO_PDSR & I2C_SCL)
    #define SET_HIGH_SDA ONE_I2C_PIO->PIO_ODR = I2C_SDA
    #define SET_LOW_SDA ONE_I2C_PIO->PIO_OER = I2C_SDA
    #define SET_OUT_SDA ONE_I2C_PIO->PIO_CODR = I2C_SDA
    #define GET_SDA (ONE_I2C_PIO->PIO_PDSR & I2C_SDA)
    #define CZAS 3

    nie ważne jaki ustawie czas opóźnienia (0 czy 50) zawsze zachowuje się tak samo, gdy wylutowałem kwarc PCF przestał liczyć czas, wlutowany jest kondensator 10 pF, oraz dwa rezystory 4,7 KO, procesor jest jakieś 40 cm od PCF (tzn. na jednej płytce jest procek AT91SAM na drugiej PCF bateria)

    Pozdrawiam
  • #41
    piotrva
    VIP Meritorious for electroda.pl
    pod PCF'a powinien być podpięty kwarc 32,768 kHz i kondensator (33pF) lub trymer i na tym koniec (jeśli chodzi o linie OSCI i OSCO), żadnych rezystorów przy rezonatorze
  • #42
    007mirek
    Level 11  
    jest kwarc 32,768 kHz i kondensator (10pF) rezystorów nie ma na liniach OSCI i OSCO (tylko na scl i sda).
  • #44
    007mirek
    Level 11  
    Witam

    Znalazłem nareszcie rozwiązanie mojego problemu okazuje się ze wystarczy ze odczytane byte przesunę o 5 i zegarek działa prawidłowo.
    Może wie ktoś czemu się tak dzieje
    oto kawałek kodu.

    static u16 OdczytajByte(void)
    {
    u8 i;
    static u16 Wynik = 0;
    Wynik = 0;
    SDA_S_H;
    for (i = 0; i < 8; i++) {
    delay_us(7);
    SCL_S_H();
    delay_us(7);
    Wynik <<= 1;
    Wynik |= SDA_G;
    SCL_S_L;
    }
    wyswietl(Wynik ,"G");
    Wynik =Wynik >>5;
    wyswietl(Wynik ,"B");
    return Wynik ;
    }

    (Wcześniej miałem zmienne typu u8 co powodowało ze miałem tylko końcówki odczytanych bytów po zwiększeniu zakresu do u16 znalazłem rozwiązanie )
  • #45
    doles
    Level 19  
    Witam, dołączę się do tematu aby nie robić śmietnika. Mam taki oto problem. Zrobiłem początkowo program, który odczytuje mi rejestry godziny, minut, sekund i sekund setnych na wyświetlaczu LCD - sam odczyt, taki timer. Niestety gdy próbowałem zapisać coś do PCF'a np do rejestru minut liczbę 10 tak po tej operacji przestał działać licznik minut... Czyli wciskam przycisk, ustawia się 10 i gdy sekundy przejdą wartość 59 minuty nie inkrementują się. Problem jest nawet po odłączeniu zasilania - powinny się chyba zresetować ustawienia PCF'a w pamięci ... Przez przypadek kombinowałem z odczytem sekund i te też "stanęły" w miejscu... teraz działa mi tylko sekundy setne. Na początku gdy nie robiłem nic z zapisem do rejestrów było OK. Wszystko pięknie odczytywało. Czy uszkodziłem PCF'a ?

    Code: c
    Log in, to see the code
  • #46
    JarekC
    Level 32  
    Witam,

    Raczej nie uszkodziłeś PCFa.
    Bardziej prawdopodobne jest, że masz coś nie tak z przyciskiem i cały czas w pętli while wykonujesz zapis do rejestru minut. Zakomentuj na chwilę te część kodu i sprawdź.

    Pozdrawiam
    JarekC
  • #47
    doles
    Level 19  
    Zakomentowałem nie raz i niestety nic to nie daje...tak jakbym już przy jednym wciśnięciu na początku zapisał coś na stałe do rejestrów, bo nawet odcięcie zasilania nie resetuje ustawień PCF'a a przecież powinien wrócić do początku - godzina 00:00:00:00 ... Próbowałem zapisać do rejestru kontrolnego 0x00 wartość 0, przywróciło to jedynie odliczanie sekund setnych... bo sekundy i minuty stoją w miejscu. Po włączeniu zasilania minuty pokazuje 01, godziny i sekundy 00 natomiast lecą jak szalone sekundy setne. Nie mam pojęcia co namieszałem tym przyciskiem ... Czy mógłby ktoś powiedzieć, jak zapisać poprawnie do PCF'a jakąś wartość do rejestrów ? Albo lepiej jak go teraz zresetować...
  • #48
    JarekC
    Level 32  
    Witam,

    Aby zresetować PCF musisz odpiąć zasilanie główne oraz zasilanie podtrzymujące (bateria).
    Jeżeli przy PCF jest zamontowany kondensator to musisz go zewrzeć na chwilkę lub odczekać aż się rozładuje. Trzeba to zrobić bo energia zgromadzona w kondensatorze może wystarczyć PCFowi na kilkanaście, kilkadziesiąt sekund pracy,
    Potem załączyć i układ powinien być zresetowany.

    Pozdrawiam
    JarekC
  • #49
    doles
    Level 19  
    Hmm baterii podtrzymującej nie mam, wyłączyłem zasilanie na całą noc od układu a rano po podłączeniu było tak samo ...
  • #50
    JarekC
    Level 32  
    Możesz spróbować zacząć od tego aby sprawdzić poprawność zapisu i odczytu PCFa.
    Zapisz np komórkę 100 pamięci PCFa jaką wartością a potem odczytaj i sprawdź poprawność.

    Działający kod obsługi I2C i PCF8583 możesz znaleźć w moim projekcie:

    "Zegar "VGA-RTC" - ATMega16+PCF8583+TeleVGA+Monitor"
    https://www.elektroda.pl/rtvforum/viewtopic.php?p=10120357#10120357

    Pozdrawiam
    JarekC
  • #51
    doles
    Level 19  
    co to jest komórka 100 pamięci PCF'a ? Trochę jaśniej ?
  • #52
    kiziu13
    Level 17  
    PCF ma 256 komórek pamięci, z czego pierwsze 15 zajmują rejestry, a reszta jest dostępna dla użytkownika jako ekstra RAM. JarekC miał na myśli, abyś po prostu do którejś komórki RAMu, np. o numerze 100 (0x64), wpisał jakąś wartość i sprawdził, czy po odczycie z tej samej komórki, wartość będzie taka sama, jaką zapisałeś. Dowiesz się, czy nie uszkodziła się w jakiś sposób pamięć.
  • #53
    doles
    Level 19  
    Witam, przepraszam z góry za tak długi czas nieobecności, ale miałem ważne projekty do zrobienia na uczelnię. Tak więc po przerwie wracam z nadzieją "naprawienia" problemu. Zapisałem do komórki ram o adresie 0x64 wartość BCD 00100000 czyli liczbę 20. Jej odczyt przebiega prawidłowo, czyli rozumiem, że układ nie jest uszkodzony. Pytanie teraz brzmi...jak go zresetować? Odłączenie zasilania, zwarcie + i - nic nie daje. Płytka ewaluacyjna na której uczę się programować stała bez zasilania kilka dni więc...powinno wszystko się zresetować. Domyślam się że teraz już tylko zostaje reset programowy. Pomoże ktoś?
  • #54
    JarekC
    Level 32  
    Witam,

    W takim razie odczytaj 15 pierwszych adresów i podaj odczytane wartości.
    Zobaczymy jak jest skonfigurowany PCF.

    Pozdrawiam
    JarekC
  • #55
    doles
    Level 19  
    Witam, znów przepraszam za zwłokę. Teraz już mam czas pisać :) Wszelkie sprawy uczelniane zostały zakończone. Sprawdziłem wszystkie adresy począwszy od 0x00 do 0x0F. Efekt poniżej:

    Adres wartość
    0x00 00
    0x01 00
    0x02 00
    0x03 00
    0x04 00
    0x05 01
    0x06 01
    0x07 00
    0x08 00
    0x09 FF
    0x0A FF
    0x0B EF
    0x0C FF
    0x0D CF
    0x0E EF
    0x0F FF
  • #56
    JarekC
    Level 32  
    Witam,

    Rejestry konfiguracyjne i liczniki mają stan zgodny ze stanem po resecie układu.

    Może masz problemy z układem oscylatora (kwarc + kondensatory).

    Sprawdź czy na nóżce INT masz przebieg 1Hz (przy pomocy miernika lub diody LED),
    tylko pamiętaj iż ta noga jest typu Open Drain czyli wymaga rezystora podciągającego (Pull-Up.)

    Pozdrawiam
    Jarekc
  • #57
    doles
    Level 19  
    Dioda LED podłączona do nóżki INT miga idealnie co sekundę.
  • #58
    Kuniarz
    Moderator of Designing
    Odkopię temat, bo mi się pomysły kończą.

    Zawsze używałem DS1307, ale pech chciał, że pracuję na gotowej elektronice, z PCF8583P właśnie i mi rogi pokazuje bestia jedna...

    Mam takie procedury, okrojone do minimum :
    Code:

    Sub Gettime                                                 'odczyt czasu z RTC
       I2cstart
       I2cwbyte 162
       I2cwbyte 2
       I2cstart
       I2cwbyte 163
       I2crbyte Sekundy , Ack
       I2crbyte Minuty , Ack
       I2crbyte Godziny , Ack
       I2crbyte Dzien , Ack
       I2crbyte Miesiac , Nack
       I2cstop
       Sekundy = Makedec(sekundy)
       Minuty = Makedec(minuty)
       Godziny = Makedec(godziny)
    End Sub


    Sub Settime                                                 'zapis czasu do RTC
       Godziny = Makebcd(godziny)
       Minuty = Makebcd(Minuty)
       Sekundy = Makebcd(Sekundy)
       I2cstart
       I2cwbyte 162
       I2cwbyte 2
       I2cwbyte Sekundy
       I2cwbyte Minuty
       I2cwbyte Godziny
       I2cwbyte Dzien
       I2cwbyte Miesiac
       I2cstop
    End Sub


    Odczytuje wartości 165:165:165
    Jeśli zmienię adres na 160 i 161 wszystko działa (oprócz liczenia dni tygodnia, na czym najbardziej mi zależy)

    Jakieś pomysły ?
  • #59
    atom1477
    Level 43  
    Zamienić adresy na 160 i 161?
  • #60
    Kuniarz
    Moderator of Designing
    Zamieniłem, czas leci, dzień się zmienia, ale nie liczy tych kilku bitów które odpowiadają za numer dnia tygodnia, na czym akurat BARDZO mi zależy.
    Skąd w ogóle bierze się to 163, 160 , bo nie mogę załapać...

    edit: a może w bajcie kontrolnym, pod 00, trzeba bit 3 ustawić na 1 i wówczas odczytywać niemaskowane wartości ? Taka inicjalizacja ?