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

[ATmega8][BASCOM] Przerwania z timera a odczyt z UARTa

m4jkel 20 Sie 2008 23:14 3064 4
REKLAMA
  • #1 5458104
    m4jkel
    Poziom 12  
    Witam

    Piszę na atmedze8 w bascomie program do odczytywania danych z odbiornika GPS. GPS jest podłączony RSem do Atmegi, obsługuje go sprzętowy UART. Transmisja jest realizowana z prędkością 4800, megę taktuje zewnętrzny kwarc 7,3728 Mhz (ale na wewnętrzym 4 Mhz też próbowałem).

    Oto kod obcięty o parę chwilowo nieistotnych rzeczy (definicje zmiennych, $crystal, $baud):

    
    Config Serialin = Buffered , Size = 80
    Enable Interrupts
    
    Config Timer1 = Timer , Prescale = 64
    Enable Timer1 : On Timer1 Co1s
    
    Cls
    
    Do
      If Ischarwaiting() = 1 Then                               
        Znak = Inkey()
        Print Chr(znak) ;
      End If
    Loop
    End
    
    
    Co1s:
      Cls
      Timer1 = 3036
      Locate 1 , 1
      Lcd "a"
    Return
    


    Sprawa wygląda prosto. GPS nadaje co 1 sekundę taki ciąg danych:
    $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A

    Program odczytuje z bufora kolejne znaki i wysyła je na Tx, celem sprawdzenia co tak naprawdę odczytuje. Tx Atmegi podłączyłem do komputera i widzę dane na terminalu.

    Jeśli przerwanie jest wyłączone wszystkie dane ładnie przechodzą. Jeśli tylko włączę przerwanie, a w nim użyję np. funkcji LCD do pisania na wyświetlaczu, cześć danych co jakiś czas się gubi. Im dłuższy tekst wysyłam do wyświetlacza lub im częściej licznik się przepełnia tym więcej danych gubię. Jak rozumiem chodzi o to, że przerwanie timera ma większy priorytet niż te od UARTA, więc co jakiś czas UART gubi napływające dane.

    Jak w takim razie zrobić, żebym mógł korzystać z timera, a UART odbierał wszystkie dane?

    Pozdrawiam,
    m4jkel
  • REKLAMA
  • REKLAMA
  • Pomocny post
    #3 5458240
    mirekk36
    Poziom 42  
    Config Serialin = Buffered , Size = 80 
    Enable Interrupts 
    
    Dim _Flaga_1s as Bit
    _Flaga_1s = 0
    
    Config Timer1 = Timer , Prescale = 64 
    Enable Timer1 : On Timer1 Co1s 
    
    Cls 
    
    Do 
      If Ischarwaiting() = 1 Then                                
        Znak = Inkey() 
        Print Chr(znak) ; 
      End If 
    
      if _Flaga_1s = 1 then
       
         ' ------> a tutaj wyświetlaj już sobie spokojnie co chcesz co 1 sekundę
         ' czyli np to co było przedtem w przerwaniu:
    
              Locate 1 , 1 
              Lcd "a" 
    
        _Flaga_1s = 0
      End If
    
    
    Loop 
    End 
    
    
    Co1s: 
      Cls 
      Timer1 = 3036 
      _Flaga_1s = 1
    Return 


    1. Naucz się korzystać z mechanizmu tzw "Flag"
    2. Zapomnij o używaniu polecenia LCD w przerwaniach szczególnie gdy nóżka R/W twojego wyświetlacza podłączona jest do GND i wyświetlanie jest b.wolne. Ale nawet wtedy gdy sterujesz nóżką R/W z procka za pomocą odpowiedniejbiblioteki Bascoma (bo można) to i tak lepiej to robić tak jak pokazałem wyżej

    ... jak widzisz warunek if _Flaga_1s = 1 then zajdzie dokładnie co 1sekundę a o to chyba tobie chodzi ? prawda? - oczywiście na koniec tego If'a trzeba skasować flagę - chyba już wiesz dlaczego? :)
  • REKLAMA
  • #4 5458401
    m4jkel
    Poziom 12  
    korneliuszo Twoja metoda zadziałała, ważne było tylko żeby bufor był odpowiednio duży. Wydaje mi się jednak, że to rozwiązanie trochę zbyt brutalne przerywać przerwanie przerwaniem :)

    mirekk36 O to chodziło, dzęki! Te flagi to bardzo dobra sprawa. Czemu muszę skasować flagę to jasne. A mogę chyba ją skasować zaraz na początku IFa? Tak mi się wydaje logiczniej, chociaż to chyba nie ma żadnego znaczenia.
  • #5 5459281
    mirekk36
    Poziom 42  
    Cytat:
    A mogę chyba ją skasować zaraz na początku IFa? Tak mi się wydaje logiczniej, chociaż to chyba nie ma żadnego znaczenia.


    znaczenie to ma :)
    ale w tym przypadku możesz ją kasować na początku, jednak zauważ jaki ciekawy mechanizm masz w rękach. Bo np gdy chciałbyś aby w przerwaniu ta flaga i ew jeszcze jakieś inne operacje mogły się wykonać dopiero gdy załatwisz wszystko w tym IF'ie to wtedy warto ją skasować jednak na końcu, natomiast w przerwaniu dodać jeszcze warunek:

    if FLAGA = 0 Then Flaga = 1


    innymi słowy, część przerwań może być ładnie pominięta dotąd dokąd nie zostaną wykonane wszystkie opeacje w tym IF'ie ..... oczywiście to czasem może być potrzebne a czasem nie (wtedy można ją kasować na początku)
REKLAMA