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

[Atmega32][C]+[C#]Wysyłanie tablicy danych przez port szeregowy

mateo238 05 Lis 2011 15:11 4761 27
  • #1 10104151
    mateo238
    Poziom 10  
    Efekt jaki chciałbym uzyskać to z komputera przez port szeregowy wysyłam tablicę bajtów. Następnie na uC odbieram tą tablicę i zapisuje ją do pamięci EEPROM. Jak najlepiej rozwiązać taki problem? Czy są gotowe funkcje pozwalające w C# wysyłać tablice na port szeregowy a w AVR aby odbierać tablice?

    Pozdrawiam
  • #3 10106922
    mateo238
    Poziom 10  
    W AVR mam funkcję która odbiera bajt z portu szeregowego:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Czy jest analogiczna funkcja która pozwoli odebrać całą tablicę bajtów bo właśnie tablicę chcę przesłać z komputera. Czy może przy użyciu tej funkcji można zrealizować odbieranie tablicy??

    Pozdrawiam
  • #4 10107041
    tmf
    VIP Zasłużony dla elektroda
    Trzeba ją wywołać tyle razy ile bajtów odbierasz. Potrzebujesz oczywiście jakiś znacznik końca odbieranego ciągu. Z odebranych bajtów poskładasz sobie całą tablicę, albo po prostu zapiszesz je w EEPROM tak jak chcesz.
  • #5 10107062
    mateo238
    Poziom 10  
    Jak zaznaczyć koniec ciągu (koniec tablicy)??
  • #6 10107090
    Fredy
    Poziom 27  
    mateo238 napisał:
    Jak zaznaczyć koniec ciągu (koniec tablicy)??


    to już od Ciebie zależy. Możesz ustalić stałą ilość znaków, wtedy tą funkcję wywołujesz n razy , możesz na końcu wysyłać jakiś szczególny znak który nigdy napewno nie powtórzy się w innym miejscu. Ten znak gdy zostanie odebrany oznaczać będzie koniec tablicy. Wybór znaku zależy od ciebie. Jeśli transmitujesz cały wachlarz danych i może się zdarzyć znak od 0 do 255 to pozostaje ci tylko ustalić stałą długość ramki albo jakiś timeout.
  • #7 10107402
    Konto nie istnieje
    Konto nie istnieje  
  • #8 10107427
    tmf
    VIP Zasłużony dla elektroda
    Najpierw w ogóle zobacz co ci ta funkcja w C# wysyła. Bo tablica kojarzy się z danymi binarnymi, a z tym zawsze jest problem (padding, endianess). Może się okazać, że te dane binarne mają zupełnie nieciekawy format i na 8-bitowym AVR otrzymasz coś zupełnie innego niż występuje na 64-bitowym PC. Jeśli jednak na upartego chcesz wysyłać dane binarne to np. pierwsze 2 bajty ciągu powinny zawierać ilość danych wysyłanych - musisz stworzyć coś w stylu ramki danych.
  • #9 10108684
    mateo238
    Poziom 10  
    Wiec na komputerze byłoby coś takiego:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Natomiast jak odebrac to na AVR? Czy tak zadziała:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Czy takie rozwiązanie jest dobre czy trzeba inaczej podejść do sprawy?? Z góry dzięki za cenne rady.

    Pozdrawiam
  • #10 10108836
    tmf
    VIP Zasłużony dla elektroda
    Nie zadziała z kilku powodów. Po pierwsze zapis do zmiennej w pamięci EEPROM na AVR wymaga posłużenia się którąś z funkcji z eeprom.h - póki co, w bieżącej wersji kompilatora named address spaces nie są zaimplementowane.
    Kolejna sprawa to ta flaga w przerwaniu - co to za dziwactwo?
    I kolejna - na PC byte jak jest zdefiniowane? Pamiętaj, że w zależności od definicji ta tablica może wcale nie mieć 1024 bajtów. Bezpieczniej byłoby jawnie wysyłać element po elemencie.
  • #11 10108855
    Konto nie istnieje
    Konto nie istnieje  
  • #12 10109068
    nsvinc
    Poziom 35  
    Przesyłanie w ASCII jest wyjątkowo niewydajne, a dodatkowo, wymaga zasobożernych instrukcji zamieniających string na int i odwrotnie. ASCII-owy protokół popychania danych przez UART nie jest optymalny. Znacznie lepiej enkodować informacje w strumień z symbolami zastrzerzonymi, które jednoznacznie definiują początki i końce danych.
  • #13 10109133
    Konto nie istnieje
    Konto nie istnieje  
  • #14 10111343
    mateo238
    Poziom 10  
    Odnośnie uwag użytkownika tmf:
    - pominąłem w poście (przeoczenie) funkcje zapisu do eepreomu ale wiem że musi takowa być
    - flaga w przerwaniu ma spowodować odbiór danych w pętli while (chodziło o zrobienie tak aby przerwanie trwało jak najkrócej). W poście zapomniałem jedynie o kasowaniu flagi po odebraniu danych
    - tablica jest zadeklarowana w pokazany sposób czyli "byte tablica[1024];". Ma to być tablica przechowująca 1024 elementy każdy z zakresu od 0-255

    Co do pozostałych uwag to nie chciałbym kombinować ze stringami (wydawało mi się że nie jest to konieczne). W tablicy będą mniej więcej takie dane: 255, 128, 0, 43, 158, 65 itd dane te mają iść bezpośrednio na port mikrokontrolera aby sterować diodami podłączonymi do portu (PORTA = eeprom_read_byte(&tablica_eeprom[indeks]).

    Ponadto gdy zawsze wysyłam pełną tablicę danych (1024 elementy) to chyba nie ma potrzeby aby jakoś szczególnie określać koniec wysyłanych danych.
  • #15 10111359
    tmf
    VIP Zasłużony dla elektroda
    Flaga w przerwaniu dubluje istniejącą flagę w rejestrze statusu USART, stąd też jest zupełnie niepotrzebna.
    Pytałem nie o sposób zadeklarowania tablicy, bo to widzę, tylko o sposób zadeklarowania typu byte - czy gwarantuje, że element tablicy będzie 8-bitowy? Bo szczególnie w językach typu C# bym się spodziewał, że kompilator to przerobi tak jak wygodniej jest procesorowi, czyli wrzuci elementy po 32- lub 64-bity i wszystko się sypnie. Jak widzisz po wypowiedziach także innych, przesyłanie danych w formatach binarnych pomiędzy platformami nie jest takie proste. Oczywiście nie musisz robić konwersji na stringi, dane możesz przesyłać w postaci binarnej, niekoniecznie tylko przy pomocy funkcji wysyłającej od razu całą tablicę. Bezpieczniej byłoby czytać ja indeks po indeksie i wysyłać jako kolejne bajty.
  • #17 10111481
    Konto nie istnieje
    Konto nie istnieje  
  • #19 10113156
    mateo238
    Poziom 10  
    Czyli jak najlepiej rozwiązać ten problem?
  • #20 10113576
    Konto nie istnieje
    Konto nie istnieje  
  • #21 10118285
    mateo238
    Poziom 10  
    Więc aktualnie sprawa wygląda tak:

    Na PC mam coś takiego:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Natomiast na AVR mamy coś takiego:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Aktualnie jest problem z odbieraniem tego rodzaju, że po którymś wysłaniu dane jakby się rozjechały... wysyłając kolejne razy te same dane z PC w końcu dochodzę do etapu, że dane są poprawnie wyświetlone na AVR. Co może być nie tak? Wygląda to trochę jakbym przekraczał indeks tablicy ale nie widzę w kodzie gdzie mogłoby to nastąpić.

    Będę wdzięczny za każdą pomoc.
  • #22 10118402
    Konto nie istnieje
    Konto nie istnieje  
  • #23 10118738
    mateo238
    Poziom 10  
    Może ja źle myślę ale skoro wysyłam po kolei elementy tablicy i później je po kolei odbieram to wydaje mi się że powinno wszystko działać. Czy tylko mi się wydaje?
  • #24 10118770
    mirekk36
    Poziom 42  
    mateo238 napisał:
    Może ja źle myślę ale skoro wysyłam po kolei elementy tablicy i później je po kolei odbieram to wydaje mi się że powinno wszystko działać. Czy tylko mi się wydaje?


    Dobrze ci się wydaje, tylko ludzie piszą ci wyraźnie, że trzeba zorganizować sobie jakąś własną ramkę danych, jakiś własny protokół.

    Tymczasem kolega próbuje odbierać dane w sposób tzw: blokujący a potem dziwi się, że program się rozejeżdża z tym co jest wysyłane z PC :(

    Bo co ta pętla główna robi ??? pełnego kodu nie widać a już można się domyślać, że cały program jest błędnie napisany, wystarczy zresztą spojrzeć na specyfikatory "volatile" nadane zmiennym lokalnym wewnątrz funkcji main, no i zgrozę w postaci zdefiniowania bufora jako zmienną tablicową lokalną zamiast globalną. Dzięki czemu tworzy się ona na stosie, a dzięki takiemu rozmiarowi w 5 sekund kolega straci kontrolę nad stosem i w ogóle prawidłowym działaniem programu.... Bo widać, że na temat stosu też jeszcze kolega niewiele wie. To oczywiście zrozumiałe, wszystkiego trzeba się nauczyć po kolei - to normalne. Tylko właśnie - po kolei , i akurat o tym jak działa stos, co to są zmienne lokalne, gdzie one się pojawiają w pamięci, co to są zmienne globalne, jak są inicjalizowane w ogóle zmienne i dużo innych takich rzeczy z działu że tak powiem teorii to trzeba najpierw gdzieś poczytać, dowiedzieć się - a potem zabrać się za pisanie może najpierw prostszych programów i stopniowo dochodzić do takich.
  • #25 10118784
    mateo238
    Poziom 10  
    Nie bardzo wiem jakby taki przykładowy protokół miał wyglądać.

    Co do zmiennych
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    zmienię je na globalne. W pętli nieskończonej pobierane są dane z tablicy dane[] i wyświetlane na diodach. A więc jak w pętli głównej odbiorę dane przez uart to już nowe dane są pobierane do wyświetlania. Rozumiałbym gdyby po którymś przebiegu pętli obraz się ustabilizował (wczytywały by się już tylko aktualne komórki a nie np. czesc nowych a czesc starych danych) ale aktualnie po wczytaniu wyświetlane są dziwne dane (choć czasami jest tez ok).
  • #26 10118837
    tmf
    VIP Zasłużony dla elektroda
    Tak jak pisze Mirek zacznij od podstaw - postaraj się zrozumieć jak wygląda transmisja danych i jakie mogą na nią czyhać pułapki. Po co te volatile?
    Skąd twój program ma wiedzieć, że transmitujesz pierwszy bajt danych? Jakiekolwiek zakłócenie spowoduje, że przesyłane dane się rozsynchronizują. Musisz stworzyć jakiś prosty protokół wymiany. Coś co będzie miało zdefiniowany znacznik początku bloku danych, ich ilość i CRC. Trzeba na mikrokontrolerze stworzyć odpowiednią maszynę stanu, która będzie miała szansę w przypadku błędów się reinicjować. Dobrym pomysłem nie jest przesyłanie od razu kilkuset bajtów tylko podzielenie tego na fragmenty. Zobacz jak wyglądają profesjonalne protokoły, XMODEM itd. Myślisz, że ludzie sobie bez powodu tak życie komplikują?
    Musisz zmienić sposób myślenia, programując na PC wiele za ciebie załatwiają gotowe funkcje i OS, programując mikrokontrolery sam musisz nad wszystkim panować. A tu albo po prostu przyjmiesz, że nasze rady są dobre i nie zastanawiając się je zaimplementujesz, albo, co lepsze, pomyślisz skąd się robią błędy, poczytasz trochę o elektronice i parę podstaw o mikrokontrolerach.
  • #27 10118986
    zumek
    Poziom 39  
    Cytat:
    ...Właśnie dlatego miałeś wymyślić własny protokół aby wyeliminować rozjeżdżanie się danych..

    I nawet nie trzeba daleko szukać, wystarczy rozejrzeć się po własnym podwórku.
    Weźmy dla przykładu wszystkim znany plik, z rozszerzeniem .hex - jest gotowa ramka:?: Jest.
    Albo np. taka hybryda NMEA+HEX $010203...FEFF*CC
    i.t.d, i.t.p
  • #28 10119017
    Konto nie istnieje
    Konto nie istnieje  
REKLAMA