Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[Rozwiązano] [XMEGA][C] UART/USART - obsługa komend

8888domino8888 30 Sie 2018 19:47 378 8
  • #1 30 Sie 2018 19:47
    8888domino8888
    Poziom 3  

    Witam.
    Piszę aplikację w języku C służącą do komunikacji mikrokontrolera AVR XMEGA32A4 poprzez interfejs UART/USART. Docelowo interfejs ten ma być połączony z modułem Bluetooth i służyć do komunikacji z telefonem. Aplikacja na telefonie sterowałaby mikrokontrolerem i urządzeniami peryferyjnymi podpiętymi pod niego poprzez wysyłanie odpowiednich komend. Do napisania aplikacji skorzystałem z pomocy książki Tomasza Francuza "AVR. Praktyczne projekty" i wykorzystałem opisany tam kod, odpowiednio dostosowując go do swojego mikrokontrolera. Wykorzystany tam jest bufor nadawczy i odbiorczy danych.
    Rozwiązanie to działa świetnie przy maksymalnie 2 komendach, które należy wykryć (np. AT+LEDON, AT+LEDOFF) oraz komendy default-owej (Nieznane polecenie).
    Niestety problem pojawia się w przypadku, gdy chcę wykrywać więcej niż 2 komendy, czyli w przypadku gdy dopisuję kolejne warunki w instrukcji switch. W tym przypadku komendy nie są wykrywane, w odpowiedzi na wysłane komendy zawsze otrzymuję odpowiedź default-ową, czyli "Nieznane polecenie". Przypuszczam, że błąd mogą powodować funkcje TranslateCommand oraz GetToken, które służą do porównania otrzymanej komendy z tablicą komend oraz określają numer indeksu. Spędziłem sporo czasu na wykrycie tego błędu, niestety nie dałem rady, stąd bardzo proszę o pomoc.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0 8
  • #3 31 Sie 2018 01:09
    8888domino8888
    Poziom 3  

    Funkcja TranslateCommand() ma zwracać indeks odebranej komendy. Po testach zauważyłem, że zwraca po prostu ilość elementów w tablicy cmds[], czyli po prostu liczbę wszystkich komend.

    0
  • #5 31 Sie 2018 10:48
    tmf
    Moderator Mikrokontrolery Projektowanie

    Kod wygląda ok. Jeśli TranslateCommand zwraca liczbę elementów tablicy cmds[] to znaczy, że polecenie nie zostało w niej odnalezione. Przyczyną może być różnica w zapisie polecenia lub brak końcowego znaku NUL. Zobacz kod z innych przykładów - obsługują one znacznie więcej niż dwa polecenia i nie ma z tym problemów.

    0
  • #6 31 Sie 2018 21:02
    joik123
    Poziom 9  

    Spróbuj uruchomić testowy program, gdzie wysyłasz przez uarta to co odebrałeś, żeby sprawdzić samą komunikację. Co do tej funkcji to po prostu stwórz tablicę z odpowiednia komendą i daj ją jako argument funkcji. Po tym myślę że już znajdziesz przyczynę :D

    0
  • #7 01 Wrz 2018 23:08
    8888domino8888
    Poziom 3  

    Odnośnie sprawdzania zawartości tablicy "txt" to zdeklarowałem ją jako globalną a następnie odsyłałem jej zawartość po rozpoznaniu (lub nie rozpoznaniu) komendy. Miała ona zawsze tą samą zawartość, a dokładnie 143 powtarzająca się wartość "FF".
    Odnośnie różnicy w zapisie polecenia oraz braku znaku końcowego to też upewniłem się, lecz problemu tam nie było.
    Dodatkowo przetestowałem początkowy kod programu "usart-int", z wyżej wymieniowej książki, i niestety dzieje się tak samo, a więc po dodaniu powyżej drugiej komendy, komendy te nie są wykrywane.
    Odnośnie innych przykładów tam podanych to bardzo zależy mi na użyciu tylko przerwań, ponieważ program nie będzie przesyłał dużych ilości danych a będzie miał reagować jedynie na komendy.

    0
  • Pomocny post
    #8 06 Wrz 2018 17:51
    trol.six
    Poziom 30  

    8888domino8888 napisał:
    Rozwiązanie to działa świetnie przy maksymalnie 2 komendach,

    W kodzie jest błąd. A to że czasem działa wynika najprawdopodobniej z optymalizacji. Zobacz co się stanie jak skompilujesz z opcjami -O0

    Można tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Albo tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Swoją drogą, to zdajesie zadziała tylko jeśli adresy będą maksymalnie 16 bitowe.
    .

    0
  • #9 09 Wrz 2018 02:39
    8888domino8888
    Poziom 3  

    Już pierwsze rozwiązanie podane przez użytkownika trol.six zadziałało i naprawiło mój problem, za co jestem bardzo wdzięczny.

    Dodano po 6 [minuty]:

    Użycie funkcji pgm_read_word, czyli w moim programie to zamiana jednej linijki kodu użytej w funkcji TranslateCommand():
    if(strcmp_P(txt, cmds[indeks])==0) break;
    na:
    if(strcmp_P(txt, (char*)pgm_read_word(&cmds[indeks]))==0) break;

    0
  Szukaj w 5mln produktów