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

89C4051 Bascom: Uart nie wychodzi z pętli przerwania, jak to naprawić?

kaldach 13 Lut 2006 15:55 2520 6
REKLAMA
  • #1 2297433
    kaldach
    Poziom 17  
    Posty: 324
    Pomógł: 4
    Ocena: 6
    posługując się wcześniejszymi postami napisałem sobie taki prosty programik, który ma demonstrować działanie przerwania od portu szeregowego. Niestety nie wychodzi on z pętli przerwania, na lcd wyświetla cały czas "Przerwanie". W którym miejscu robię błąd ?? Czsy ma ktoś sprawdzone rozwiązanie tego problemu ??


    $crystal = 11059200
    $baud = 9600
    config lcd = 20*4
    Dim X As Byte
    Enable Interrupts
    Enable Serial
    On Serial Port Nosave

    Do
    Lcd "test!"
    Lcd X
    Lcd "wrocilem!!!"
    Waitms 100
    Loop

    Port:
    inputbin X
    Lcd "Przerwanie"
    Return
  • REKLAMA
  • #2 2298284
    szymtro
    Poziom 30  
    Posty: 1421
    Pomógł: 101
    Ocena: 59
    to już było.
    Trzeba samemu skasować odpowiednią flagę która wywołała przerwanie:
    Przerwanie_rs:
       If Scon.0 = 1 Then    'czy przerwanie od odbioru
          <tu program>
          Scon.0 = 0
       Else                          'jezeli inaczej to przerwanie od nadawania
          <tu program>
          Scon.1 = 0
       End If
    Return
    
  • REKLAMA
  • #3 2300832
    kaldach
    Poziom 17  
    Posty: 324
    Pomógł: 4
    Ocena: 6
    Oki, udało się z tym, że wychodzi następny problem mianowicie w momencie rozpoczęcia transmisji aktualizuje zmienne, wyświetla ich wartości, ale niestety po odebraniu każdego słowa resetuje wartość zmiennej S i zaczyna odliczanie od nowa, co jest tego przyczyną ? Rozumiem, że komenda return powoduje powrót do miejsca gdzie przerwano wykonanie programu.

    $crystal = 11059200
    $baud = 9600
    Dim Ds As String * 3
    Dim S As Byte
    Dim Digit1 As Byte
    Dim Digit2 As Byte
    Dim Digit3 As Byte
    Dim Digit4 As Byte
    Enable Interrupts
    On Serial Port
    Config Lcd = 20 * 4
    Enable Serial



    Do
    For S = 1 To 100
    Locate 1 , 1
    Lcd Digit1
    Locate 2 , 1
    Lcd Digit2
    Locate 3 , 1
    Lcd Digit3
    Locate 4 , 1
    Lcd Digit4
    Locate 1 , 10
    Waitms 100
    Locate 1 , 10
    lcd S
    Next S
    Loop '

    Port:
    If Scon.0 = 1 Then
    Inputbin Ds
    Digit1 = Mid(ds , 1 , 1)
    Digit2 = Mid(ds , 2 , 1)
    Digit3 = Mid(ds , 3 , 1)
    Digit4 = Mid(ds , 4 , 1)
    Scon.0 = 0
    Scon.1 = 0
    End If
    Return
  • REKLAMA
  • #4 2308151
    szymtro
    Poziom 30  
    Posty: 1421
    Pomógł: 101
    Ocena: 59
    chciałeś przerwanie a wcale go nie używasz (prawie wcale). to Samo można zrobić w programie głównym poprostu sprawdzając stan scon.0 a tak zajmie mniej miejsca.
    Radze zmienić koncepcje. Rozumiem że chcesz żeby ci wypisywało jakieś cyfry czy znaki na lcd. No to zrób zmienna zliczajacą znaki, potem jakąś zmienna typu bufor (o długości taką jak ilość znaków w ramce) no i ustal jakąś ramkę.
    np. powiedzmy ze ramka będzie taka: "1234"+ENTER i wtedy dopiero wyświetli na ekranie. czyli było by coś takiego:
     dim rs_rx_licznik as byte
    dim rs_rx_bufor(4) as byte
    
    rs_rx_licznik=1 'to jest ważne i dopiero po tym zalacz przerwania
    enable interrupts
    
    do
    ...
    loop
    
    przerwanie_rs:
     if scon.0=1 then 'odebrano znak po rs
      if sbuf=13 then 'ENTER
       rs_rx_licznik=1
       sbuf="?" 'znak potwierdzenia przyjecia danych
      else 'inny znak
       if rs_rx_licznik<4 then
        rs_rx_bufor(rs_rx_licznik)
        incr rs_rx_licznik   
       end if
      end if
      scon.0=0
     else 'wyslano znak po rs
      'tu zostaw puste - tak ma byc i nic nie przeszkadza a przyda sie  w przyszlosci
      scon.1=0
     end if
    return
    
  • #5 2422107
    relkaMe
    Poziom 2  
    Posty: 2
    Eh ten rs-232 + przerwania to juz mnie o bóle głowy przyprawia. Mam programik:
    Cytat:

    $crystal = 11059200 ' czestotliwosc kwarcu
    $baud = 1200 ' predkosc transmisji
    Dim X As Byte , Znak As Byte
    Enable Interrupts ' wlaczenie przerwan
    Enable Serial ' wlaczenie przerwania portu RS232
    On Serial Port ' na przerwanie z portu wykonaj procedure "port"

    Do ' poczatek petli programu glownego
    P1.1 = Not P1.1
    Waitms 250
    Loop


    Port:
    If Scon.0 = 1 Then 'czy przerwanie od odbioru
    Znak = Inkey
    If Znak > 13 Then
    Cls
    Lcd Znak
    ' Print Chr(znak); <- tu się dzieją jaja

    End If

    Scon.0 = 0
    Else 'jezeli inaczej to przerwanie od nadawania
    Scon.1 = 0
    End If

    Return


    Wszystko jest pieknie gdy tylko mam odebrac bajty z rs-a. Gdy zas chcę odpowiedziec to program sie wiesza.....
    Kombinowałem z róznymi ustawieniami wyłączałem przerwania włączałem je po nadaniu znaków spowrotem ale i tak lipa :cry:
    Czy ktos moze mi pomóc?
  • REKLAMA
  • #6 2436653
    relkaMe
    Poziom 2  
    Posty: 2
    Doszedłem do czegoś po wielu próbach i setkach inwektyw :D
    Może się komuś przydać więc zamieszczam
    
    $crystal = 11059200                                           ' czestotliwosc kwarcu
    $baud = 1200                                                  ' predkosc transmisji
    Dim X As Byte , Znak As Byte
    
    Scon.0 = 0
    Scon.1 = 0
    
    Enable Interrupts                                             ' wlaczenie przerwan
    Enable Serial                                                 ' wlaczenie przerwania portu RS232
    On Serial Port                                                ' na przerwanie z portu wykonaj procedure "port"
    
    Do                                                            'jakis programik glowny
      P1.1 = Not P1.1
      Wait 2
    Loop
    
    
    Port:
      If Scon.0 = 1 Then                                          'otrzymalismy cos
        Znak = Inkey
        If Znak > 13 Then                                         'sprawdzamy czy jest to jakis okreslony przez nas znak
          Cls
          Lcd Znak
                                                                  'odsylamy paczke danych
          Disable Interrupts
          For X = 97 To 120
            Scon.1 = 0
            Sbuf = X                                           '<---tutaj nastepuje wyslanie bajtu
            Do                                                    'zanim nadamy kolejny bajt sprawdzamy czy zakonczono
            Loop Until Scon.1 = 1                                 'wysylanie poprzedniego czyli czy scon.1 = 1
          Next
          Enable Interrupts
    
        End If
        Scon.0 = 0
      End If
    
      If Scon.1 = 1 Then
        Scon.1 = 0
      End If
    Return


    Dodano po 4 [minuty]:

    Ale w dalszym ciągu nie wiem czemu gdybym chciał wysłać bajty instrukcją print program się wiesza...
  • #7 2437093
    szymtro
    Poziom 30  
    Posty: 1421
    Pomógł: 101
    Ocena: 59
    No to pomyśl dokładnie dlaczego program sie wiesza - to dość proste.
    I pomyśl co sie dzieje z wykonywaniem programu jak przyjdzie przerwanie (np rs_send). A na koniec poanalizuj sobie na jaki bit czeka procedurka wysyłania print - i już bedziesz wiedział że jak kasujesz flage scon w przerwaniu to po print program bedzie czekał w nieskończoność.

Podsumowanie tematu

✨ Dyskusja dotyczy problemu z obsługą przerwania UART w mikrokontrolerze 89C4051 programowanym w Bascom. Głównym problemem jest brak wyjścia z pętli przerwania, co skutkuje ciągłym wyświetlaniem komunikatu "Przerwanie" na LCD. Rozwiązaniem jest ręczne kasowanie flagi przerwania w rejestrze SCON (np. Scon.0 = 0 dla przerwania odbioru), co pozwala na poprawne zakończenie obsługi przerwania. W kolejnych postach omawiane są problemy z resetowaniem zmiennej sterującej w trakcie odbioru danych oraz sugestie dotyczące implementacji bufora odbiorczego i detekcji ramki danych (np. zakończenie ramki znakiem ENTER). Poruszono także kwestie związane z blokowaniem programu podczas transmisji, zwłaszcza gdy w przerwaniu kasuje się flagi przerwania, co może powodować nieskończone oczekiwanie na zakończenie transmisji. Zaleca się przemyślenie koncepcji obsługi przerwań i ewentualne przeniesienie części logiki do głównej pętli programu, aby uniknąć problemów z blokowaniem i poprawić stabilność działania UART.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA