Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[ATmega8][Bascom][PCF8583] nie odczytuje czasu po i2c

rassmuss 05 Apr 2009 14:13 2727 6
IGE-XAO
  • #1
    rassmuss
    Level 11  
    Witam wszystkich, pewnie juz nie raz czytaliscie takie tematy...A tu kolejny ;)
    Przegladalem wiele tematow o komunikacji z pcf8583, wiele kodow z nich przetestowalem i nic.
    A tradycyjnie problem jest taki, ze przy odczycie godziny dostaje krzaki. Przypuszczam ze nie dziala komunikacja po i2c, bo nie ma znaczenia czy pcf jest zasilany czy nie, otrzymuje to samo po wywolaniu przerwania na INT0. Linie sda i scl sa podciagniete programowo i rezystorami 4k7.
    Ogolny schemat dzialania jest taki:
    -program dziala w petli wyswietlajac godzine na zegarku
    -timer1 mruga kropka przy drugiej cyfrze
    -w zalozeniach pcf generuje niskie zbocze co sekunde i ono wywoluje przerwanie na INT0
    -to przerwanie odczytuje godzine i aktualizuje zmienne w procesorze
    Wszystko smiga jesli nie wywolam przerwania. Mam 00.00 i kropka sobie ladnie miga. Po wywolaniu przerwania pojawiaja sie krzaki. Jesli zamiast minut bede wyswietlal sekundy, nic sie nie zmienia, a wiec chyba na pewno i2c kuleje.

    Oto kodzik
    Code:
    $regfile = "m8def.dat"
    
    $crystal = 8000000


    Const Pcf_o = 163             'adres zegara RTC odzczytu
    Const Pcf_z = 162             'adres zegara RTC zapisu

    'konfiguracja portow wejsciowych
    Config Portc.0 = Input
    Config Portc.1 = Input
    Config Portc.2 = Input
    Config Portc.3 = Input
    Config Portd = Output
    Config Portb = Output

    Config Sda = Portc.4
    Config Scl = Portc.5
    'Config I2cdelay = 5
    'I2cinit
    Config I2cdelay = 100


    'konfiguracja przerwania
    Config Int0 = Falling         'przerwanie wywoluje zbocze malejace
    Config Pind.2 = Input         'nozka przerwania to wejscie
    Set Portd.2                   'stan spoczynkowy 1
    On Int0 Sekunda               'procedurka obslugi przerwania
    Enable Int0                   'wlaczamy przerwania na int0

    Config Timer1 = Timer , Prescale = 64
    On Timer1 Kropkownik



    'definicja cyferek tak aby uproscic ich uzycie
    Dim Cyfry(10) As Byte         'tablica cyfr
                 'zero tam gdzie ma sie palic!
    Cyfry(1) = &B10001000         'zero
    Cyfry(2) = &B11101011         'jeden
    Cyfry(3) = &B01001100         'dwa
    Cyfry(4) = &B01001001         'trzy
    Cyfry(5) = &B00101011         'cztery
    Cyfry(6) = &B00011001         'piec
    Cyfry(7) = &B00011000         'szesc
    Cyfry(8) = &B11001011         'siedem
    Cyfry(9) = &B00001000         'osiem
    Cyfry(10) = &B00001001        'dziewiec


    'zmienne przechowujace obecny czas
    Dim Minuty As Byte            'przechowuje minuty
    Dim Godziny As Byte           'przechowuje godziny
    Dim Sekundy As Byte



    'zmienne przechowujace czas budzenia
    Dim Minutybudzik As Byte
    Dim Godzinybudzik As Byte



    'zmienne przechowujace czas do wyswietlenia
    Dim Minwyswietl As Byte       'minuty
    Dim Godzwyswietl As Byte      'godziny


    'zmienna tymczasowa
    Dim Tmp As Byte


    'zmienna mowiaca czy wyswietlac kropke
    Dim Kropka As Bit



    'zmienna przechowujaca obecny tryb dzialania
    Dim Tryb As Byte
    '0 - godzina obecna
    '1 - godzina ustawiana
    '2 - godzina budzenia
    '3 - godzina alarmu


    'aliasy aby ulatwic dzialanie
    Led1 Alias Portd.4            'pierwszy wyswietlacz
    Led2 Alias Portd.5            'drugi wyswietlacz
    Led3 Alias Portd.6            'trzeci wyswietlacz
    Led4 Alias Portd.7            'czwarty wyswietlacz

    Przyciskmin Alias Pinc.2      'przycisk ustawiania minut
    Przyciskgodz Alias Pinc.3     'przycisk ustawiania godzin
    Przyciskustaw Alias Pinc.0    'przycisk ustawiania czasu
    Przyciskbudzik Alias Pinc.1   'przycisk ustawiania czasu budzika


    'stany spoczynkowe poszczegolnych wyjsc
    Reset Led1                    'zerujemy tranzystorki, zaden wyswietlacz sie nie pali
    Reset Led2
    Reset Led3
    Reset Led4

    Set Portb                     'podciagamy port (segment sie pali gdy tu podac zero)

    Set Portc.2                   'podciagamy linie przyciskow, wcisniecie podaje mase
    Set Portc.3
    Set Portc.0
    Set Portc.1
    Set Portc.4
    Set Portc.5


    Minuty = 0
    Godziny = 0

    Minutybudzik = 0
    Godzinybudzik = 12

    Minwyswietl = 0
    Godzwyswietl = 0


    Tryb = 0                      'wyswietlamy godzine jak nic sie nie dzieje

    Kropka = 0

    Enable Timer1

    Enable Interrupts             'wlaczamy przerwania w kosci


    Declare Sub Wyswietl_czas     'wyswietla cos na wyswietlaczu


    Do                            'glowna petla programu

       If Przyciskustaw = 0 Then  'jesli jest wcisniety przycisk ustawiania zegara
          Tryb = 1
          Kropka = 1
       End If

       If Przyciskbudzik = 0 Then 'jesli przycisk ustawiania budzika
          Tryb = 2
       End If

       If Przyciskustaw = 0 And Przyciskbudzik = 0 Then       'jesli oba razem
          Tryb = 3
       End If

       Call Wyswietl_czas

       Select Case Tryb           'zaleznie od trybu na wyswietlaczu bedzie cosik innego
          Case 0 : Minwyswietl = Minuty
                   Godzwyswietl = Godziny

          Case 1 To 2 : Minwyswietl = Minutybudzik
                        Godzwyswietl = Godzinybudzik

          Case 3:
       End Select

       Call Wyswietl_czas


       Tryb = 0                   'zerujemy tryb na wypadek gdyby puscic przyciski, jesli nie beda puszczone
                                  'to przy nastepnym przebiegu petli Tryb zostanie odpowiednio ustawiony
    Loop
    End

    Sekunda:                      'procedurka obslugi przerwania
       I2cstart
       I2cwbyte 162
       I2cwbyte 2
       I2cstart
       I2cwbyte 163
       I2crbyte Sekundy , Ack
       I2crbyte Minuty , Ack
       I2crbyte Godziny , Nack
       I2cstop

       Minuty = Makedec(minuty)
       Godziny = Makedec(godziny)
    Return


    Kropkownik:
       If Tryb = 0 Then
          Toggle Kropka
       End If
    Return



    Sub Wyswietl_czas
       Set Portb                  'dajemy 1 na wszystkie wyjscia portu b (gasimy wyswietlacze)

       Reset Led1                 'wylaczamy wszystkie dla pewnosci
       Reset Led2
       Reset Led3
       Reset Led4

       Tmp = Godzwyswietl / 10
       'If Tmp <> 0 Then
          Portb = Cyfry(tmp + 1)
          Set Led1
          Waitms 4
          Reset Led1
       'End If

       Tmp = Godzwyswietl / 10
       Tmp = Tmp * 10
       Tmp = Godzwyswietl - Tmp
       Portb = Cyfry(tmp + 1)

       If Kropka = 1 Then
          Portb.3 = 0
       End If

       Set Led2
       Waitms 4
       Reset Led2

       Tmp = Minwyswietl / 10
       Portb = Cyfry(tmp + 1)
       Set Led3
       Waitms 4
       Reset Led3

       Tmp = Minwyswietl / 10
       Tmp = Tmp * 10
       Tmp = Minwyswietl - Tmp
       Portb = Cyfry(tmp + 1)
       Set Led4
       Waitms 4
       Reset Led4
    End Sub

    Prosze o jakiekolwiek sugestie
    Pozdrawiam
    [28-30.06.2022, targi] PowerUP EXPO 2022 - zasilanie w elektronice. Zarejestruj się za darmo
  • IGE-XAO
  • #2
    dawid512
    Level 32  
    Dlaczego chcesz odczytywać czas w przerwaniu? Przerwanie powinno być jak najkrótsze. Odczyt danych z pcf-a zrób w pętli głównej a przerwanie wykorzystaj tylko do migania kropką.
  • IGE-XAO
  • #3
    crazy_phisic
    VIP Meritorious for electroda.pl
    Jak myślisz co zwróci zmienna typu Byte po takim działaniu dla np Godzwyswietl=5:
    Code:

       Tmp = Godzwyswietl / 10
       Tmp = Tmp * 10
       Tmp = Godzwyswietl - Tmp
  • #4
    rassmuss
    Level 11  
    dawid512 wrote:
    Dlaczego chcesz odczytywać czas w przerwaniu? Przerwanie powinno być jak najkrótsze. Odczyt danych z pcf-a zrób w pętli głównej a przerwanie wykorzystaj tylko do migania kropką.
    Wiem ze powinno byc jak najkrotsze, ale chcialem aby odczyt czasu wystepowal tylko gdy jest potrzebny. Gdy dorzuce go do petli glownej to obawiam sie ze wyswietlacze zaczna migac.
    W pierwotnym rozwiazaniu (bez PCFa) mialem zmienna logiczna ktora ustawialem w przerwaniu, a w petli glownej sprawdzalem jej wartosc i gdy trzeba bylo zmienialem czas. Tutaj moze tak samo zrobic?

    crazy_phisic wrote:
    Jak myślisz co zwróci zmienna typu Byte po takim działaniu dla np Godzwyswietl=5:
    Code:

       Tmp = Godzwyswietl / 10
       Tmp = Tmp * 10
       Tmp = Godzwyswietl - Tmp
    Zdziwisz sie moze, ale to dziala tak jak powinno. Oczywiscie jezeli w tej zmiennej przechowuje liczby 0-59. Zastosowalem Byte aby zmniejszyc zapotrzebowanie na pamiec (skrzywienie optymalizacyjne).
    W zamyśle mialo to dzialac tak:
    Code:
    Tmp = 5 / 10        = 0
    
    Tmp = 0 * 10       = 0
    Tmp = 5 - 0         = 5
    i wyswietla sie poprawnie 5 gdy na sztywno przypisac taka wartosc zmiennej.
    Mowisz ze zmiana na Word rozwiaze problem? W kodach ktore ogladalem rowniez uzywano Byte i podobno to dzialalo dobrze (autorzy pytan pisali ze problemy rozwiazane, ale oni raczej uzywali wyswietlacza na HD44780).
  • #5
    zumek
    Level 39  
    rassmuss wrote:
    ... Gdy dorzuce go do petli glownej to obawiam sie ze wyswietlacze zaczna migac.

    To zrób tak, żeby w przerwaniu timera były odświeżane wyświetlacze, a całą resztę umieść w pętli głównej - jak nakazuje zdrowy rozsądek :D
  • #6
    rassmuss
    Level 11  
    zumek wrote:
    rassmuss wrote:
    ... Gdy dorzuce go do petli glownej to obawiam sie ze wyswietlacze zaczna migac.

    To zrób tak, żeby w przerwaniu timera były odświeżane wyświetlacze, a całą resztę umieść w pętli głównej - jak nakazuje zdrowy rozsądek :D
    Czyli ze niby odwrotnie niz zamiaruje? Nie odswiezac w glownej petli tylko w przerwaniu timera, a czas czytac ciagle w petli...Ciekawy pomysl...Tylko ze wtedy przerwanie trwaloby minimum 20ms, aby nie za dlugo?
    A czemu mowisz zdrowy rozsadek :P
    Naczytalem sie tutaj o mozliwie najkrotszych obslugach przerwan a to to sie z tym kloci :P
  • #7
    zumek
    Level 39  
    rassmuss wrote:
    ...Tylko ze wtedy przerwanie trwaloby minimum 20ms, aby nie za dlugo?

    A kto powiedział, ze za każdym razem(przerwaniem) masz odświeżyć wszystkie wyświetlacze :?:
    Przeszukaj forum, bo ten sposób sterowania wyświetlaczami(i nie tylko) LED, omawiano wielokrotnie.