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
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
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
$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