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

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

rassmuss 05 Kwi 2009 14:13 2802 6
  • #1 6376695
    rassmuss
    Poziom 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
    $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
  • #2 6377027
    dawid512
    Poziom 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ą.
  • #3 6377121
    crazy_phisic
    VIP Zasłużony dla elektroda
    Jak myślisz co zwróci zmienna typu Byte po takim działaniu dla np Godzwyswietl=5:
    
       Tmp = Godzwyswietl / 10
       Tmp = Tmp * 10
       Tmp = Godzwyswietl - Tmp
    
  • #4 6377810
    rassmuss
    Poziom 11  
    dawid512 napisał:
    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 napisał:
    Jak myślisz co zwróci zmienna typu Byte po takim działaniu dla np Godzwyswietl=5:
    
       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:
    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 6377960
    zumek
    Poziom 39  
    rassmuss napisał:
    ... 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 6378194
    rassmuss
    Poziom 11  
    zumek napisał:
    rassmuss napisał:
    ... 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 6378241
    zumek
    Poziom 39  
    rassmuss napisał:
    ...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.
REKLAMA