Elektroda.pl
Elektroda.pl
X
Sklep HeluKabel
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[AtMega8][Bascom] Zegar PDF8563 + PCF8591 + Timer - kłopot z I2C

maximus22_kr 14 Sie 2011 18:45 2603 2
  • #1 14 Sie 2011 18:45
    maximus22_kr
    Poziom 18  

    Witam
    Mam układ, który mierzy dwie temperatury ( DS18B20 ), dwa napięcia ( PCF8591 ( pobiera czas ( PCF8563 ), a z powodu niedużego wyświetlacza ( 12 x 4 ) wskazania są zmieniane do 10 sekund po przepełnieniu Timer1.

    Układy PCF8563 i PCF8591 są podpięte z "zewnątrz" przewodami około 10 cm.
    Magistrala I2C ma obniżoną prędkość przez
    Config I2cdelay = 10

    Code:

    $regfile = "m8def.dat"                                      'definicja procesora
    $crystal = 4000000                                          'taktowanie procesora
    $hwstack = 32                                               ' rozmiar stosu sprzętowego
    $swstack = 10                                               ' rozmiar stosu
    $framesize = 40                                             ' rozmiar ramki
    $baud = 9600                                                ' predkość transmisji

    Config Debounce = 30

    '********************* Konfiguracja wyświetlacza
    Config Lcdbus = 4
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portc.3 , Rs = Portc.1
    Config Lcd = 24 * 2

    '********************* Konfiguracja znaku specjalnego LCD
    Deflcdchar 0 , 8 , 20 , 8 , 32 , 32 , 32 , 32 , 32          ' znak stopnia celcjusza
    Deflcdchar 1 , 32 , 14 , 1 , 15 , 17 , 15 , 1 , 32          ' znak "ą"

    '********************* Konfiguracja magistrali I2C
    Config I2cdelay = 10                                        ' domyślnie tryb Slow
    Config Sda = Portc.4
    Config Scl = Portc.5

    '********************* Konfiguracja podświetlania
    Config Portb.0 = Output                                     'Podswietlanie Niebieskie
    Reset Portb.0

    Config Portb.1 = Output                                     'Podswietlanie Czerwone
    Reset Portb.1





    Config Portb.2 = Output                                     'Podswietlanie Zielone
    Reset Portb.2

    '********************* Konfiguracja magistrali 1-Wire
    Config 1wire = Portc.0

    '********************* Konfiguracja Timer2

    Config Timer1 = Timer , Prescale = 64                       'dla kwarc = 4000000 Hz Prescale = 64 przepełnienie co 16us
    Enable Timer1

    Enable Interrupts

    On Timer1 Czas
    Timer1 = 34286                                              '31250 x 16us = 0,5 s , 65536 - 31250 = 34286

    '********************* Deklaracje zmiennych
    Dim Odczyt As Byte
    Dim Odczyt1 As Byte
    Dim Temp As Byte

    Dim Licznik1 As Integer
    Dim Flaga_uart As Bit
    Dim Uart_ciag As String * 25

    Dim Licznik2 As Integer
    Dim Ot1 As Bit

    Dim A1 As Single
    Dim Napiecie1 As String * 5
    Dim A2 As Single
    Dim Napiecie2 As String * 5

    Dim Ds1(8) As Byte                                          'zmienna określająca numer układu
    Dim Ds2(8) As Byte                                          'zmienna określająca numer układu
    Dim Ss1 As String * 6
    Dim Ss2 As String * 6
    Dim T1 As Integer                                           'zmienna odczytu dwóch bajtów z DS18B20
    Dim T2 As Integer                                           'zmienna odczytu dwóch bajtów z DS18B20

    '********************* Deklaracje zmiennych zegara

    Dim S As Byte                                               'DEC
    Dim M As Byte                                               'DEC
    Dim H As Byte                                               'DEC
    Dim Day As Byte
    Dim Month As Byte
    Dim Wk As Byte
    Dim Year As Byte

    Dim Hh As Byte                                              'BCD
    Dim Mm As Byte                                              'BCD
    Dim Ssek As Byte                                            'BCD
    Dim Wwk As Byte
    Dim Dday As Byte
    Dim Mmonth As Byte
    Dim Yyear As Byte
    Dim Dt As String * 2
    Dim Mc As String * 3
    Dim Dt1 As Byte
    Dim Mc1 As Byte

    Dim Czas_pcf As String * 12
    Dim Data_pcf As String * 9

    '********************* Deklaracja podprogramów
    Declare Sub Przeszukaj_i2c
    Declare Sub Odczytaj
    Declare Sub Temp1_lcd
    Declare Sub Temp2_lcd
    Declare Sub Wybor
    Declare Sub Gettime()                                       'pobieranie czasu
    Declare Sub Settime                                         'ustawianie czasu

    '********************* Przypisanie przyjaznych nazw do poszczególnych portów - Aliasów

    Niebieski Alias Portb.0
    Czerwony Alias Portb.1
    Zielony Alias Portb.2

    '********************* Wartości początkowe
    Const Adres_o = 145                                         'adres odczytu I2C PCF8591
    Flaga_uart = 0
    Niebieski = 1
    Ot1 = 0

    Cursor Off

    Ds1(1) = 1wsearchfirst()
    Ds2(1) = 1wsearchnext()

    Cls

    '********** Program główny
    Do

    Call Gettime


    'Obliczenia dla 10V
    A1 = Odczyt * 0.0486259
    Napiecie1 = Fusing(a1 , "#.#" )

    'Obliczenia dla 15V
    A2 = Odczyt1 * 0.0667391
    Napiecie2 = Fusing(a2 , "#.#" )

    If Flaga_uart = 1 Then
       Print Uart_ciag
       Flaga_uart = 0
    End If

    Uart_ciag = Napiecie1 + "V" + "  " + Napiecie2 + "V" + "  " + Ss1 + "  " + Ss2


    '********** magistrala 1-wire wejście 1 czujnik 1
    Disable Interrupts

    1wreset                                                     'reset magistrali 1-wire
    1wwrite &H55                                                'rozkaz adresowy SKIP ROM
    1wverify Ds1(1)                                             'sprawdź adres
    1wwrite &HBE                                                'rozkaz funkcyjny polecenie odczytu DS18B20
    T1 = 1wread(2)                                              'odczytaj dwa pierwsze bajty
                                                      'czekaj 750 ms

    '********** magistrala 1-wire wejście 1 czujnik 2

    1wreset                                                     'reset magistrali 1-wire
    1wwrite &H55                                                'rozkaz adresowy SKIP ROM
    1wverify Ds2(1)                                             'sprawdź adres
    1wwrite &HBE                                                'rozkaz funkcyjny polecenie odczytu DS18B20
    T2 = 1wread(2)                                              'odczytaj dwa pierwsze bajty
                                                     'czekaj 750 ms


    '********** konwersja temperatury dla wszystkich DS18B20

    1wreset
        1wwrite &HCC
        1wwrite &H44

    Enable Interrupts

    '**************** pierwsze wejście - pierwszy DS18B20 obliczenia **********
    T1 = T1 * 10
       T1 = T1 / 16

       Ss1 = Str(t1)
       Ss1 = Format(ss1 , " 0.0")                               'formatuj według wzorca - jedno miejsce po przecinku

    '**************** pierwsze wejście - drugi DS18B20 obliczenia  **********
    T2 = T2 * 10
       T2 = T2 / 16

       Ss2 = Str(t2)
       Ss2 = Format(ss2 , " 0.0")                               'formatuj według wzorca - jedno miejsce po przecinku



    Loop
    End


    Temp1_lcd:

    '**************** pierwsze wejście - pierwszy DS18B20 obliczenia + wyświetlanie **********

    Locate 1 , 1
    Lcd "Wewn" ; Chr(1) ; "trz"
    Locate 2 , 1                                                'wyświetl w pozycji
    Lcd Ss1 ; Chr(0) ; "C "                                     'wyświetl wynik formatowania + znak specjalny + C

    Locate 1 , 13
    Lcd Napiecie1 ; "V "

    Locate 1 , 19
    Lcd Napiecie2 ; "V"

    Return

    Temp2_lcd:

    '**************** pierwsze wejście - drugi DS18B20 obliczenia + wyświetlanie **********


    Locate 1 , 1
    Lcd "Zewn" ; Chr(1) ; "trz"
    Locate 2 , 1                                                'wyświetl w pozycji
    Lcd Ss2 ; Chr(0) ; "C "

    Locate 1 , 13
    Lcd Napiecie1 ; "V "

    Locate 1 , 19
    Lcd Napiecie2 ; "V"

    Return


    '**************** Podprogram wyboru układu DS18B20 **********

    Wybor:
    If Ot1 = 0 Then
      Niebieski = 1
      Zielony = 0
      Gosub Temp1_lcd
      Locate 2 , 13
      Lcd Czas_pcf ; "       "
      Ot1 = 1

    Else
    If Ot1 = 1 Then
      Niebieski = 0
      Zielony = 1
      Gosub Temp2_lcd
      Locate 2 , 13
      Lcd Data_pcf ; "  "
      Ot1 = 0
    End If
    End If

    Return


    '********************* Odczyt PCF8591 I2C - częstotliwość odczytu zależna pd ustawień Timer1

    Odczytaj:
    I2cinit
    I2cstart                                                    'sygnał startu magistrali I2C
    I2cwbyte 144                                                'wyślij adres "odbiorczy" PCF8591
    I2cwbyte &B00000100
    I2cwbyte &B00000101
    I2cwbyte 255
    I2cwbyte 255
    I2cstart                                                    'znów generujemy warunek startu
    I2cwbyte Adres_o                                            'adresujemy układ EEPROM do odczytu
    I2crbyte Odczyt , Ack
    I2crbyte Odczyt1 , Nack
    I2cstop
    Return

    '***********************  Obsługa czasu/daty
    Sub Gettime()
      I2cstart
      I2cwbyte 162
      I2cwbyte &H02
      I2cstart
      I2cwbyte 163
       I2crbyte Ssek , Ack                                      'Odczytuje sekundy
       I2crbyte Mm , Ack                                        'Odczytuje minuty
       I2crbyte Hh , Ack                                        'Odczytuje godziny
       I2crbyte Dday , Ack                                      'Odczytuje dni
       I2crbyte Wwk , Ack                                       'Odczytuje dzień tygodnia
       I2crbyte Mmonth , Ack                                    'Odczutuje miesiąc
       I2crbyte Yyear , Nack                                    'Odczytuje rok
       I2cstop

        Ssek = Ssek And &B01111111                              'sekundy
        Mm = Mm And &B01111111                                  'minuty
        Hh = Hh And &B00111111                                  'godziny
        Dday = Dday And &B00111111                              'dni miesiąca
        Wwk = Wwk And &B00000111                                'dni tygodnia
        Mmonth = Mmonth And &B00011111                          'miesiące
        Yyear = Yyear And &B11111111                            'lata

       S = Makedec(ssek)                                        'Zamiana kodu BCD na wartość dziesiętną
       M = Makedec(mm)                                          'Zamiana kodu BCD na wartość dziesiętną
       H = Makedec(hh)                                          'Zamiana kodu BCD na wartość dziesiętną
       Wk = Makedec(wwk)                                        'Zamiana kodu BCD na wartość dziesiętną
       Day = Makedec(dday)                                      'Zamiana kodu BCD na wartość dziesiętną
       Month = Makedec(mmonth)                                  'Zamiana kodu BCD na wartość dziesiętną
       Year = Makedec(yyear)                                    'Zamiana kodu BCD na wartość dziesiętną

      Czas_pcf = Bcd(hh) + ":" + Bcd(mm) + "    " + Dt          'Tworzenie stringa z czasem
      Data_pcf = Bcd(dday) + "/" + Mc + "/" + Bcd(yyear)        'Tworzenie stringa z datą

      '********************* Funkcja zamieniająca numer dnia tygodna na nazwę dnia
      Dt1 = Makedec(wwk)                                        'numer dnia tygodnia dla lookupstr
      Dt = Lookupstr(dt1 , Dzien_tyg )

      '********************* Funkcja zamieniająca numer miesiaca na nazwę miesiaca
      Mc1 = Makedec(mmonth)                                     'numer miesiąca dla lookupstr
      Mc = Lookupstr(mc1 , Miesiace )

    End Sub

    Czas:                                                       'co 0,5 s
    Timer1 = Timer1 + 34286                                     'załaduj do Timer1 wartość 34286

    Incr Licznik1
    Incr Licznik2

    If Licznik1 = 20 Then
      Flaga_uart = 1
      Licznik1 = 0
    End If

    If Licznik2 = 12 Then
      Gosub Wybor
      Licznik2 = 0
    End If

    Gosub Odczytaj

    Return

    '********************* Informacja o nazwie dnia tygodnia i miesiąca
    Dzien_tyg:
     Data "Nd" , "Pn" , "Wt" , "Sr" , "Cz" , "Pt" , "So"
    Miesiace:
     Data "" , "Sty" , "Lut" , "Mar" , "Kwi" , "Maj" , "Cze" , "Lip" , "Sie" , "Wrz" , "Paz" , "Lis" , "Gru"


    Problem polega na tym, że po kilku minutach ( czasem godzinie ) wskazania zegara zamieniają się w sieczkę - nie pomaga reset, ani ponowne wgranie programu, pomaga jedynie ponowne ustawienie daty i czasu. Wtedy przez jakiś czas jest OK.
    Nie wiem czy to wina dłuższych połączeń, czy może użycia Timer1. Wygląda to tak, jakby coś było wysyłane do PCF8563 i mieszało jego ustawienia czasu i daty.
    PCF8591 działa cały czas OK.
    Może to wina sposobu prezentacji danych dla każdego podprogramu wyboru wyświetlanych danych - próbowałem wyświetlać stale tylko napięcia a zmieniać termometry, ale po kilku zmianach wartości wyświetlanej LCD wyświetlał krzaczki

    0 2
  • Sklep HeluKabel
  • Pomocny post
    #2 14 Sie 2011 19:22
    snnaap
    Poziom 25  

    Przeglądając Twój program mam takie małe spostrzeżenie, a mianowicie w pętli głównej masz wywołaną procedurę Gettime - ' Call Gettime' - która działa na I2C.

    Co się stanie gdy podczas wykonywania procedury Gettime zostanie zgłoszone przerwanie od Timer'a??

    Program przerywa wykonywanie procedury Gettime i skacze do obsługi Timera a tam jest wywoływana procedura Odczytaj, która również działa na I2C.

    Zdaje mi się że tu tkwi błąd.

    Spróbuj wyłączyć przerwania przed Call Gettime może to pomoże.

    Pozdrawiam

    0
  • Sklep HeluKabel
  • #3 15 Sie 2011 01:10
    maximus22_kr
    Poziom 18  

    Tak, to jest to
    Po wyłączeniu przerwań dla Gettime idzie bez zakłóceń.

    0