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

STM32F4 - USART, nieprawidłowe zakończenie transmisji stringu

Hyde911 28 Sty 2016 17:31 996 10
  • #1 15379770
    Hyde911
    Poziom 24  
    Posty: 752
    Pomógł: 57
    Ocena: 18
    Czołem,

    Mam problem z przesyłem danych USARTEM. Mam taką o to funkcję:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jeśli wyślę dwa stringi, z których drugi jest krótszy od pierwszego to na koniec drugiej transmisji dodawane są końcowe znaki pierwszej transmisji:

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

    Otrzymuję:
    tekst123
    TEKST123

    Jeśli zastosuję preinkrementację wskaźnika to obetnie mi pierwszy znak ze stringa. Nie wiem jak to rozwiązać
  • Pomocny post
    #2 15379818
    szelus
    Poziom 34  
    Posty: 1508
    Pomógł: 315
    Ocena: 53
    Zasadniczo nie jest to możliwe, tzn. funkcja wysyłająca wygląda dobrze, problem jest gdzieś indziej.
    Masz dokładnie taki program, jak pokazałeś?
    Jak odbierasz i wyświetlasz?
  • #3 15379875
    Hyde911
    Poziom 24  
    Posty: 752
    Pomógł: 57
    Ocena: 18
    szelus napisał:
    Zasadniczo nie jest to możliwe, tzn. funkcja wysyłająca wygląda dobrze, problem jest gdzieś indziej.
    Masz dokładnie taki program, jak pokazałeś?
    Jak odbierasz i wyświetlasz?


    Rzeczywiście, problem był w programie odczytującym dane:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Dziękuję za pomoc.
  • Pomocny post
    #4 15379945
    szelus
    Poziom 34  
    Posty: 1508
    Pomógł: 315
    Ocena: 53
    To dalej nie jest dobry kod. Co, wg Ciebie, sprawdza poniższy warunek?
    Cytat:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    Zamiast zerować bufor, zapewne wystaczy poprawnie sprawdzać długość.
    Zwracając message przez wartość kopiujesz ją jeszcze raz.
  • #5 15380057
    Hyde911
    Poziom 24  
    Posty: 752
    Pomógł: 57
    Ocena: 18
    Masz racje, wystarczy tak:

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


    A co do wartości zwracanej, to próbuję wymyślić jakiś powód dla którego nie chcę zwracać wskaźnika :)
    Ale wygląda na to, że wskaźnik będzie odpowiedni.
  • #6 15380529
    szelus
    Poziom 34  
    Posty: 1508
    Pomógł: 315
    Ocena: 53
    Wskaźnik możesz zwracać, o ile zaalokujesz message przez new. Ale to kłopot, bo potem trzeba pamiętać o zwolnieniu. No chyba, że shared_ptr (C++11).
    Najprościej jest przekazać przez referencję jako argument zmienną, do której ma być zwrócona wiadomość:
    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #7 15380582
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    W C++ można spokojnie zwracać zmienne przez wartosć, ponieważ wykorzystane zostanie "return value optimization". Ta optymalizacja jest wręcz obowiązkowa w C++11, w którym do tego celu zostanie użyte "move semantics". Zwracanie przez wartość to często najbardziej optymalna opcja jaką można zastosować!

    A nawet jeśli to zwracanie stringa wywoła alokację, to co z tego? Komuś na PC skończy się RAM? U siebie mam w tym momencie 11GB wolnej pamięci - czy to jakiś problem jakbym sobie alokował krótkie stringi bez przesadnej kombinacji? Nie mówiąc już nawet o tym, że klasa std::string często posiada coś takiego jak "small string optimization", czyli krótkie łańcuchy nie są alokowane dynamicznie tylko przechowywane "wewnątrz" obiektu.

    Tak więc naprawdę nie ma co kombinować - C++ jest skomplikowanym językiem, pewne nawyki znane z C są w nim często błędne lub przynajmniej zupełnie niepotrzebne.
  • #8 15380596
    Hyde911
    Poziom 24  
    Posty: 752
    Pomógł: 57
    Ocena: 18
    Referencja jest chyba najlepszym sposobem, gdyż w innym miejscu (i oddzielnym wątku) odczytuję dane:

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


    Jeszcze raz dziękuję.
  • #9 15380606
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Hyde911 napisał:
    Referencja jest chyba najlepszym sposobem, gdyż w innym miejscu (i oddzielnym wątku) odczytuję dane:

    Nie jest - jak włączysz C++11 i zwrócisz "przez wartość" to zostanie wykorzystany operator "move assignment" i nie będzie żadnej alokacji. Przy starszych standardach języka może być różnie - być może dokładnie tak samo ("return value optimization" zostało wprowadzone znacznie wcześniej niż C++11), ale na pewno zwracanie przez wartość nie będzie problemem w Twoim programie. Do tego taki sposób jest niezawodny, a to duża zaleta.
  • #10 15380656
    szelus
    Poziom 34  
    Posty: 1508
    Pomógł: 315
    Ocena: 53
    Freddie, ja sam w błąd wprowadzam, nie ma powodu do korzystania z liczby mnogiej. :twisted:

    Przyznaję, że za C++11 trochę nie nadążam, mimo, że to już trochę ;) czasu obowiązuje - z wiekiem ten czas się jakoś tak dramatycznie kurczy. Jak to ktoś, gdzieś określił, "jak chińska koszulka w praniu". :)

    Rzeczywiście, nie ma co kombinować, nawet, jeżeli to nie jest na PC-cie i nie ma paru giga RAMu. Mój błąd.

    Freddie Chopin napisał:
    ale na pewno zwracanie przez wartość nie będzie problemem w Twoim programie. Do tego taki sposób jest niezawodny, a to duża zaleta.

    Zwracanie przez referencję też jest niezawodne, ale na pewno mniej czytelne. Stąd, domyślam się, takie a nie inne zmiany w C++11.
  • #11 15380739
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    szelus napisał:
    Freddie, ja sam w błąd wprowadzam, nie ma powodu do korzystania z liczby mnogiej.

    Sorry, nie wiem czemu myślałem że w temacie wypowiadał się jeszcze jeden user na samym początku - nie sprawdziłem, mój błąd (;

    szelus napisał:
    Stąd, domyślam się, takie a nie inne zmiany w C++11.

    Ponownie warto podkreślić, że RVO nie jest cechą tylko C++11 - wg wiki cecha ta (popularniejszą nazwą jest jednak "copy elision") została umieszczona już w standardzie C++03.

    https://en.wikipedia.org/wiki/Copy_elision

Podsumowanie tematu

✨ Użytkownik zgłosił problem z przesyłem danych przez USART w mikrokontrolerze STM32F4, gdzie końcowe znaki pierwszego stringa były dodawane do drugiego. Po analizie okazało się, że problem leżał w kodzie odbierającym dane, który nie czyścił bufora po odczycie. Użytkownik poprawił kod, dodając odpowiednie czyszczenie bufora oraz poprawiając sposób odczytu danych. Dyskusja dotyczyła również optymalizacji zwracania zmiennych w C++, gdzie podkreślono zalety zwracania przez wartość oraz użycia referencji.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA