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

[Atmega16][BASCOM] Odbiór RC5 w przerwaniu - niestabilny

klops_mops 06 Wrz 2009 19:10 4061 10
REKLAMA
  • #1 6987882
    klops_mops
    Poziom 17  
    Witam. Napisałem sobie prosty program by odbierał rc5 i wysyłał komendę oraz adres przez rs232. Niby to działa, ale nie do końca, tzn. naciskając przyciski pilota rozpoczyna się transmisja rs232, ale oto co dostaję:
    
    31  ---  255
    31  ---  255
    31  ---  255
    0  ---  3
    0  ---  3
    0  ---  3
    0  ---  3
    0  ---  3
    0  ---  3
    0  ---  3
    0  ---  3
    0  ---  3
    0  ---  3
    31  ---  255
    31  ---  255
    31  ---  255
    31  ---  255
    0  ---  2
    31  ---  255
    31  ---  255
    0  ---  2
    0  ---  2
    31  ---  255
    31  ---  255
    0  ---  5
    31  ---  255
    31  ---  255
    31  ---  255
    31  ---  255
    0  ---  4
    31  ---  255
    31  ---  255
    31  ---  255
    31  ---  255
    31  ---  255
    31  ---  255
    31  ---  255
    31  ---  255
    31  ---  255
    31  ---  255
    31  ---  255
    31  ---  255
    0  ---  15
    31  ---  255
    

    Jak widać, bardzo często pojawia się 31 --- 255 - dlaczego?

    Program:
    
    $regfile = "m16def.dat"
    $crystal = 16000000
    $baud = 4800
    
    Config Rc5 = Pind.2
    
    On Int0 Odbierz_rc5
    Enable Int0
    Enable Interrupts
    
    Config Portc.0 = Output
    Config Portc.1 = Output
    
    Dim Odebrano As Bit
    Dim Komenda As Byte , Adres As Byte
    
    Set Portc.0
    Set Portc.1
    
    Do
      If Odebrano = 1 Then
         Odebrano = 0
         Print Adres ; "  ---  " ; Komenda
         Enable Int0
      End If
    Loop
    End
    
    Odbierz_rc5:
      Disable Int0
      Enable Interrupts
      Reset Portc.1
      Getrc5(adres , Komenda)
      Adres = Adres And &B00011111
      Odebrano = 1
    Return
    


    Inne informacje:
    Odbiór bez przerwania (w pętli głównej) działa, program wgrywam bootloaderem (megaload), kwarc dobry, pilot na 100% rc5, ustawienia fusów:
    hFuse D0
    lFuse EF

    Z góry dziękuje za pomoc.
  • REKLAMA
  • Pomocny post
    #2 6988056
    mirekk36
    Poziom 42  
    a przejrzał kolega chociaż raz przykład odbioru RC5 z helpa Bascoma ??? oczywiście tam nie jest on w przerwaniu ale to nic. Za to są takie rzeczy jak:

    - maskowanie tooglebitu
    - sprawdzanie czy adres jest np = 0 - co oznacza pilota TV albo przynajmniej jakiś warunek czy adres < 255 - bo inaczej to będzie taki klops właśnie jaki u ciebie występuje

    generalnie jak się zrobi dobrze procedurę odbioru w bascomie zgodnie chociażby z helpem to to zawsze ale to zawsze działa dobrze wręcz idealnie
  • #3 6988221
    klops_mops
    Poziom 17  
    Ok dodałem warunek na adres, maskowanie :) Teraz wysyła tylko te "sensowne" dane;
    
    0  ---  5
    0  ---  4
    0  ---  5
    0  ---  3
    0  ---  6
    0  ---  12
    0  ---  33
    0  ---  16
    0  ---  0
    0  ---  7
    0  ---  7
    0  ---  7
    


    Czasem jednak zdarzy się tak, że nie "załapie" każdego przyciśnięcia. Możliwe, że to wynika ze zwykłego trafienia wiązki. Ale jest ok.
    A helpa czytałem, w sumie nie tylko go, bo jeszcze google też używałem i znalazłem kilka kodów :)

    Dzięki Mirek, za pomoc ;)
  • REKLAMA
  • #4 6988314
    mirekk36
    Poziom 42  
    nie wiem jakiego odbiornika podczerwieni używasz, ja zwykle te typu TFMSxxxx i muszę przyznać, że one mają kąt widzenia wiązki chyba ze 360st ;)

    natomiast jeśli czasem nie "złapie" jak mówisz niektórego naciśniecia klawisza to może częściej oznaczać tylko to, że gumki w pilocie są hmm nie wiem, starte, zabrudzone i coś źle stykają...... rozbierz, przemyj spirtem i zapewne się polepszy ;)
  • REKLAMA
  • #5 6989019
    klops_mops
    Poziom 17  
    Ok, a teraz jeszcze jedna sprawa:
    Zmodyfikowałem trochę program by wyświetlał na multipleksowanych wyświetlaczach LED 4x7 odebraną komendę. Jak zwykle trochę chodzi, ale nie do końca - założenie jest takie: odbiera komendę z rc5 i wyświetla ją na led, efekt jaki uzyskuję: odbiera komendę, wyświetla na ułamek sekundy, potem wyświetla 95, czasem się zdarzy, że dłużej "trzyma" ta prawidłową wartość.
    
    $regfile = "m16def.dat"
    $crystal = 16000000
    $baud = 4800
    
    Config Rc5 = Pind.2
    Config Timer2 = Timer , Prescale = 256
    Config 1wire = Portd.7
    
    Declare Sub Pobr_znaku(cyfra As Byte)
    
    On Timer2 Mult_wysw
    On Int0 Odbierz_rc5
    
    Dim A As Byte , B As Byte , C As Byte , D As Byte
    Dim Adres As Byte , Komenda As Byte
    Dim Nr_wysw As Byte
    Dim Pokaz As Byte
    Dim Odebrano As Bit
    Dim Wart As Byte
    
    Config Pina.0 = Output
    Config Pina.1 = Output
    Config Pina.2 = Output
    Config Pina.3 = Output
    Config Portb = Output
    
    W1 Alias Porta.0
    W2 Alias Porta.1
    W3 Alias Porta.2
    W4 Alias Porta.3
    
    Enable Int0
    Enable Interrupts
    
    Enable Timer2
    Load Timer2 , 125
    
    
    C = 10
    D = 10
    
    
    Do
    
    If Odebrano = 1 Then
    Odebrano = 0
    
    If Adres = 0 Then
    
    Print Adres ; "  ---  " ; Komenda
    End If
    
    Wart = Komenda
     Wart = Makebcd(wart)
     B = Wart And &B00001111
     Shift Wart , Right , 4
     A = Wart
     C = 10
    D = 10
    
    Enable Int0
    End If
    Loop
    
    
    
    Sub Pobr_znaku(cyfra As Byte)
     If Cyfra < 10 Then
      Portb = Lookup(cyfra , Kody7seg )
     Else
      Portb = &B11111111
     End If
    End Sub
    
    
    
    Mult_wysw:
     Load Timer2 , 125
     Set W1
     Set W2
     Set W3
     Set W4
     Select Case Nr_wysw
    
      Case 0:
       Call Pobr_znaku(a)
    
       Reset W1                                                 'włączenie wyświetlacza 1
      Case 1:                                                   'gdy Nr_wysw = 1, to
       Call Pobr_znaku(b)                                       'wywołanie procedury
    
       Reset W2                                                 'włączenie wyświetlacza 2
      Case 2:                                                   'gdy Nr_wysw = 2, to
       Call Pobr_znaku(c)                                       'wywołanie procedury
    
       Reset W3                                                 'włączenie wyświetlacza 3
      Case 3:                                                   'gdy Nr_wysw = 3, to
       Call Pobr_znaku(d)                                       'wywołanie procedury
    
       Reset W4                                                 'włączenie wyświetlacza 4
     End Select                                                 'koniec instrukcji wyboru
     Incr Nr_wysw
     If Nr_wysw = 4 Then
      Nr_wysw = 0                                               'zeruj wartość Nr_wysw
     End If
    Return
    
    
    Odbierz_rc5:
      Disable Int0
      Enable Interrupts
      Getrc5(adres , Komenda)
      Adres = Adres And &B01111111
      Odebrano = 1
    Return
    
    End
    
    Kody7seg:
    Data 129 , 243 , 73 , 97 , 51 , 37 , 5 , 241 , 1 , 33
    


    Co napisałem nie tak?
    Zastanawia mnie jeszcze jak by do tego "dorzucić" odczyt temperatury z DS1820/DS18B20? Może w przerwaniu?

    Możliwe jest, że te błędy powstają, bo program wgrywam bootladerem, lub Atmega była już programowana sporo razy?
  • Pomocny post
    #6 6989246
    mirekk36
    Poziom 42  
    programu to ja ci już nie przeanalizuję teraz bo padnięty jestem .....

    .... ale to że wgrywasz bootloaderem i że atmega była programowana wiele razy - nie ma tu najmniejszego znaczenia

    Dodano po 22 [minuty]:

    ok - po pierwsze nie stosujesz wcięć w kodzie a jak stosujesz to totalnie bez ładu - przez co nawet tobie trudno później dostrzec jakieś błędy (a szczególnie komuś obcemu tzn nie autorowi kodu) - a dobrze i przejrzyście napisany program to podstawa. Bo co to np jest??? :

    Do 
    
    If Odebrano = 1 Then 
    Odebrano = 0 
    
    If Adres = 0 Then 
    
    Print Adres ; "  ---  " ; Komenda 
    End If 
    
    Wart = Komenda 
     Wart = Makebcd(wart) 
     B = Wart And &B00001111 
     Shift Wart , Right , 4 
     A = Wart 
     C = 10 
    D = 10 
    
    Enable Int0 
    End If 
    Loop 

    jak dla mnie to jakieś pomieszanie z poplątaniem ;)

    pytałem się ciebie o to czy korzystasz z helpa a ty nadal w nowym kodzie z uporem godnym podziwu maskujesz (zaraz po odebraniu kodu z pilota) adres "Adres = Adres And &B01111111 " zamist komendę - to po pierwsze

    .... po drugie jak już korzysta się z flagi w pętli głównej to powinien być jakiś jasny i czytelny z odpowiednimi wcięciami warunek IF, a flagę zwykle resetuje się pod koniec wykonywania warunku. A u ciebie znowu plątanina tzn:

    - najpierw zerujesz swoją flagę Odebrano
    - potem w oparciu o prawidłowy adres (i dobrze) gdy = 0 - wysyłasz daną na RS232 - ale tu warunek się kończy !!!! (bez sensu) żeby po nim zacząć swoje przekładanki komendy na wartość na wyświetlaczu

    i tak dziwię się że masz jakieś powtarzalne rezulaty - skoro nie maskujesz tooglebitu w komendzie. Na prawdę się dziwię dlaczego nie zajrzałeś do helpa nadal odnośnie getrc5 - tylko nie mów że zajrzałeś - co nawyżej na szybciora rzuciłeś pobieżnie okiem bo cały czas używasz czegoś takiego:

    Adres = Adres And &B01111111


    a w helpie jest jak wół napisane:

    Command = Command And &B01111111


    co oznacza że toogle bit - siedzi w command a nie w address - co można wywnioskować nie tylko z opisu w helpie ale także z tego polecenia nie mówiąc już o pczeczytaniu standardu kodowania RC5 ;)

    zanim więc zabierzesz się za odczyty temperatury z DS18xxxx - to najpierw doprowadź to co masz z RC5 do 100% porządku
  • #7 6992753
    klops_mops
    Poziom 17  
    Wielkie dzięki Mirek za rady :)
    Co do tego helpa - czytałem ale nie kopiowałem kodu. Nie zauważyłem, że maskuje ten bit nie na tym, co trzeba....

    Zmodyfikowałem trochę kod, uwzględniając Twoje sugestie, teraz wszystko wydaje się działać ok - komendy bez problemu są wyświetlane na wyś. led..
    Jedyne co mi nie pasuje - gdy dodam funkcje print, to wyświetlacz na ułamek sekundy (podczas wysyłania po rs232) mrugnie trzema pierwszymi cyframi.. Natomiast, gdy nie ma tej funkcji wszystko chodzi ok.
    
    ' ################### KONFIGURACJA ###################
    $regfile = "m16def.dat"
    $crystal = 16000000
    $baud = 4800
    
    Config Rc5 = Pind.2
    Config Timer2 = Timer , Prescale = 256
    Config 1wire = Portd.7
    
    Declare Sub Pobr_znaku(cyfra As Byte)
    
    On Timer2 Mult_wysw
    On Int0 Odbierz_rc5
    
    'deklaracja zmiennych
    Dim A As Byte , B As Byte , C As Byte , D As Byte
    Dim Adres As Byte , Komenda As Byte
    Dim Nr_wysw As Byte
    Dim Pokaz As Byte
    Dim Odebrano As Bit
    Dim Wart As Byte
    
    'konfiguracja pracy portow
    Config Pina.0 = Output
    Config Pina.1 = Output
    Config Pina.2 = Output
    Config Pina.3 = Output
    Config Portb = Output
    
    'przypisanie aliansow na poszczegolne wyswietlacze
    W1 Alias Porta.0
    W2 Alias Porta.1
    W3 Alias Porta.2
    W4 Alias Porta.3
    
    Enable Int0
    Enable Interrupts
    
    Enable Timer2
    Load Timer2 , 125
    
    
    C = 10                                                      'wylaczenie wys. 3
    D = 10                                                      'wylaczenie wys. 4
    
    
    ' ################### POCZATEK GLOWNEJ PETLI ###################
    Do
      If Odebrano = 1 Then
         If Adres = 0 Then
    
            Komenda = Komenda And &B01111111
            'Print Adres ; "  ---  " ; Komenda                   'gdy jest print, to wyswietlacze na chwile mrugna...
    
            Wart = Komenda
            Wart = Makebcd(wart)
            B = Wart And &B00001111
            Shift Wart , Right , 4
            A = Wart
            C = 10
            D = 10
         End If
    
         Odebrano = 0
         Enable Int0
      End If
    Loop
    ' ################### KONIEC GLOWNEJ PETLI ###################
    
    
    
    
    ' ################### MULTIPLEKSOWANIE ###################
    Sub Pobr_znaku(cyfra As Byte)
        If Cyfra < 10 Then
           Portb = Lookup(cyfra , Kody7seg )
        Else
           Portb = &B11111111
        End If
    End Sub
    
    
    
    Mult_wysw:
     Load Timer2 , 125
     Set W1
     Set W2
     Set W3
     Set W4
     Select Case Nr_wysw
    
      Case 0:
       Call Pobr_znaku(a)
    
       Reset W1
      Case 1:
       Call Pobr_znaku(b)
    
       Reset W2
      Case 2:
       Call Pobr_znaku(c)
    
       Reset W3
      Case 3:
       Call Pobr_znaku(d)
    
       Reset W4
     End Select
     Incr Nr_wysw
     If Nr_wysw = 4 Then
        Nr_wysw = 0
     End If
    Return
    ' ################### KONIEC MULTIPLEKSOWANIA ###################
    
    
    
    
    ' ################### ODBIERANIE RC5 W PRZERWANIU ###################
    Odbierz_rc5:
      Disable Int0
      Enable Interrupts
      Getrc5(adres , Komenda)
    
      Odebrano = 1
    Return
    ' ################### KONIEC RC5 ###################
    
    
    
    End
    ' ################### KODY WYSWIETLACZA ###################
    Kody7seg:
    Data 129 , 243 , 73 , 97 , 51 , 37 , 5 , 241 , 1 , 33
    

    Czy ten program jest już poprawnie napisany?
  • REKLAMA
  • Pomocny post
    #8 6992857
    mirekk36
    Poziom 42  
    klops_mops ---> masz dwa wyjścia żeby ci nie mrugały te wyświetlacze w czasie PRINT'a ;) - innymi słowy mówiąc aby procedura wysyłania RS232 nie zakłócała procedury multipleksowania

    1. prostszy sposób - zwiększ tą kocią prędkość RS232 na jakąś ludzką - chociaż 9600bps to już praktycznie nie powinno ci mrugać a jak dasz każdą większą to już będzie coraz lepiej. Tylko po co ci taki kwarc 16MHz jeśli korzystasz z RS232. Daj jakiś przyjazny kwarc dla RS232 - czyli np 11.059200MHz a jak już aaaaaż tak koniecznie potrzebujesz tak wielkiej szybkości - chociaż dotychczasowy projekt na to nie wskazuje to weź kwarc 18.432MHz. Wprawdzie troszkę przetaktujesz procka - ale gwarantuję ci że się nic nie stanie - za to z każdym z tych wymienionych kwarców będziesz mógł ustawić sobie prędkość transmisji 115200bps i będzie chodziło jak brzytwa i po ludzku

    2. sposób - też mało skomplikowany - to zainteresuj się poleceniem Config serialout i utworzeniem bufora nadawczego szczególnie właśnie jak na upartego będziesz chciał korzystać z tak kocich nieludzko wolnych i dawno nie używanych prędkości RS232 ;)
  • #9 6993079
    klops_mops
    Poziom 17  
    Kwarc 16Mhz, widnieje tam tylko, z tego względu, że taki znajduje się na mojej płytce testowej.. :)
    Nawet teraz, gdy ustawię
    
    $baud = 115200
    

    to nie ma błędów transmisji, a i multipleksowanie działa wzorowo :)
    Więc w docelowym projekcie zastosuję kwarc 11.059200MHz.

    Nasuwa mi się jeszcze jedno pytanie:
    Czy odczyt temperatury z DS18xxx, mogę zrealizować w przerwaniu, wykonywanym co 1sek, z użyciem Timera1?
  • #10 6993133
    mirekk36
    Poziom 42  
    klops_mops napisał:

    Nasuwa mi się jeszcze jedno pytanie:
    Czy odczyt temperatury z DS18xxx, mogę zrealizować w przerwaniu, wykonywanym co 1sek, z użyciem Timera1?


    widzę, że już trochę programujesz i robisz różne rzeczy na elektrodzie - to powinieneś wiedzieć - że nigdy nie daje się żadnych długotrwałych operacji w przerwaniach - nigdy ale to nigdy! ;)

    stosuj flagi - tak jak już do tej pory zastosowałeś
REKLAMA