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

[Mega16][Bascom] Obsługa DS1820 w przerwaniach...

Kuniarz 10 Maj 2010 08:19 2334 12
REKLAMA
  • #1 8057509
    Kuniarz
    Moderator Projektowanie
    Witajcie !

    Wiem, że temat był wielokrotnie sygnalizowany na forum, przejrzałem wszystkie tematy z tym problemem związane i niestety nie uzyskałem satysfakcjonującego rezultatu.

    Cała idea jest w tym, żeby całą obsługę odczytu temperatur z 4rech DSów, połączonych na oddzielnych liniach, wcisnąć w obsługę przerwań. Krótko mówiąc, chodzi o to, aby odczyt temperatury odbywał się ZAWSZE, niezależnie od tego, co program innego wykonuje.
    Po kilku zmianach sugerowanych na forum (ustawienie stosu, wyłączanie przerwania podczas odczytu) mam taki oto kod :

    $regfile = "m16def.dat"
    $crystal = 16000000
    $baud = 1200
    $hwstack = 150                                              'wartosc stosu
    $swstack = 150                                              'wartosc stosu
    
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7 , E = Portc.3 , Rs = Portc.2
    Cls
    Cursor Off Noblink
    Deflcdchar 0 , 12 , 18 , 18 , 18 , 12 , 32 , 32 , 32
    
    Config Timer0 = Timer , Prescale = 256                      'timer przerwania odczytu DSow
    Enable Interrupts
    Enable Ovf0
    On Ovf0 Przerwanie_0
    
    Dim T1 As Single                                            'temperatura
    Dim T2 As Single                                            'temperatura
    Dim T3 As Single                                            'temperatura
    Dim T4 As Single                                            'temperatura
    
    Dim T_pom_1 As Integer                                      'zmienna pomocnicza odczytu temperatury
    Dim T_pom_2 As Integer                                      'kolejna zmienna pomocnicza do przeliczania temperatury
    Dim T_pom_3 As Integer                                      'kolejna zmienna pomocnicza do przeliczania temperatury
    Dim T_pom_4 As Integer                                      'kolejna zmienna pomocnicza do przeliczania temperatury
    
    Dim Opoznienie As Byte
    Dim Licznik_opoznienia As Byte
    Dim Odczyt1 As Bit                                          'informacja, ze trwa odczyt (0-3 - numer DSa)
    Dim Numer_odcz As Byte                                      'numer aktualnie czytanego DSa
    
    Opoznienie = 255
    Odczyt1 = 0
    Numer_odcz = 1
    
    Licznik_opoznienia = Opoznienie
    
    Dim X As Byte                                               'zmienna pomocnicza
    Dim Y As Word                                               'zmienna pomocnicza 0-65535
    Dim Z1 As Byte                                              'zmienna pomocnicza migania
    Dim Z2 As Byte
    
    '*************************************************
    '***********  POCZĄTEK  PROGRAMU  ****************
    '*************************************************
    
    Do
    
    Locate 1 , 1
    Lcd Fusing(t1 , "#.#") ; Chr(0) ; "C"
    Locate 1 , 8
    Lcd Fusing(t2 , "#.#") ; Chr(0) ; "C"
    Locate 2 , 1
    Lcd Fusing(t3 , "#.#") ; Chr(0) ; "C "
    Locate 2 , 8
    Lcd Fusing(t4 , "#.#") ; Chr(0) ; "C "
    
    Loop
    
    End
    
    '**********************************
    '****    P R O C E D U R Y    *****
    '**********************************
    
    '*** obsługa przerwania 0
    '***********************************
    
    Przerwanie_0:
    '                                          odczyt temperatur z DSow
    
    Load Timer0 , 250
    If Odczyt1 = 0 Then
       Disable Timer0
       1wreset Pinb , 0
       1wwrite &HCC , 1 , Pinb , 0
       1wwrite &H44 , 1 , Pinb , 0
       1wreset Pinb , 1
       1wwrite &HCC , 1 , Pinb , 1
       1wwrite &H44 , 1 , Pinb , 1
       1wreset Pinb , 2
       1wwrite &HCC , 1 , Pinb , 2
       1wwrite &H44 , 1 , Pinb , 2
       1wreset Pinb , 4
       1wwrite &HCC , 1 , Pinb , 4
       1wwrite &H44 , 1 , Pinb , 4
    
       Enable Timer0
       Odczyt1 = 1
    End If
    Decr Licznik_opoznienia
    If Licznik_opoznienia > 0 Then
       Goto Wyj_ds_przerw
    End If
    
    Licznik_opoznienia = Opoznienie
    Disable Timer0
    1wreset Pinb , 0
    1wwrite &HCC , 1 , Pinb , 0
    1wwrite &HBE , 1 , Pinb , 0
    T_pom_1 = 1wread(2 , Pinb , 0)
    T1 = T_pom_1 / 16
    
    1wreset Pinb , 1
    1wwrite &HCC , 1 , Pinb , 1
    1wwrite &HBE , 1 , Pinb , 1
    T_pom_2 = 1wread(2 , Pinb , 1)
    T2 = T_pom_2 / 16
    
    1wreset Pinb , 2
    1wwrite &HCC , 1 , Pinb , 2
    1wwrite &HBE , 1 , Pinb , 2
    T_pom_3 = 1wread(2 , Pinb , 2)
    T3 = T_pom_3 / 16
    
    1wreset Pinb , 4
    1wwrite &HCC , 1 , Pinb , 4
    1wwrite &HBE , 1 , Pinb , 4
    T_pom_4 = 1wread(2 , Pinb , 4)
    T4 = T_pom_4 / 16
    
    Enable Timer0
    Odczyt1 = 0
    
    Wyj_ds_przerw:
    
    Return
    


    Sęk w tym, że po kilkunastu sekundach od uruchomienia, pojawiają się sporadycznie zerowe odczyty temperatur, w różnych momentach, z różnych czujników.

    Czy ktoś ma jakiś rozsądny pomysł ? (nierozsądne to np. : oddzielna atmega do DSów, wywalić DSy z przerwań, itp.)

    Pozdrawiam ! Pomocy !
    Pomogłem? Kup mi kawę.
  • REKLAMA
  • #2 8057590
    ksarim
    Poziom 15  
    Nie znam Bascoma ale postaram się coś doradzić.

    1) Jak rozumiem w przerwaniu odczytujesz po kolei temperaturę na każdym z 4 czurników. Czy wyłączasz wszystkie inne przerwania na czas tej operacji?

    2) Jak często generowane jest przerwanie odczytu tych temperatur? Czy podczas odczytywania temperatury dajesz czas każdemu z czujników na konwersję temperatury (z tego co pamiętam należy odczekać około 500ms)? Możliwe, że Twoje przerwanie jest generowane za często, czujniki nie mają odpowiednich czasów na konwersję temperatur i w pewnym momencie coś się sypie. Prawdopodobnie kiedy coś się sypie odczytujesz same jedynki na lini 1-Wire co wskazuje na to, że czujnik nic nie nadawał. Nie wiem jak ten dokładnie ten czujnik funkcjonuje ale być może właśnie podczas przetwarzania temperatury nie reaguje on poprawinie na komunikację po 1-Wire.
  • REKLAMA
  • #3 8057640
    Kuniarz
    Moderator Projektowanie
    Dziękuję kolego za chęci, niestety faktycznie nie znasz Bascoma ;-), ponieważ odpowiedzi na Twoje postulaty są zawarte w programie.
    Tak, czekam odpowiedni czas na odczyt.
    Obstawiam na jakieś przepełnienie stosu itp. Jakieś pomysły ?
    Pomogłem? Kup mi kawę.
  • Pomocny post
    #4 8057785
    malon
    Poziom 14  
    Witam, co z tego, że wywołujesz polecenie konwersji co 1 sek. skoro zaraz po wysłaniu polecenia konwersji (H44), żądasz odczytu (HBE). DSxxxx potrzebuje czasu właśnie na konwersję i tego powinno się przestrzegać. Myślę że zasilanie DS`ów jak i podłączenie zrobiłeś bezbłędnie :?:
    Najprościej w Twoim kodzie, to zamień miejscami - najpierw odczyt (HBE) potem (H44) konwersja.
    Pozdrawiam
  • REKLAMA
  • #5 8057817
    utak3r
    Poziom 25  
    Też co prawda nie znam Bascoma, ale odczytu dokonuje po opóźnieniu - wysyła H44, ustawia zmienną i w każdym kolejnym przerwaniu ją dekrementuje. Dopiero, gdy zejdzie do zera, żąda odczytu.
  • REKLAMA
  • Pomocny post
    #6 8057860
    xury
    Specjalista automatyka domowa
    Ja myślę, że za dużo nawalone jest w przerwaniu.
    Ja bym to napisał tak, że w przerwaniu ustawiałbym tylko flagę, a odczyt robiłbym w pętli głównej i to nie wszystkich czujników na raz tylko jeden na przerwanie, a potem następny itd.
  • #7 8057867
    Kuniarz
    Moderator Projektowanie
    Tak jest, sprawa zadania odczytu i konwersji danych nie jest tu problemem, kod jest poprawny.

    Starzy Chińczycy twierdzą, że zupa ogórkowa nigdy nie smakuje tak samo, uważają też, że każdy problem da się rozwiązać wnikliwie studiując literaturę...

    Panowie, problem tkwił w tym, że wywołanie przerwania zapisuje stan rejestrów, ale.... nie wszystkich ! Rejestry R13-R15, odpowiadające za zmienne SINGLE nie są zachowywane.
    Wystarczy dopisać POP i PUSH i sprawa rozwiązana.
    Informację tą znalazłem w mojej ulubionej książce Marcina Wiązani, poniżej wklejam działający kod - dla potomnych.

    
    $regfile = "m16def.dat"
    $crystal = 16000000
    $baud = 1200
    $hwstack = 150                                              'wartosc stosu
    $swstack = 150                                              'wartosc stosu
    
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7 , E = Portc.3 , Rs = Portc.2
    Cls
    Cursor Off Noblink
    Deflcdchar 0 , 12 , 18 , 18 , 18 , 12 , 32 , 32 , 32
    
    Config Timer0 = Timer , Prescale = 256                      'timer przerwania odczytu DSow
    Enable Interrupts
    Enable Ovf0
    On Ovf0 Przerwanie_0
    
    Dim T1 As Single                                            'temperatura
    Dim T2 As Single                                            'temperatura
    Dim T3 As Single                                            'temperatura
    Dim T4 As Single                                            'temperatura
    
    Dim T_pom_1 As Integer                                      'zmienna pomocnicza odczytu temperatury
    Dim T_pom_2 As Integer                                      'kolejna zmienna pomocnicza do przeliczania temperatury
    Dim T_pom_3 As Integer                                      'kolejna zmienna pomocnicza do przeliczania temperatury
    Dim T_pom_4 As Integer                                      'kolejna zmienna pomocnicza do przeliczania temperatury
    
    Dim Opoznienie As Byte
    Dim Licznik_opoznienia As Byte
    Dim Odczyt1 As Bit                                          'informacja, ze trwa odczyt (0-3 - numer DSa)
    Dim Numer_odcz As Byte                                      'numer aktualnie czytanego DSa
    
    Opoznienie = 255
    Odczyt1 = 0
    Numer_odcz = 1
    
    Licznik_opoznienia = Opoznienie
    
    Dim X As Byte                                               'zmienna pomocnicza
    Dim Y As Word                                               'zmienna pomocnicza 0-65535
    Dim Z1 As Byte                                              'zmienna pomocnicza migania
    Dim Z2 As Byte
    
    '*************************************************
    '***********  POCZĄTEK  PROGRAMU  ****************
    '*************************************************
    
    Set Porta.0
    Set Porta.1
    
    Do
    
    Locate 1 , 1
    Lcd Fusing(t1 , "#.#") ; Chr(0) ; "C"
    Locate 1 , 8
    Lcd Fusing(t2 , "#.#") ; Chr(0) ; "C"
    Locate 2 , 1
    Lcd Fusing(t3 , "#.#") ; Chr(0) ; "C "
    Locate 2 , 8
    Lcd Fusing(t4 , "#.#") ; Chr(0) ; "C "
    
    Loop
    
    End
    
    '**********************************
    '****    P R O C E D U R Y    *****
    '**********************************
    
    '*** obsługa przerwania 0
    '***********************************
    
    Przerwanie_0:
    '                                          odczyt temperatur z DSow
       push R12
       push R13
       push R14
       push R15
    
    Load Timer0 , 250
    If Odczyt1 = 0 Then
       Disable Timer0
       1wreset Pinb , 0
       1wwrite &HCC , 1 , Pinb , 0
       1wwrite &H44 , 1 , Pinb , 0
       1wreset Pinb , 1
       1wwrite &HCC , 1 , Pinb , 1
       1wwrite &H44 , 1 , Pinb , 1
       1wreset Pinb , 2
       1wwrite &HCC , 1 , Pinb , 2
       1wwrite &H44 , 1 , Pinb , 2
       1wreset Pinb , 4
       1wwrite &HCC , 1 , Pinb , 4
       1wwrite &H44 , 1 , Pinb , 4
    
       Enable Timer0
       Odczyt1 = 1
    End If
    Decr Licznik_opoznienia
    If Licznik_opoznienia > 0 Then
       Goto Wyj_ds_przerw
    End If
    
    Licznik_opoznienia = Opoznienie
    Disable Timer0
    1wreset Pinb , 0
    1wwrite &HCC , 1 , Pinb , 0
    1wwrite &HBE , 1 , Pinb , 0
    T_pom_1 = 1wread(2 , Pinb , 0)
    T1 = T_pom_1 / 16
    
    1wreset Pinb , 1
    1wwrite &HCC , 1 , Pinb , 1
    1wwrite &HBE , 1 , Pinb , 1
    T_pom_2 = 1wread(2 , Pinb , 1)
    T2 = T_pom_2 / 16
    
    1wreset Pinb , 2
    1wwrite &HCC , 1 , Pinb , 2
    1wwrite &HBE , 1 , Pinb , 2
    T_pom_3 = 1wread(2 , Pinb , 2)
    T3 = T_pom_3 / 16
    
    1wreset Pinb , 4
    1wwrite &HCC , 1 , Pinb , 4
    1wwrite &HBE , 1 , Pinb , 4
    T_pom_4 = 1wread(2 , Pinb , 4)
    T4 = T_pom_4 / 16
    
    Enable Timer0
    Odczyt1 = 0
    
    Wyj_ds_przerw:
       pop R15
       pop R14
       Pop R13
       pop R12
    Return
    
    Pomogłem? Kup mi kawę.
  • #8 8058055
    malon
    Poziom 14  
    Jak zawsze trzeba być dociekliwym, w tym przypadku tego mi zabrakło :cry: Zamiast pomóc Tobie, Ty pomogłeś mi :D: Dziękuję :!:
    Pozdrawiam
  • #9 8061214
    asembler
    Poziom 32  
    CIesze się że działa ale zaraz pojawi sie nastepny post pod tytułem odczytuje kilka DS-ów dlaczego nie działają mi inne rzeczy?
    Reasumując wydaje mi sie ze obsługa przerwania nie powinna byc taka długa powinna trwac mikrosek a nie milisek.
  • #10 8103271
    farrix
    Poziom 17  
    Ja pszepraszam że zadam pytanie nie na temat ale czy dało by się za pomocą 1wire skomunikować 2 proce, razem z czujnikiem?
  • Pomocny post
    #11 8104849
    wicy
    Poziom 22  
    Kuniarz, Jeszcze tylko spytam - czemu w obsłudze przerwania włączasz przerwanie timera i zaraz potem znów je wyłączasz? Nie lepiej wyłączyć na samym początku i włączyć na samym końcu?
  • #12 8104952
    Kuniarz
    Moderator Projektowanie
    wicy napisał:
    Kuniarz, Jeszcze tylko spytam - czemu w obsłudze przerwania włączasz przerwanie timera i zaraz potem znów je wyłączasz? Nie lepiej wyłączyć na samym początku i włączyć na samym końcu?


    a, przepraszam, to pozostało jeszcze z czasów eksperymentów ;-) W gotowym rozwiązaniu nie ma wyłączania przerwań w ich obsłudze, więc te linijki można po prostu wywalić.
    Pomogłem? Kup mi kawę.
  • #13 8122715
    asembler
    Poziom 32  
    farrix napisał:
    Ja pszepraszam że zadam pytanie nie na temat ale czy dało by się za pomocą 1wire skomunikować 2 proce, razem z czujnikiem?

    Dałoby się.
REKLAMA