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.

[Bascom][ATMega8]Przerwanie rozkłada transmisję 1wire

iXXL 20 Nov 2008 20:30 1871 9
  • #1
    iXXL
    Level 12  
    Zbudowalem sterownik do nagrzewnicy powietrza i od dluzszego czasu chodzi prawidlowo. Ostatnio z ciekawosci chcialem do niego dorzucic mozliwosc zliczania wlaczen wentylatora. Licznik wlaczen automatycznie zerowany co 24h.

    I tu pojawil sie problem, wlaczenie przerwania powoduje zaklocenia w odzczycie ds18b12 skutkiem czego dostaje dziwne odczyty.
    Przeniesienie procedury odczytu temperatury do procedury obslugi przerwania niewiele pomoglo.
    Timer cyka na wewnetrznym 1MHz z preskale8 , zmiana preskale na wyzszy troche pomaga, ale nie likwiduje problemu.
    Wylaczenie przerwan na czas odczytu pewnie rozwiaze problem, ale znowu zegar zacznie wariowac :(

    Poprawiłem tytuł i przeniosłem do właściwego działu.
    [zumek]
  • #2
    Klima
    Level 30  
    A nie masz li jakichś śmieci na tym przerwaniu? Poza tym, to 1wire jest czułe na opóźnienia i w czasie transmisji nie ma prawa pojawić się przerwanie (przynajmniej w tych krytycznych miejscach - na początku slotu czasowego).
  • #3
    dawid512
    Level 32  
    Mam nadzieję że inkrementujesz sobie jakąś zmienną która informuje o ilości włączeń wentylatora a potem ją resetujesz. Przerwanie od timera zakłóca ci odczyt z DS-a musisz sobie dodać flagę którą będziesz ustawiał lub resetował i będzie cię informować że właśnie zakończyło się przerwanie i masz jeszcze trochę czasu do następnego. W tym momencie musisz wykonać odczyt z DS-a. Jeśli piszesz w Bascomie to proponuję wykorzystać while i wend.
  • #4
    iXXL
    Level 12  
    dawid512 wrote:
    Mam nadzieję że inkrementujesz sobie jakąś zmienną która informuje o ilości włączeń wentylatora a potem ją resetujesz. Przerwanie od timera zakłóca ci odczyt z DS-a musisz sobie dodać flagę którą będziesz ustawiał lub resetował i będzie cię informować że właśnie zakończyło się przerwanie i masz jeszcze trochę czasu do następnego. W tym momencie musisz wykonać odczyt z DS-a. Jeśli piszesz w Bascomie to proponuję wykorzystać while i wend.


    Oczywiscie, mam zmienna.
    Jak rozumiem, odzczyt moze sie odbywac tylko w czasie miedzy jednym a drugim przerwaniem ?
    jak by wygladal szkielet takiego zalozenia ? bo nie mialem dotad takiego problemu do rozwiazania...
  • #5
    dawid512
    Level 32  
    Np. tak:
    Code:
    Set Flaga : While Flaga = 1 : Wend
    to umieszczasz raz lub kilkakrotnie w odczycie z DS-a. Część umieszczona poniżej tego wykona się dopiero jeśli flaga zostanie zresetowana. Flagę resetujesz po wykonaniu przerwania.
  • #6
    iXXL
    Level 12  
    Czy to miales na mysli :

    Code:
    Set Flaga
    
    While Flaga = 1
    1wreset Pind , 2
    1wwrite &HCC , 1 , Pind , 2
    1wwrite &H44 , 1 , Pind , 2
    Waitms 255
    Licz_temp = 0
    1wreset Pind , 2
    1wwrite &HCC , 1 , Pind , 2
    1wwrite &HBE , 1 , Pind , 2
    B1 = 1wread(1 , Pind , 2)
    B2 = 1wread(1 , Pind , 2)
    Wend


    przerwanie resetuje flage, wiec efekt jest ten sam jakby jej nie bylo...
  • #7
    iXXL
    Level 12  
    Utul wrote:
    Witam
    dawid512 wrote:
    Śmiem zapytać co to za zapis:
    Code:
    1wwrite &HCC , 1 , Pind , 2 
    ?


    No raczej wszystkie linie związane z odczytem i zapisem do DS'a są krótko mówiąc zje****.

    Pozdro


    Moze i tak, nie twierdze ze jestem orlem, daleki jestem nawet od powiedzenia ze 'umiem' ;)
    Podlaczone mam 2 czujniki (na d.2 i d.3) i w ten sposob odwoluje sie do kazdego z nich.

    narazie poradzilem sobie tak:

    Code:

    $regfile = "m8def.dat"
    $crystal = 1000000
    Deflcdchar 0 , 4 , 10 , 4 , 32 , 32 , 32 , 32 , 32          ' replace ? with number (0-7)
    Deflcdchar 1 , 32 , 4 , 4 , 4 , 4 , 4 , 32 , 32             ' replace ? with number (0-7)
    Deflcdchar 2 , 32 , 1 , 2 , 4 , 8 , 16 , 32 , 32            ' replace ? with number (0-7)
    Deflcdchar 3 , 32 , 32 , 32 , 31 , 32 , 32 , 32 , 32        ' replace ? with number (0-7)
    Deflcdchar 4 , 32 , 16 , 8 , 4 , 2 , 1 , 32 , 32            ' replace ? with number (0-7)
    Config Lcdpin = Pin , Db4 = Portc.2 , Db5 = Portd.6 , Db6 = Portb.2 , Db7 = Portb.1 , E = Portb.0 , Rs = Portd.7
    Config Timer0 = Timer , Prescale = 8 : Enable Interrupts : Enable Timer0
    On Timer0 Zegar
    Config Lcd = 16 * 2
    Config 1wire = Portd.2 : Config 1wire = Portd.3
    Config Portd.5 = 1 : Portd.5 = 1
    Dim B1 As Byte : Dim B2 As Byte : Dim R As Byte : Dim Znak As String * 1 : Dim Tmp As String * 4
    Dim T1 As Single : Dim T2 As Single : Dim Tu As Single : Dim Tu1 As Single
    Dim Sek As Byte : Dim Minu As Byte : Dim Godz As Byte : Dim Setne As Word       'zmienne dla zegara
    Dim Wl_przek As Byte : Dim Flaga As Bit
    Dim Anim As Byte
    Flaga = 0
    R = 255
    Tu = 28 : Tu1 = Tu + 2
    Sek = 0 : Minu = 22 : Godz = 22 : Setne = 0
    Wl_przek = 0 : Flaga = 0 : Anim = 1
    Cursor Off
    Cls
    Do
    Disable Interrupts
    1wreset Pind , 2
    1wwrite &HCC , 1 , Pind , 2
    1wwrite &H44 , 1 , Pind , 2
    Enable Interrupts
    Waitms 500
    1wreset Pind , 2
    1wwrite &HCC , 1 , Pind , 2
    1wwrite &HBE , 1 , Pind , 2
    B1 = 1wread(1 , Pind , 2)
    B2 = 1wread(1 , Pind , 2)
    If Flaga = 1 Then
       Locate 1 , 14 : Lcd Wl_przek
       Locate 2 , 14 : Lcd Chr(anim)
       Incr Anim
       If Anim = 5 Then Anim = 1
    Else
       Anim = 1
       Locate 2 , 14 : Lcd " "
    End If
    Upperline
    Lcd "temp.:"
    Lowerline
    Lcd "ust. : " ; Tu ; Chr(0) ;
    Locate 1 , 7
    'prcedura przeliczajaca temperature z czujnikow DS18B20
    If B2 >= 248 Then
    B1 = R - B1
    B2 = R - B2
    Znak = "-"
    Else
    Znak = " "
    End If
    T1 = B1 / 16
    T2 = B2 * 16
    T1 = T1 + T2
    T1 = T1 + 0.05
    If T1 < Tu Then
       Portd.5 = 0
       If Flaga = 0 Then
          Flaga = 1
          Wl_przek = Wl_przek + 1
       End If
    End If
    If T1 > Tu1 Then
        Portd.5 = 1
        Flaga = 0
    End If

    Tmp = Fusing(t1 , "##.&")
    If T1 > 99.999 Then
    Lcd Tmp ; Chr(0) ;
    Else
          If T1 > 9.999 Then
          Lcd Znak ; Tmp ; Chr(0) ;
          Else
          Lcd Znak ; " " ; Tmp ; Chr(0) ;
          End If
    End If
    Loop

    Zegar:
    Timer0 = 12
    Incr Setne
    If Setne = 500 Then
       Incr Sek
       Setne = 0
    End If
    If Sek = 60 Then
       Sek = 0
       Incr Minu
       If Minu = 60 Then
          Minu = 0
          Incr Godz
          If Godz = 24 Then
             Godz = 0
             Wl_przek = 0                                       'co 24 godziny zeruj licznik wlaczen przekaznika
          End If
       End If
    End If
    Return
    End


    niby chodzi....ale

    po pierwsze, nie lubie rozkazu 'waitms' , probowalem go zastapic zmienna incrementowana w przerwaniu i petla if....then , niestety nie dalem rady, pomimo ze teoretycznie czas incrementowania zmiennej do spelnienia warunku wyniosl 400ms.
    Po drugie, czy zatrzymanie przerwan nawet na tak krotki okres nie spowoduje opoznien w pracy zegara ?
  • #8
    Michał_z1
    Level 16  
    witam.
    Po pierwsze podczas "gadania" z DSem wyłącz przerwania (na czas konwersji temperatury znów je włacz oczywiście), nie możesz bowiem transmisji 1wire zakłucać przerwaniami, w reszcie działania programu przerwania zostaw włączone, po drugie zatrzymania przerwań moą mieć wpływ na pracę zegara....będzie się późnić.
    A może by tak odczytywać DSa co minutę wykorzystując istniejący w programie zegar??
    pozdrawiam.
  • #9
    dawid512
    Level 32  
    Jeżeli będziesz wyłączał przerwania to tak pisał kolega wyżej zakłócisz pracę zegara. W podprogramie który wykonuje się podczas przerwania od timera na końcu zresetuj flagę. Potem w odpowiednich miejscach obsługi DS-a wstawiaj
    Code:
    Set Flaga : While Flaga = 1 : Wend
    w takiej postaci!
    Wtedy gdy zakończy się przerwanie kod umieszczony poniżej tego który podałem wykona się w przeciwnym wypadku będzie czekał aż przerwanie się zakończy.
  • #10
    Michał_z1
    Level 16  
    witam ponownie.
    Innym wyjściem jest zastosowanie przerwania z TIMER1 (16bit.) z preskalerem 1024, oraz ustawienie wartości początkowej po każdym przerwaniu na 55770, wtedy przerwanie będzie realizowane co 1,00003800 s, więc zdążysz ze wszystkim, a jeśli jeszcze wywołasz sprawdzenie temperatury zaraz po wykonaniu przerwania wtedy już napewno zegar będzie dokładny (nie spowoduje to zatrzymań zliczania podczas blokowania przerwania).
    pozdrawiam.