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

[AVR] Transmisja bajtu 0x00 przez port szeregowy

memento1987 19 Kwi 2010 20:31 1983 10
REKLAMA
  • #1 7980533
    memento1987
    Poziom 10  
    Napisałem w Javie strumieniowanie pliku muzycznego bajt po bajcie przez port szeregowy z komputera do AVR.
    Fragment kodu odpowiedzialny za strumieniowanie tutaj:
    
                          RandomAccessFile file = new RandomAccessFile(streamingFileWithPath,"r");
                          BinaryFile bin=new BinaryFile(file);
                          int fileSize = (int)file.length();
    
                          int bytesSize = fileSize;
                          short bytes = 0;
                          int i = 0;
                          while (true) {
                            try {
                              bytes = bin.readByte();
                              if(bytes == 0) bytes++;
                              System.out.print(Integer.toHexString(bytes)+" ");
                              if(i==5)
                                outputStream.write(0);
                              else
                                outputStream.write(bytes);
                              i++;
                              if(i==bytesSize)
                                break;
                            }
                            catch (EOFException eof) {
                              System.out.println ("End of File");
                              break;
                            }
                          }
    

    Wszystko działa ok dopóki w strumieniu nie pojawi się bajt o wartości 0x00. Wtedy po drugiej stroni transmisji przez port szeregowy dostaję jakieś dziwne wartości wyjściowe.
    Przykładowe działanie:
    Przykład dobrego działanie:
    Wysyłam sekwencję: 2e 73 6e 64 1 1 1 18 1 1 b1 67 1 1 1 1 1 1 1f 4c
    Na wyjściu otrzymuję sekwencję: 2e 73 6e 64 01 01 01 18 01 01 b1 67 01 01 01 01 01 1 1f 4c
    czyli wszystko jest w OK,
    ale
    Przykład błędnego działania:
    Wysyłam sekwencję: 2e 73 6e 64 1 0 1 18 1 1 b1 67 1 1 1 1 1 1 1f 4c
    Na wyjściu otrzymuję sekwencję: 2e 73 6e 64 01 00 00 00 10 00 00 00 11 00 00 00 A8 35 be 09
    I tak zawsze przy wysłaniu bajtu o wartości 0 pojawia się jakieś niespodziwane (przynajmniej dla mnie) wyjście.
    Czy ktoś potrafi mi wyjaśnić dlaczego tak się dzieje? Może ktoś ma jakiś sposób jak sobie z tym poradzić? Albo może cociaż ktoś potrafi mi wytłumaczyć dlaczego w tym drugim przypadku dostaję taką właśnie wartość sekwencji wyjściowej.
    Z góry dzięki za każdą pomoc
  • REKLAMA
  • #2 7980679
    Szymon Tarnowski
    Poziom 27  
    Mnie to wygląda na błędne użycie metody write, jej argumentem jest tablica znaków a nie jedna liczba.
  • REKLAMA
  • #3 7980696
    BoskiDialer
    Poziom 34  
    Sprawdź jakie masz błędy ustawienia prędkości transmisji, w miarę możliwości ustawień portu wysyłaj dane z dwoma bitami stopu (co, gdy odbiornik idzie trochę za wolno, ułatwia odzyskanie synchronizacji) - te dane wyglądają, jak by procesor tracił synchronizację. Sprawdź, czy wysłanie bajtu FF przywraca synchronizację.

    Inna możliwość, to błąd w kodzie, gdy bajt o kodzie 0 jest analizowany jako koniec ciągu znaków (np dane od uartu odbierane jako ciąg znaków) co powoduje przerwanie odbierania, ale dalszy segment kodu analizuje dane w stałych porcjach, a więc dalej są śmieci z wcześniejszego odbierania danych.

    Rozumiem, że
    if(bytes == 0) bytes++;
    służy do usuwania bajtów zerowych na czas testów, a
     if(i==5) outputStream.write(0); else {...}
    do wtrącenia bajtu zerowego w celu zademonstrowania problemu. Wtedy jednak to co zostanie wpisane do outputStream różni się od tego wypisanego na System.out, chociaż nie powinno to mieć tak daleko idącyc konsekwencji.
  • #4 7980729
    memento1987
    Poziom 10  
    no niestety to nie to. Z tablicą działa tak samo :-(
    Co więcej napisałem kod w C++ do ręcznego przesyłania wpisanych w program bajtów przez port szeregowy. I tutaj też jeśli wpiszę bajt 0x00 to na wyjściu dostaję taki sam niespodziewany wynik.
  • #5 7980750
    BoskiDialer
    Poziom 34  
    To o czym pisze Szymon Tarnowski również może być przyczyną, szczególnie w przypadku, kiedy funkcja write występuje w kilku wersjach. W takim przypadku do testu trzeba by zmienić kod, aby wartość zerowa była wpisana pośrednio do zmiennej bytes a następnie została wywołana funkcja write, gdyż wariant funkcji nie jest wybierany w trakcie wykonywania - tutaj był by wybrany wariant write(int char), chociaż wątpię, aby stała 0 została potraktowana jako zerowy wskaźnik dla write(Strint str) [jeśli takowy wariant funkcji write istnieje].

    Dodano po 56 [sekundy]:

    Jeśli inny program powoduje odebranie takiego samego - złego wyniku, to być może wina jest po stronie odbiornika?
  • #6 7980790
    memento1987
    Poziom 10  
    Cytat:
    Rozumiem, że
    Kod:
    if(bytes == 0) bytes++;
    służy do usuwania bajtów zerowych na czas testów, a
    Kod:
    if(i==5) outputStream.write(0); else {...}
    do wtrącenia bajtu zerowego w celu zademonstrowania problemu. Wtedy jednak to co zostanie wpisane do outputStream różni się od tego wypisanego na System.out, chociaż nie powinno to mieć tak daleko idącyc konsekwencji.

    Jest dokładnie tak jak napisałeś. To służy tylko do testów.
  • REKLAMA
  • #7 7981048
    rpal
    Poziom 27  
    a moze niech kolega podłączy się z drugim pc-tem i z pomocą termina śle i wysyła bajty może to nasunie jakieś rozwiązanie ?
  • #8 7981064
    memento1987
    Poziom 10  
    Zrobiłem taki eksperyment, że przekierowałem te bajty z programu do pliku wyjściowego zamiast do portu szeregowego. I zapisało tam wszystko poprawnie, również bajty 0x00.

    Zatem widocznie problem leży w ustawieniach portu szeregowego po stronie odbiorczej.
    Będę coś kombinował z tej drugiej strony i zobaczymy co z tego wyjdzie.
  • REKLAMA
  • #9 7982816
    OlekM
    Poziom 17  
    Na podstawie powyższych postów, wydaje się, że najbardziej prawdopodobny scenariusz nakreślił użytkownik BoskiDialer:

    Cytat:

    Inna możliwość, to błąd w kodzie, gdy bajt o kodzie 0 jest analizowany jako koniec ciągu znaków (np dane od uartu odbierane jako ciąg znaków) co powoduje przerwanie odbierania, ale dalszy segment kodu analizuje dane w stałych porcjach, a więc dalej są śmieci z wcześniejszego odbierania danych.


    Kolega, sądząc po wyborze języka, jest zapewne zwolennikiem podejścia wysokopoziomowego. Czy zatem dane w procesorze nie są odbierane funkcją typu fgets lub scanf? Te funkcje (jak i większość innych ze standardowej biblioteki C, może poza fread i fwrite) zakończą odbieranie danych po napotkaniu znaku 0.
    W takim przypadku rozwiązaniem mogło by być odbieranie danych wprost z rejestru UDR (po sprawdzeniu stosownej flagi w rejestrze USCRA).
  • #10 7982904
    memento1987
    Poziom 10  
    Stworzyłem emulację tej sytuacji przez program socat pod Ubuntu. Ten program umożliwia stworzenie pary wirtualnych portow szeregowych. Porty są takie, że jak sie do jednego z nich pisze to na drugim można czytać.
    I teraz zrobiłem tak, że do jednego z pary portó (/dev/pts/2) podpiąłem mój program. Do drugiego (/dev/pts/1) podpiąłem Serial Port Terminal (aplikacja z Ubuntu). I teraz jak odbieram wysyłane dane na tym terminalu to też dzieje się tam samo jak powyżej opisałem. Czyli bajt 0x00 jest zamieniany na "krzaki".
    Czy ktoś może probował te programy socat i Serial Port Terminal? Czy taka symulacja jak powyżej jest w wiarygodna? Czy może one (tworzone wirtualne porty, albo program SPT) mają jakąś specyfikę, która mogłaby powodować taki odczyt danych?
    Dodam, że wirtualne porty szeregowe tworzę przez socat poleceniem: socat -d -d PTY: PTY:
  • #11 7983938
    rpal
    Poziom 27  
    w takim razie temat zawierajacy w tytule AVR jest z założenia mylny i problem dotyczy programu od strony PC-ta. Javy kompletnie nie znam, :(
REKLAMA