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: Odbiór danych ASCII przez UART i problem z Backspace

Romek2100 03 Gru 2013 18:18 2643 7
REKLAMA
  • #1 13020939
    Romek2100
    Poziom 10  
    Witam,

    Muszę przesyłać do Atmegi przez UART daną 4 bajtową w formie ASCII.
    Trzeci i czwarty bajt może przy niektórych ramkach być z przedziału 1..255 jako liczba Byte.

    Myślałem żeby całość odbierać przerwaniem:
    Config Serialin = Buffered , Size = 22 , Bytematch = 13


    A w pętli głównej Input'em. Problem jest jednak z tym bajtem liczbowym.
    W przypadku nadawania np. czwartej liczby=8 która jest w ASCII Backspacem, wcześniejsza trzecia litera zostaje skasowana tak jakby działał na nią "Backspace", jeśli odbieram ją Input'em.

    Jak wybrnąć z tej sytuacji ?

    Pozdrawiam.
  • REKLAMA
  • #2 13021702
    BlueDraco
    Specjalista - Mikrokontrolery
    Proste - nie używać funkcji input, która służy tyko do czytania tekstów.
  • REKLAMA
  • #3 13027116
    Romek2100
    Poziom 10  
    Czyli jak rozumiem, wprost czytać z tablicy bufora ?
    Gdzie znajduje się ten bufor z którego odczytuje INPUT ?

    Jak wtedy w Bascomie z 4 bajtowej tablicy wyjąć pierwsze 2 bajty, które potem porównuje Select Case ?
  • REKLAMA
  • #4 13048991
    tank_driver
    Poziom 17  
    Romku,

    Tworzysz zmienną czterobajtową (Dim zmienna(4) as byte), czytasz cztery kolejne bajty odebrane przez port szeregowy z automatu, instrukcją INPUTBIN zmienna(1) , 4
    Instrukcja ta odczyta cztery bajty z bufora portu szeregowego (w formie surowych bajtów), i zapisze je w zmiennej wielobajtowej "zmienna" począwszy od bajtu (pozycji) 1.

    A poszczególne bajty ze zmiennej wielobajtowej czytasz po pozycji - zmienna(1) oznacza pierwszy bajt, lub "od pierwszego bajtu". Nie jestem teraz 100% pewien (i nie mam możliwości sprawdzenia, piszę z pamięci) ale wydaje mi się że żeby wczytać dwa pierwsze bajty zmiennej wielobajtowej do zmiennej typu n.p. word wystarczy polecenie:

    zmienna_word=zmienna(1)

    Pozdrawiam,
    TD
  • REKLAMA
  • #5 13050070
    Romek2100
    Poziom 10  
    INPUTBIN można odebrać tylko ściśle określoną ilość bajtów.
    A jak odebrać zmienną ilość bajtów binarnych, jeśli jest nadawany bajt końca ramki ?
  • #6 13050160
    tank_driver
    Poziom 17  
    Napisałeś że musisz przesłać / odebrać 4 bajty, więc pomyślałem że INPUTBIN będzie dobre.

    Czy wysyłasz znak początku ramki?

    Jak wykryć znak końca ramki? Ja bym to zrobił w przerwaniu URXC, sprawdzając co przyszło do bufora UDR, jeśli nie jest to znak końca ramki to dopisywałbym to do wielobajtowej zmiennej, jeśli natomiast byłby to znak końca ramki to nie dopisywałbym nic, ale ustawiłbym dodatkowy bit "dana_gotowa" tak, aby podprogram który będzie obrabiał te dane wiedział że ma do czynienia z kompletnym źródłem.

    Możesz też zabezpieczyć się przed błędami i założyć maksymalną długość ramki, jeśli dana przychodząca "przeleci" poza zakres to możnaby ustawić bit "blad_RX" na 1, po czym dalej czytać UDR w przerwaniu czekając na znak początku ramki.

    Sprawdź jeszcze ten temat:
    https://www.elektroda.pl/rtvforum/topic2468716.html

    Pozdrawiam!

    EDIT: z tym że musisz to robić na porcie sprzętowym, tylko wtedy będziesz miał dostęp do rejestru UDR. Obsługa przerwania możliwie krótka (może wstawka w ASM?) aby nie gubiło danych, ewentualnie zmodyfikować program na PC tak, aby przed wysłaniem kolejnego bajtu danych czekał on na potwierdzenie odbioru poprzedniego.
  • #7 13051914
    Romek2100
    Poziom 10  
    UART konfiguruje tak:
    Config Serialin = Buffered , Size = 22 , Bytematch = 13

    a przerwanie:
    Serial0charmatch:
       lds r24,{event}
       inc r24
       sts {event},r24
    Return


    W pętli głównej czekam na event, i tu można byłoby przepisać bezpośrednio z bufora UARTa do tablicy. Tylko gdzie jest ten bufor i czy można bezpośrednio przepisać ramkę ?
    W ten sposób pozbyłbym się problemów z INPUTami.
  • #8 13052002
    tank_driver
    Poziom 17  
    Manual BASCOM-a, w opisie instrukcji SERIALIN mówi że bufor danych wejściowych przechowywany jest w wewnętrznej tablicy bajtów _RS232INBUF0 . Oprócz tego są dwa wskaźniki, na początek tych danych oraz na ich rozmiar.

    'Using the CONFIG SERIAL=BUFFERED, SIZE = 10 for example will
    'use some SRAM memory
    'The following internal variables will be generated :
    '_Rs_head_ptr0 BYTE , a pointer to the location of the start of the buffer
    '_Rs_tail_ptr0 BYTE , a pointer to the location of tail of the buffer
    '_RS232INBUF0 BYTE ARRAY , the actual buffer with the size of SIZE

    http://avrhelp.mcselec.com/index.html?config_serialin.htm

    Niestety nie jest podany adres tej tablicy (pewnie jest zmienny).
    Może spróbuj odwołać się do tej wewnętrznej zmiennej?

    Jest też polecenie INKEY, które odczytuje dane z tego bufora, w manualu jest (dla mnie niejasna) wzmianka o czytaniu danych nie będących znakami:

    'When you need to receive binary data and the bibary value 0 ,
    'you can use the IScharwaiting() function.
    'This will return 1 when there is a char waiting and 0 if there is no char waiting.
    'You can get the char with inkey or waitkey then.

    Pozdrawiam,
    TD

    EDIT: Jeszcze jedno, sprawdź pole "bytematch" przy konfiguracji UART-u instrukcją SERIALIN. Musisz użyć specjalnych nazw podprogramów aby to polecenie prawidłowo interpretowało zdarzenia.

    " The ASCII value of the byte that will result in calling a user label.
    When you specify ALL, the user label will be called for every byte that is received. You must include the label yourself in your code and end it with a return. The following label names must be used when you check for a specific byte value:

    • Serial0CharMatch (for SERIALIN or the first UART/UART0)
    • Serial1CharMatch (for SERIALIN1 or the second UART/UART1)
    • Serial2CharMatch (for SERIALIN2 or the third UART/UART2)
    • Serial3CharMatch (for SERIALIN3 or the fourth UART/UART3)

    The following label names must be used when you check for any value:

    • Serial0ByteReceived (for SERIALIN or the first UART/UART0)
    • Serial1ByteReceived (for SERIALIN1 or the second UART/UART1)
    • Serial2ByteReceived (for SERIALIN2 or the third UART/UART2)
    • Serial3ByteReceived (for SERIALIN3 or the fourth UART/UART3)

    When you specify NONE, it is the same as not specifying this optional parameter."

    EDIT2: ok, widzę że u Ciebie procedura, którą obsługuje SERIALIN jest nazwana poprawnie.

    EDIT3: (bo najlepsze pomysły przychodzą kiedy jest się w wannie)
    Bascom obsługuje bufor portu szeregowego programowo, każda przychodząca dana jest porównywana z "bytematch" oraz, jeśli nie jest zgodna to jest dodawana do wielobajtowej zmiennej będącej buforem. W przeciwnym wypadku wywoływany jest odpowiedni podprogram itp.

    Skoro BACOM "ma czas" aby wykonać wszystkie te czynności, to dlaczego nie zrobić tego samemu? Zrezygnować z bufora wejściowego, czytać rejestr UDR po wystąpieniu przerwania URXC, porównać go ze wzorcem początku / końca ramki i jeśli nie jest zgodny to dodać do naszej wielobajtowej zmiennej. Wydaje się to prostszym i pewniejszym rozwiązaniem, bo będzie "szyte na miarę" dla naszych potrzeb.
REKLAMA