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

[ATMega16][C] Odczyt czasu z zegara PCF8563

LosRabinos 15 Lip 2011 13:11 4993 23
  • #1 9721075
    LosRabinos
    Poziom 10  
    Witam
    Próbuję odczytać czas z zegara PCF8563, ale na wyświetlaczu LCD nic się nie wyświetla.
    Bardzo proszę o sprawdzenie poprawności poniższego kodu i wskazanie gdzie ew. powinienem coś poprawić.
    Ogólnie podłączyłem SDA i SCL przez rezystory 4,7k do Vcc oraz zastosowałem rezonator 32kHz, a przy nim kondensator 22p. Pomiędzy Vcc a GND wpiąłem kondensator 100nF.
    Podczas kompilacji pojawiają się 3 warning-i, że zmienne sekundy, minuty, godziny w funkcji main nie są zainicjalizowane, ale przecież wpisuję do nich wartość w dalszej części funkcji więc nie wiem skąd warning...
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Na koniec mam jeszcze pytanie: w którym dokładnie memencie zegar RTC zaczyna liczyć czas? Czy dobrze mi się wydaje, że w momencie wpisania konkretnej wartości do rejestru odpowiadającego sekundom?
    Z góry dziękuję za jakąkolwiek pomoc.
  • #3 9721121
    LosRabinos
    Poziom 10  
    In function 'main':
    warning: 'godziny' may be used uninitialized in this function
    warning: 'minuty' may be used uninitialized in this function
    warning: 'sekundy' may be used uninitialized in this function
  • #5 9721520
    LosRabinos
    Poziom 10  
    Dziękuję nsvinc, teraz już nie ma żadnych warning-ów po kompilacji.
    Niestety nadal na wyświetlaczu LCD nie wyświetla się nic, więc cos jeszcze nie jest dobrze... Poniżej zamieszczam kod samej tylko funkcji main z powyższą poprawką i poprawką w pętli for:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #6 9721752
    dondu
    Moderator na urlopie...
    nsvinc napisał:
    Kompilator jasno dał do zrozumienia co jest nie tak


    Nie szukałem w manualu, ale zawsze sądziłem, że w GCC zdeklarowane zmienne bez podania ich wartości w deklaracji, są ustawiane na zero, co potwierdza brak warnningów w przykładzie:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Jak więc jest naprawdę?
    A może tu chodzi o coś innego o czym nie wiem?
  • #7 9721899
    nsvinc
    Poziom 35  
    Kompilator domyślnie nie inicjalizuje zmiennych lokalnych które zadeklarujesz w funkcyjkach
    Kod: text
    Zaloguj się, aby zobaczyć kod

    W tym przykładzie, "ple" nie jest niczym inicjalizowane, więc wartość tej zmiennej jest brana z tzw. kosmosu ;] a następnie żąda się, aby tą wartość zwróciła funkcja. To generuje warning...

    W twoim przykładzie, warninga nie będzie, bo tutaj
    Kod: text
    Zaloguj się, aby zobaczyć kod

    właśnie inicjalizujesz niezainicjalizowaną wcześniej zmienną, za to dostaniesz warninga, że zainicjalizowałeś i nic więcej z tą zmienną nie robisz...

    Zamień tą linijkę na
    Kod: text
    Zaloguj się, aby zobaczyć kod

    i podziwiaj wrzaski kompilatora ;]
  • #8 9721940
    gaskoin
    Poziom 38  
    dondu napisał:

    Nie szukałem w manualu, ale zawsze sądziłem, że w GCC zdeklarowane zmienne bez podania ich wartości w deklaracji, są ustawiane na zero, co potwierdza brak warnningów w przykładzie:

    A może tu chodzi o coś innego o czym nie wiem?


    Tylko globalne i statyczne (które de facto też są z punktu widzenia kompilatora globalne) Jest to opisane w manualu do avr-libc.
  • #9 9722044
    LosRabinos
    Poziom 10  
    Czy ma ktoś jakiś pomysł co powinienem poprawić w programie?
    Bardzo proszę osoby, które miały do czynienia z tym układem, bo ja po kilku dniach rozkminiania już nie mam pomysłów co może byc źle...
  • #10 9722762
    krru
    Poziom 33  
    Warning chyba wynikał z faktu, że podstawienie tych 'podejrzanych' zmiennych było w pętli, a pętla for potencjalnie może się nie wykonać ani razu. W Twoim kodzie jest to stała liczba obiegów, ale kompilator chyba aż tak nie analizuje kodu.
    Po przesunięciu podstawień poza pętle (pierwotnie to było w ogóle źle) warningi powinny zniknąć, a tym że dodałeś jeszcze jawne zainicjowanie wartości.

    A jeśli chodzi o zegarek - może podaj czym się objawia "niedziałanie". Ja bawiłem się PCF8583 - trochę inaczej ma zorganizowane rejestru, ale dostęp jest podobny.

    I takie dwie uwagi - można odczytać wiele kolejnych rejestrów jedną transmisją I2C.
    Konwersje BCD i sprintf są zbędne - rejestry są w BCD właśnie po to, by je łatwo wypisać, bierze się odpowiednie 4 bity, dodaje do '0' i mamy znak do wyświetlenia w danym polu.
  • #11 9722849
    janbernat
    Poziom 38  
    O tej sprinf to ja gdzieś kiedyś czytałem...
    A- wczoraj.
    W książce tmf.
    Str. 92.
    Należy dołączyć bibliotekę libprintff_flt
    I do opcji linkowania dodać -Wl,-u,vprintf
    A najepiej w tym wypadku tego nie używać.
    Tylko skorzystać z formatu BCD.
    To jest z kolei w książce mirka36 opisane.
    W książce tmf być może też- ale jeszce do tego nie doszedłem.
  • #12 9723447
    dondu
    Moderator na urlopie...
    @Nsvinc Nadal mnie nie przekonuje to co napisałeś.
    Podając swój przykład zbudowałem go dokładnie tak jak przykład autora tematu.
    Ty omawiasz inny przykład.

    Dla porównania autor tematu:


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    mój:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Różnią się tylko wystąpieniem pętli for. Dlatego napisałem, że nie rozumie, dlaczego według Ciebie, brak inicjalizacji wartości zmiennej miałby powodować warning. Pod tym względem oba przykłady są takie same. Chyba, że jest coś czego nie łapię :)

    Podajesz natomiast przykład który nie ma miejsca w przypadku kodu przedstawionego na początku przez autora.

    Więc może jednak jest to związane z tym co pisze krru?
    Niestety autor nie podał linii które generują ten warning (@LosRabinos następnym razem, gdy prosimy o komunikat kopiuj cały oraz podawaj, których linii dotyczy).


    @gaskoin to dlaczego mój przykład nie generuje warninga skoro zmienna nie jest globalna ani statyczna?

    Drążę temat, ponieważ jest coś czego chyba nie wiem.
  • #13 9723565
    krru
    Poziom 33  
    Moją hipotezę można latwo sprawdzić zamieniając pętle for na do{ }while. Taka pętla wykonuje się przynajmniej raz i wtedy podstawienie na pewno nastąpi.
  • #14 9723668
    LordBlick
    VIP Zasłużony dla elektroda
    LosRabinos, proponuję tymczasowo zamiast wypisywania na wyświetlaczu, wysłanie RS-em do PC... Watchdog wyłączony ? Zadeklarowana częstotliwość zegara odpowiada rzeczywistej ?
  • #15 9723783
    krru
    Poziom 33  
    Cenna uwaga, wcześniej zadałem pytanie o obawy. W jednym z poprzedzających postów znajduje się zdanie
    LosRabinos napisał:
    Niestety nadal na wyświetlaczu LCD nie wyświetla się nic, więc cos jeszcze nie jest dobrze...


    Jeśli faktycznie na wyświetlaczu nie ma dokładnie nic to świadczy, że szukamy błedu tam, gdzie go być może nie ma.
    Istrukcja typu:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    zawsze zapiszę jakąś liczbę do tab (w postaci tekstu oczywiście) i wypisanie tego tab na wyświetlaczu powinno zawsze dać jakiś efekt wizualny, nie mówiąc już o ':' wypisywanym później.
    Jeszcze raz ponowię swoje pytanie, bardziej ściśle. Co oznacza "nic na wyświetlaczu"?
    Czy dolna linijka (zakładam że to HD44780) jest inna niż górna? Czy w ogóle wydać pozycje na których powinny być znaki? Czy jest i jeśli tak, to czy działa podświetlenie?
  • #16 9724098
    LosRabinos
    Poziom 10  
    Obecnie nie ma juz żadnych warning-ów.

    Jeśli chodzi o bibliotekę "hd44780.c" to ona jest gotową biblioteką, którą pobrałem z internetu.
    Jedyne co w niej zmieniałem to oznaczenia pinów, do których mam podłączone odowiednie wyprowadzenia wyświetlacza, ale działa poprawnie - w innych prgramach wszystko wyświetlane jest poprawnie.
    Podświetlanie działa poprawnie i obie linie wyswietlacza są takie same; widoczne są segmenty w których powinny pojawic się literki.

    Częstotliwość zegara jest ok czyli 16MHz, z watchdogiem nic nie robiłem (na początku posta podałem cały mój program).
    Gdy wysyłam dane przez RS-232 do PC, to w terminalu również nic się nie wyświetla.

    Poszukam jeszcze dokładniej, bo być może gdzieś się program zapętla...
  • #17 9741755
    LosRabinos
    Poziom 10  
    Nie udało mi się rozwiązać problemu z komunikacją z zegarem rtc więc, postanowiłem skorzystac z gotowego rozwiązania z książki Mirosława Kardasia, w której co prawda jest opisany PCF8583, ale w zasadzie jest on bardzo podobny do mojego PCF8563P.
    Po wgraniu programu, na wyśw. LCD i w terminalu nic się wyświetla...
    Pomyślałem że skoro ciągle nic się nie wyświetla, ani nie trafia do terminala to pewnie program gdzieś się zapętla.
    Dodałem więc w funkcji main programu (w pierwszym wierszu wyświetlacza) napis "Czas", "?" oraz "??", co oznaczyłem komentarzami Test1, Test2 i Test3.
    Ponadto dodałem sprawdzenia: poprawności wysłania sekwencji start, poprawności wysłania sekwencji stop oraz poprawności zapisania danych.
    Sprawdzenia te pochodzą z artykułu pt. "Obługa I2C(TWI) na AVR" ze strony domowej Cezarego Klimasza.
    Po wgraniu programu na wyśw. LCD pojawił się napis:
    Czas: ?
    ERROR WRITE !

    Nie wyświetlił się natomist napis "??" w pierwszej linii wyświetlacza, dlatego też program zapętla się gdzieś w wywołaniu funkcji:
    TWI_Read_buf(0xA2, 0x02, 3, bufor2); (znajdującej się na początku pętli while w funkcji main)
    Sprawdziłem wszystkie funkcje dokładnie po kolei, lecz nie odnalazłem błędów...
    Na koniec sprawdziłem możliwe miejsca zapętlenie czyli pętle while w funkcjach: void TWI_Write(uint8_t ucData) oraz uint8_t TWI_Read(uint8_t ack).
    Okazało się, że jeśli usunę z pętli while w funkcji uint8_t TWI_Read(uint8_t ack) znak negacji i pętla while będzie wyglądać tak:
    while ((TWCR & (1<<TWINT))); , to na wyświetlaczu wyświetla mi się taki oto napis:
    Czas: ? ??
    10:10:103ITE !
    ,
    natomiast w terminalu ciągle (co sekundę) otrzymuję stringi "ggg".
    Pierwsza linia wyświetlacza jest ok. ale druga jak widać już nie, gdyż ja oczekuję czasu 11:22:33.
    Na to wygląda, że flaga TWINT nie jest ustawiana w tym warunku pętli...
    Niestety jak na początkującego ten problem mnie przerasta w tej chwili i nie mam już pomysłów co można poprawić, dlatego bardzo proszę o jakieś wskazówki i pomoc przy rozwiązaniu tego problemu.
    Poniżej zamieszam kod cały kod programu:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    P.S. Przepraszam, że się tak rozpisałem, ale mam nadzieję, że chociaż dokładnie opisałem problem.
  • #18 9767375
    LosRabinos
    Poziom 10  
    Po głębszej analizie datasheet-a dodałem dokładniejsze sprawdzanie poprawności operacji dla interfejsu I2C. Mianowicie w funkcji void TWI_Write(uint8_t ucData) rozpisałem każdy warunek osobno.
    Teraz przy wgraniu programu na wyśw. LCD pojawia się komunikat:
    Czas: ?
    ERROR 1

    Oznacza to, że albo SLA+W nie został wysłany albo, że nie został odebrany bit potwierdzenia ACK.
    Bardzo proszę, zeby mnie ktoś nakierował, co może być tego przyczyną oraz jak można to rozwiązać.
    Poniżej przedstawiam kod samej tylko funkcji sprawdzającej zapis danych oraz schemat połączeń mojego układu.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    [ATMega16][C] Odczyt czasu z zegara PCF8563
  • #19 9773908
    krru
    Poziom 33  
    LosRabinos napisał:
    Po głębszej analizie datasheet-a dodałem dokładniejsze sprawdzanie poprawności operacji dla interfejsu I2C. Mianowicie w funkcji void TWI_Write(uint8_t ucData) rozpisałem każdy warunek osobno.
    Teraz przy wgraniu programu na wyśw. LCD pojawia się komunikat:
    Czas: ?
    ERROR 1

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod




    Trochę dziwnie wygląda to sprawdzania błędów - jakoś tak seria if-ów z warunkiem !=
    mnie nie przekonuje. To jest bez sensu. Else po pierwszym if-ie oznacza że jest dokładnie
    0x18 więc kolejne sprawdzania są niepotrzebne. Przemyśl ten kod jeszcze raz.
    Bardzo prawdopodobne, że chciałeś tam napisać ==.
  • #20 9825691
    smajlas
    Poziom 12  
    LosRabinos
    Nie wiem, czy trochę poniewczasie, ale zawsze to coś.
    Odnośnie hardware-u: PCF8563 noga 3 (A0) do masy i wtedy (pierwszy listing):
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    bo ATmega gada pod nieistniejacy adres, a jak nie, to zostaw kod jaki jest, ale podepnij nogę 3 do Vcc.
  • #21 9825751
    piotrva
    VIP Zasłużony dla elektroda
    smajlas napisał:
    LosRabinos
    Nie wiem, czy trochę poniewczasie, ale zawsze to coś.
    Odnośnie hardware-u: PCF8563 noga 3 (A0) do masy i wtedy (pierwszy listing):
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    bo ATmega gada pod nieistniejacy adres, a jak nie, to zostaw kod jaki jest, ale podepnij nogę 3 do Vcc.

    OD KIEDY PCF8563 MA NOGĘ ADRESOWĄ?
    Takowa jest w modelu pcf8583, w 8563 pełni ona rolę programowanego wyjścia sygnału etatowego i jeśli z niego nie korzystamy to powinna być pozostawiona jako niepodlaczona...
    Zachęcam obu Kolegów do lektury karty katalogowej obu kości, bo jak tak dalej pójdzie to marnie wróżę...
  • #22 9825756
    smajlas
    Poziom 12  
    Ups, rzeczywiście... mea culpa, nie dopatrzyłem. Przepraszam.
  • #23 9826223
    LosRabinos
    Poziom 10  
    Witam
    Na schemacie który umieściłem przy rezonatorze kwarcowym powinien byc kondensator 22pF.
    Teraz program ruszył i na wyświetlaczu LCD pojawia się już czas który ustawiam.

    Jest tylko jeszcze jednen mały mankament tzn. ja ustawiłem czas początkowy 11:22:33. Za każym razem, gdy wartośc sekund osiągnie 40, to wartość godzin zmienia się z 11 na 51. Gdy wartośc sekund osiągnie 00 to wartość godzin wraca do stanu pierwotnego tzn 11.
    Czy ktoś mógłby mi powiedzieć skąd taka dziwna zmiana?
  • #24 9845865
    stoowa
    Poziom 14  
    Miałem podobne objawy jak Ty. Problemem tkwił w poprawnym odczytywaniu PCFa. Jak dasz ACK po odczycie to nie musisz wskazywać adresu kolejnego rejestru do odczytu bo ustawi się automatycznie (o ile czytasz rejestry po kolei...)

    przykład odczytu sekund masz poniżej:

    
    
    void odczyt_sekundy (){
    
    
    	twistartczysty();
    	twiSend(0xA2);
    
    	twiSend(0x02);
    	twistartczysty();
    	twiSend(0xA3);
    	sekunda1=twiRead(0);
    
    	twiStop();
    	sekunda1=sekunda1&0b01111111;
    	sekunda1=bcd2dec(sekunda1);
    
    }
    
REKLAMA