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

Atmega16 "wykrzacza sie" - obsługa RC5 w przerwan

gothye 31 Sie 2007 20:26 2360 7
  • #1 31 Sie 2007 20:26
    gothye
    Poziom 33  

    jest tak :

    atmega16 odczytuje kod rc5 w przerwaniach ( Int0 ) wraz z odczytem temp z wire czujnika DS1820,całosc pracuję ok ,hmm ale nie do konca , w pewnym momencie Atmega się resetuję lub pokazuję na LCD dziwne znaki "krzaczki" co może by tego powodem :(

    [/code]

    0 7
  • #2 31 Sie 2007 22:29
    lelekx
    Poziom 29  

    A co się stanie, jeżeli podczas zapisu do LCD przez procedurę Temp zostanie zgłoszone przerwanie? Wówczas do LCD popłyną przypadkowe rozkazy, czego skutkiem może być to, co opisujesz. Dobrze zrobisz, jeżeli usuniesz z przerwania obsługę LCD i zlecisz ją procedurze poza przerwaniem. Do tego będziesz potrzebować dwóch zmiennych: pierwsza zawierająca tekst do wyświetlenia i druga jako znacznik chęci wyświetlenia informacji z przerwania.

    0
  • #3 02 Wrz 2007 16:31
    gothye
    Poziom 33  

    niebardzo wiem jak wprowadzic "nowe" zmienne o których piszesz :(

    Dodano po 4 [godziny] 25 [minuty]:

    znalazłem przyczyne resetowania i dziwnych znaczków na lcd

    resetowanie uC powoduje pilot od Tv daewoo ( nie rc5 )

    dziwne znaczki na LCD następują tylko wtedy gdy uC niemoze rozpoznac komendy z pilota rc5 ( niewiem czemu) ,podczas uzywania pilota od cambrige audio następuję to samo (równierz nie Rc5 )

    na układnie bez przerwan into dla rc5 niema takich obijawów :(

    mozna temu w jakis sposób zapobiec :?:

    0
  • #4 02 Wrz 2007 22:40
    redart
    Poziom 23  

    Ja zrobiłbym to w ten sposób:

    Code:
    Set Odebr_kod 
    

    Do
       If Odebr_kod = 0 Then
          Locate 2 , 1
          Lcd "Command: " ; Command
          Odebr_kod = 1
       End If
    Temp_write
    Temp
    Loop


    Pobr_rc5:                                                   'podprogram przerwania Int0
       Disable Int0
       Enable Interrupts                                   
       Getrc5(address , Command)
       Command = Command And &B01111111 
       En = En1                                                 ' po co to ???
       If Address <> 255 Then
          Odebr_kod = 0
       End If
       Enable Int0
    Return


    Przede wszystkim należy wywalić wyświetlanie z procedury obsługi przerwania, pchanie tam takich głupot prowadzi na manowce. Sama procedura powinna być zawsze jak najprostrza i przejrzysta, a co za tym idzie szybka w wykonaniu. Procek może do niej skakać i 100 razy na sec, a tobie wystarczy odświeżanie informacji na lcd ok 5-8 razy na sec, bo więcej graniczy z możliwościami ludzkiej percepcji.
    Ponadto masz zmienną Odebr_kod której nie wykorzystujesz: dlatego należy ją zaprząc do wskazywania czy istnieje jakiś odebrany ale nie wyświetlony kod. Zmienna ta jest ustawiona jeśli nie odebrano poprawnego kodu lub jeśli został on jużwyświetlony w głównej pętli, zaś wyzerowana jeśli jest jakaś informacja do wyświetlenia.
    Ponadto wstawianie opóźnienia 100ms mija się z celem: w trakcie wykonywania tej funkcji procek 'nie żyje'. Aby zapobiec skokom do obsługi przerwania w przypadku przytrzymania przycisku na pilocie proponuję odblokowywać INT0 (Enable Int0) dopiero po wyświetleniu kodu w głównej pętli, nie zaś pod koniec procedury obsługi przerwania.
    Pzdr.

    0
  • #5 02 Wrz 2007 23:00
    gothye
    Poziom 33  

    a jesli powiem ze tak tez próbowałem tylko ze odczyt z kodów z rc5 trwa z przerwą 600ms która musi byc pomiedzy odczytem a konwersją temperatury z ds1820
    :(

    0
  • Pomocny post
    #6 02 Wrz 2007 23:51
    redart
    Poziom 23  

    gothye napisał:
    a jesli powiem ze tak tez próbowałem tylko ze odczyt z kodów z rc5 trwa z przerwą 600ms która musi byc pomiedzy odczytem a konwersją temperatury z ds1820
    :(


    Jakoś nie widzę problemu. Przecież Int0 ma wyższy priorytet niż DS. Jerśli istnieją jakieś konflikty to należy zablokować przerwanie Int0 na czas inicjacji DS'a i odczytu temperatury. W trakcie konwersji (≈750ms) kody będą odbierane. Jaki ma to mieć wpływ na IR?

    Sory nie dopatrzyłem się tego Waitms 600...
    Nic dziwnego, że się krzaczy jeśli zatrzymujesz procka na taki czas. Zamiast tego proponuję zastosować Timer do odmierzania 750ms, a jego wartość sprawdzać w pętli głównej. Po odliczeniu założonego czasu warunkowo skakać do procedury odczytu temp. Nie wiem jakie masz źródło zegara, ale np dla kwarcu 16MHz wartości przedstawiają się następująco:

    Code:
    Config Timer1 = Timer , Prescale = 1024
    
    Timer1 = 0
    Start Timer1

    Do   
       If Timer1 > 11717 Then Gosub Temp        '(16mln / 1024) *0,75sec =11718,75
       If Timer1 = 0 Then Gosub Temp_write
       If Odebr_kod = 0 Then
          Locate 2 , 1
          Lcd "Command: " ; Command
          Odebr_kod = 1
       End If
    Loop


    Pobr_rc5:                                                   'podprogram przerwania Int0
       Disable Int0
       Enable Interrupts                                   
       Getrc5(address , Command)
       Command = Command And &B01111111 
       En = En1                                               
       If Address <> 255 Then
          Odebr_kod = 0
       End If
       Enable Int0
    Return

    Sub Temp_write
       1wreset
       1wwrite &H55
       1wverify Dsid1(1)                                        'wysyłamy adres pierwszego czujnika
       1wwrite &HBE
       I1 = 1wread(2)
       1wreset
       1wwrite &H55
       1wverify Dsid2(1)                                        'wysylam adres drugiego czujnika
       1wwrite &HBE
       I2 = 1wread(2)
    'Konwersja Temp Dla Wszystkich Ds
       1wreset
       1wwrite &HCC
       1wwrite &H44
    Timer1 = 1
    End Sub Temp_write

    Sub Temp
       Cls
       I1 = I1 * 10.5
       I1 = I1 / 2
       Ss = Str(i1)
       Ss = Format(ss , " 0.0")
       Locate 1 , 1                                             'Pozycja wyświetlania nazwy i temperatury (1.1 -> 1 linia 1 kolumna, 2.10 -> 2 linia 10 kolumna itd)
       Cls
       Lcd "L " ; Ss ; "C       TEMP" ;
       I2 = I2 * 10.5
       I2 = I2 / 2
       Ss = Str(i2)
       Ss = Format(ss , " 0.0")
       Locate 1 , 15
       Lcd "R " ; Ss ; "C"
       Timer1 = 0
    End Sub Temp


    Zawsze stosuję taki sposób odmierzania czasu dla DS'ów, szczególnie jeśli wykorzystuję przerwania. W taki rozwiązaniu Timer1 nie generuje przerwania po przepełnieniu, więc nie gmatwa Int0. Nie jest to najbardziej elegancki ani efektywny (pętle If...Then) sposób odmierzania czasu, ale nie o precyzję tu chodzi, tylko o 'odetkanie' procka z tych 600ms.
    Pzdr.

    0
  • #7 03 Wrz 2007 17:13
    gothye
    Poziom 33  

    redart

    wykorzystanie timer1 do odczytu temp z ds'a jest rewelacyjne :!:

    przerobiłem program do swoich potrzeb (wywaliłem rc5 z przerwania )

    niesamowita ulga ,w prezencie dostajesz +100pkt odemnie :)

    dziekuję za pomoc

    0
  • #8 03 Wrz 2007 20:22
    redart
    Poziom 23  

    No to pogratulować sukcesu.
    A z tymi punktami to przegiąłeś - nie robię tego 'dla mamony'...
    Pzdr.

    0