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

[Bascom] Przerywanie instrukcji Input w przerwaniu

MES Mariusz 19 Gru 2010 13:04 2952 15
REKLAMA
  • #1 8887509
    MES Mariusz
    Poziom 36  
    Witam.

    Urządzenie w nieskończonej pętli pobiera za pomocą instrukcji input z UARTa napływające dane, interpretuje je i wykonuje.

    W urządzeniu jest również odbiornik podczerwieni. Kod RC5 odbierany jest w przerwaniu.

    Chciałbym, po napłynięciu właściwych danych przez RC5 (wykonuje się program przerwania) móc zakończyć oczekiwanie na dane z UART-a. Podsumowując: chciałbym w przerwaniu móc zatrzymać wykonującą się w programie głównym komendę input.

    Da się to zrobić? Brutalnie przerwać oczekiwanie na dokończenie się instrukcji input lub oszukać uP, że na UART napłynęły jakieś dane?

    Z góry dzięki za podpowiedź.
  • REKLAMA
  • #2 8888295
    M. S.
    Poziom 34  
    Nie miałem takich problemów wcześniej ale sadzę, że przerwanie zewnętrzne od odbiornika podczerwieni samoczynnie przerwie oczekiwanie na dane w instrukcji input, a po obsłużeniu przerwania wróci do input. Podobnie dzieje się z instrukcją Wait.
  • REKLAMA
  • #3 8888307
    ZbeeGin
    Poziom 39  
    Przeczytaj: http://avrhelp.mcselec.com/index.html
    Wykorzystaj opisaną tam zmienną (modyfikacja jej zawartości w przerwaniu) lub ustaw niski czas na starcie, a potem kontroluj czy Input zostało przerwane. Prawdopodobnie przy przerwaniu INPUT ustawiana jest dodatkowo zmienna ERR. Trzeba by zajrzeć w kod "tylnymi drzwiami".

    Dodano po 27 [minuty]:

    EDIT:
    Nie ma tak różowo jak myślałem. Niestety stan zmiennej ERR nie jest modyfikowany przy przerywaniu INPUT, a powinien. Jest kilka instrukcji, które tak robią, ale tu jeszcze tego nie ma.

    Ale! Zawartość ___TIMEOUT można zmodyfikować w przerwaniu. Jest jednak pewien szczegół.
    Zawartość jest kopiowana do rejestrów R16:R17:R18:R19 i tam jest czas liczony (nawet symulator bascomowy to pokazuje). Niestety jak napiszesz standardowe przerwanie, to rejestry te wylądują na stosie, a po wykonaniu przerwania zostaną z niego zdjęte. Zatem zmodyfikowanie tej zmiennej w takim przerwaniu nic nie daje, bo zmiana nie będzie zapamiętana.
    Trzeba stworzyć przerwanie, które ma parametr NO SAVE i samemu dobrać jakie rejestry trzeba zachować na stosie, a jakie nie. A to zależeć będzie od treści przerwania.
  • #4 8888486
    mirekk36
    Poziom 42  
    Eeeej panowie, nie trzeba wchodzić tylnymi drzwiami, nie trzeba stosować żadnych sztuczek i nie trzeba koniecznie tworzyć przerwanie, które jakoś tam "na siłę przerwie input".

    Wystarczy tylko inaczej - a w zasadzie to "normalnie" podejść do tematu a nie od tyłu. Niestety help bascoma nie pomaga w takim myśleniu od przodu ale nie ma co się dziwić - tam są tylko proste przykłady jak korzystać z poleceń a nie nauka programowania.

    Reasumując: używanie polecenia INPUT w pętli głównej w jej każdym obiegu nawet z ustawianym Timeoutem to nieporozumienie. Tworzy się program blokujący i działający w czysto liniowy sposób. Po CO?

    Toż jest w Bascomie ładny mechanizm bufora sprzętowego dla RS232 (Config Serialin). Ten z kolei pozwala reagować i wywoływać specjalną procedurę użytkownika gdy pojawi się znak końca linii czy ramki jaka nadlatuje przez RS232. Zwie się to BYTEMATCH. I całkiem dobrze i fajnie działa.

    Wystarczy teraz tylko ustawić sobie żeby reagowało na znak ENTER (Char(13) koniec linii i w tejże procedurze zwiększać licznik odebranych ramek zakończonych ETER'em.

    A w pętli głównej żeby nie była BLOKOWANA - wystarczy już tylko sprawdzać czy tenże licznik jest większy od ZERA. Jeśli większy to znaczy, że coś nadleciało i wtedy dopiero można użyć INPUT'a, który pięknie z bufora w mgnieniu oka - jak najszybciej się da i bez blokowania pobierze ramkę. Należy też zmniejszyć licznik odebranych ramek.

    Dzięki temu prostemu sposobowi można bez obaw wykorzystywać milion innych funkcji/procedur odpalanych w pętli głównej. NALEŻY tylko pamiętać o tym aby je także pisać w sposób NIEBLOKUJĄCY. Proszę bardzo oto namiastka sposobu jak nawet w Bascomie zrobić system wielozadaniowy.
  • REKLAMA
  • #5 8888528
    ZbeeGin
    Poziom 39  
    mirekk36. Na razie nie wiemy jakie kolega ma długieee te transmisje danych. RAM nie jest z gumy, a powinno jeszcze starczyć na całą masę zmiennych i trzy stosy, a zwłaszcza na HWStack, który by tu mocno puchnął.
    Kolega używa GETRC5. Nie zapominaj o nim, bo połączenie przerwania z INTx (słynne GETRC5 w przerwaniu) + dwa z USART-u (via bufor SERIALIN) i czasowo zależna transmisja to mieszanka, którą BASCOM może nie przełknąć.
  • #6 8888612
    mirekk36
    Poziom 42  
    ZbeeGin napisał:
    mirekk36. Na razie nie wiemy jakie kolega ma długieee te transmisje danych. RAM nie jest z gumy, a powinno jeszcze starczyć na całą masę zmiennych i trzy stosy, a zwłaszcza na HWStack, który by tu mocno puchnął.


    Jeśli to jest ATtiny2313 to pewnie, że nie ma o czym w ogóle mówić ale jeśli już coś co ma na pokładzie z 16kB Flash'a (nawet 8kB) i 1k RAM to są już zasoby spokojnie wystarczające. Nawet i ATmega88 sobie z tym poradzi. No a transmisje na pewno nie są długie idę o zakład, bo kto używa w tak małych prockach długich transmisji do sterowania czegoś czy prostego przekazywania danych? No chyba żeby przesyłać coś do/z karty SD albo przy użyciu jakiegoś TCP ale to inna bajka.
    A zalegą tego co opisałem jest to, że jeśli napisze się wszystko w sposób nieblokujący to praktycznie każda ramka będzie na bieżąco konsumowana przez pętlę główną. Czasem gdy pętla będzie zajęta inną robotą mogą wskoczyć ze dwie , trzy ... ale wystarczą 2,3 obiegi pętli i po bólu.

    ZbeeGin napisał:
    Kolega używa GETRC5. Nie zapominaj o nim, bo połączenie przerwania z INTx (słynne GETRC5 w przerwaniu) + dwa z USART-u (via bufor SERIALIN) i czasowo zależna transmisja to mieszanka, którą BASCOM może nie przełknąć.


    Zarówno GETRC5, jak Serialin ale także I2C Slave we własnym wykonaniu oraz wiele innych rzeczy jak obsługa 4 czujników DS18B20, multipleksowanie 8 wyświetlaczy LED, obsługa także RS485 i kilku innych drobiazgów najspokojniej w świecie działało mi swego czasu na ATmega32 ;)
  • REKLAMA
  • #7 8889507
    MES Mariusz
    Poziom 36  
    mirekk36 napisał:
    Eeeej panowie, nie trzeba wchodzić tylnymi drzwiami, nie trzeba stosować żadnych sztuczek i nie trzeba koniecznie tworzyć przerwanie, które jakoś tam "na siłę przerwie input".

    To przerwanie już istnieje, (jest wykonywane gdy na port obsługujący RC5 zaczynają napływać dane) więc nie jest tworzone na siłę. Oczywiście można by program napisać inaczej, tak aby instrukcja input nie "pauzowała" programu głównego, ale zmienia to koncepcję softu w całej serii urządzeń (ich programy działają na analogicznej zasadzie). Oczywiście można "nową koncepcję" wprowadzić w tym konkretnym urządzeniu, ale nie chciałbym burzyć "standardu" jaki panował do tej pory. Stąd jeśli ktoś wie czy i w jaki sposób da się w przerwaniu zmodyfikować rejestry tak aby Atmega8 "myślała", że odebrała dane z UARTa i zakończyła polecenie input, to byłbym mu za podpowiedź niezmiernie wdzięczny.
  • #8 8889853
    mirekk36
    Poziom 42  
    MES Mariusz --> przecież w tym co pisałem nie chodziło o tworzenie na siłę przerwania dla RC5 bo to akurat dobry pomysł jak na Bascom, chociaż co nieco spowalnia pracę ale może być ;)

    Chodziło o podopwiedź że można utworzyć dodatkowe przerwanie, które przerwie ci INPUT.

    Jeśli chodzi o standard pisania programów to ja cię do niczego nie namawiam na siłę. Podpowiedziałem ci tylko jak powinno się do tego podchodzić a ty dalej zrobisz z tym co zechcesz. Jeśli więc będziesz chciał brnąć nadal w tą ślepą uliczkę bo inne twoje układy tak samo źle mają napisany soft to nie ma sprawy.

    Nawiasem mówiąc sposób , który ci podałem w ogóle ale to w ogóle nie wpływałby na sposób komunikacji z innymi starszymi urządzeniami. Powiem więcej miałby taki układ od razu więcej możliwości. Bo twoje przesyłane ramki danych można byłoby nadal w identyczny sposób analizować i wykonywać "jakieś" czynności. Tyle że szybciej, płynniej, wygodniej i nowocześniej ma się rozumieć.

    Szkoda jednak, że tak proste wbrew pozorom sposoby programowania (chodzi o pisanie tzw procedur nieblokujących) są tak trudne do przyjęcia przez początkujących. Zawsze zastanawiam się z czego to wynika. Ale chyba się nie dowiem ;)
  • #9 8890851
    MES Mariusz
    Poziom 36  
    To co piszesz jest słuszne i mądre, widzisz, jest tylko jeden problem - soft jest skomplikowany bardziej niż by się wydawało, atmega8 ma tylko 8kb flash a wszystkie przerwania Atmega8 są zajęte (w tym timer1 do zliczania pojedynczych sekund, int1 i timer2 wykorzystywany przez getrc5).

    Oczywiście zawsze można skonfigurować bufor wejściowy, np. gdy spodziewamy się maksymalnie 6 bajtowych ramek danych:

    Config serialin = buffered, size = 6, bytematch = 13

    I później już tylko (jak czytam po forach) włączyć przerwania i zawrzeć w kodzie procedurę:

    Serial0charmatch:
    Input zmienna_string$ * 6
    Return


    Z tym, że nie mam pojęcia jakiego przerwania bascom do tego użyje, a co za tym idzie czy nie będzie to kolidowało z resztą przerwań / nie wpłynie na działanie programu.

    Stąd, gdyby istniał sposób, który zasugerowałem (jakieś banalne zmylenie uP, że na UART napłynęły już dane) można by tego uniknąć.

    Jeśli jednak nie da się zrobić tego tak jak zasugerowałem, cóż nie pozostanie mi nic innego, jak tylko zrobić to przez bytematch i powiązane z nim przerwanie.
  • #10 8891074
    mirekk36
    Poziom 42  
    Bytematch nie używa żadnego specjalnego przerwania że boisz się iż ci ich zabraknie ;) .... jakby było takie uzyte to zostałbyś poinformowany o tym w Helpie.

    Za to przykład, który wyczytałeś z forów internetowych rzeczywiście mógłby działać kiepsko i doszedłbyś szybko do wniosku, że coś do kitu działa ten mechanizm.

    Zawartość tej procedury powinna być JAK NAJKRÓTSZA i także nie blokująca. Powinna być wręcz napisana w asemblerze, np tak jak kiedyś zasugerował kolega zumek:

    
    Serial0charmatch:       'po odebraniu znaku Chr(13) zwiększenie licznika lini(zdarzeń) 
    lds r24,{event} 
    inc r24 
    sts {event},r24 
    ret 
    


    W zmiennej Event trzymasz więc ilość ramek które nadleciały. A w pętli głównej wywołujesz już tylko procedurę, która spokojnie za pomocą INPUT odczytuje ramki. I UWAGA! wcale nie musisz deklarować długości bufora sprzętowego równego jednej ramce to wręcz nieporozumienie jeśli chodzi o ten sposób. Powinien być CO NAJMNIEJ 2x większy albo i jeszcze troszkę, dopiero będzie to miało większy sens, bo gdy pętla główna się nie wyrobi to mogą być w międzyczasie ze dwie ramki odebrane i obsłużone później.

    Tak samo jak nie ma sensu pisać czegoś takiego

    Input zmienna_string$ * 6

    po co?

    Wystarczy

    Input zmienna

    przecież input ładnie odbierze z bufora to co trzeba a ramka może mieć dowolną długość od 1 do max jeśli u ciebie max to będzie 6.
  • #11 8892814
    ZbeeGin
    Poziom 39  
    mirekk36 napisał:
    Bytematch nie używa żadnego specjalnego przerwania że boisz się iż ci ich zabraknie ;)

    Przerwanie RXC jest tam używane, ale niezależnie czy działa opcja ByteMatch czy nie. Ogólnie buforowanie korzysta z UDRE i RXC/TXC (zależy które działa odbiorcze/nadawcze lub oba).

    mirekk36 napisał:
    .... jakby było takie uzyte to zostałbyś poinformowany o tym w Helpie.

    I tu niestety muszę koledze uświadomić, że wiele rzeczy które jest, w helpie nie jest ujętych nawet jednym prostym zdaniem.
  • #14 8894251
    mirekk36
    Poziom 42  
    xury napisał:
    Panowie jest prostsza metoda. Dziwię się że kolega Mirek nie wspomniał o tym.
    Do poczytania lektura na temat $SERIALINPUT


    No nie wspomniałem bo jak się orientujesz albo może i nie, ja już straaasznie dawno nie ruszałem Bascoma i nawet troszkę zapomniałem przyznaję o #serialinput.

    .... ale, przypomniałem teraz sobie z helpa bascoma i .... hmmm ja bym nie powiedział że jest to prostsze rozwiązanie szczególnie dla kogoś kto jeszcze się uczy tylko Bascoma a nie ma żadnego pojęcia o asemblerze. To wręcz masakra. Ja właśnie dlatego opuściłem Bascoma bo wycisnąć z niego można było oczywiście dużo więcej poprzez wstawki asemblerowe. Jak program był nimi nadziany jak dobra kasza skwarkami to mógł na prawdę duuuuużo zrobić ;)

    No ale to znowu powrót do języka niskiego poziomu i znowy straszne wydłużenie pisania, uruchamiania i testowania własnych układów.

    Dlatego nawet jak ktoś zna asembler to owszem jak się sporadycznie coś robi to można powiedzieć że jest to dobre rozwiązanie ale nie na dłuższą metę.
  • #15 8895198
    mirekk36
    Poziom 42  
    ZbeeGin napisał:
    mirekk36 napisał:
    Bytematch nie używa żadnego specjalnego przerwania że boisz się iż ci ich zabraknie ;)

    Przerwanie RXC jest tam używane, ale niezależnie czy działa opcja ByteMatch czy nie. Ogólnie buforowanie korzysta z UDRE i RXC/TXC (zależy które działa odbiorcze/nadawcze lub oba).


    No i tylko dlatego napisałem, że nie jest używane żadne specjalne przerwanie o których wspominał wyżej autor obawiając się że zabraknie mu wolnych przerwań od timerów czy innych. A to, że Bytematch musi działać w oparciu o przerwania USART to chyba zrozumiałe.

    ZbeeGin napisał:
    mirekk36 napisał:
    .... jakby było takie uzyte to zostałbyś poinformowany o tym w Helpie.

    I tu niestety muszę koledze uświadomić, że wiele rzeczy które jest, w helpie nie jest ujętych nawet jednym prostym zdaniem.


    Oj , tak - wiem o tym i zdaję sobie sprawę, a dokładniej mówiąc gdy zaczynało mi się okazywać że coraz więcej jest takich kruczków, których nie ma nigdzie opisanych ani słowem - to w pewnym momencie zdecydowało o KONIECZNOŚCI przejścia na język C ;)
  • #16 8897550
    MES Mariusz
    Poziom 36  
    A tak wracając do początku, czy przez przypadek fragment bascomowego help'a (przykład z $serialinput), nie odpowiada na pierwszy post?

    ldi R24, 13                                               'fake enter so INPUT will end





    '--------------------------------------------------------------------------------
    'name                     : $serialinput.bas
    'copyright                : (c) 1995-2005, MCS Electronics
    'purpose                  : demonstrates $SERIALINPUT redirection of serial input
    'micro                    : Mega48
    'suited for demo          : yes
    'commercial addon needed  : no
    '--------------------------------------------------------------------------------
    
    $regfile = "m48def.dat"
    
    'define used crystal
    $crystal = 4000000
    $hwstack = 32                                               ' default use 32 for the hardware stack
    $swstack = 10                                               'default use 10 for the SW stack
    $framesize = 40                                             'default use 40 for the frame space
    
    'dimension used variables
    Dim S As String * 10
    Dim W As Long
    
    'inform the compiler which routine must be called to get serial characters
    
    $serialinput = Myinput
    'make a never ending loop
    
    Do
    'ask for name
    Input "name " , S
    Print S
    'error is set on time out
    Print "Error " ; Err
    Loop
    
    End
    
    
    'custom character handling  routine
    'instead of saving and restoring only the used registers
    'and write full ASM code, we use Pushall and PopAll to save and restore
    'all registers so we can use all BASIC statements
    '$SERIALINPUT requires that the character is passed back in R24
    Myinput:
    Pushall                                                   'save all registers
     W = 0                                                     'reset counter
    Myinput1:
      Incr W                                                   'increase counter
      Sbis USR, 7                                             ' Wait for character
      Rjmp myinput2                                           'no charac waiting so check again
      Popall                                                   'we got something
      Err = 0                                                 'reset error
      In _temp1, UDR                                           ' Read character from UART
      Return                                                   'end of routine
    Myinput2:
      If W > 1000000 Then                                     'with 4 MHz ca 10 sec delay
        rjmp Myinput_exit                                     'waited too long
      Else
        Goto Myinput1                                         'try again
      End If
    Myinput_exit:
    Popall                                                   'restore registers
    Err = 1                                                   'set error variable
    ldi R24, 13                                               'fake enter so INPUT will end
    
REKLAMA