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.

C - USART wysyłanie tablicy znaków

Kudzu 11 Wrz 2013 22:20 2838 25
  • #1 11 Wrz 2013 22:20
    Kudzu
    Poziom 14  

    Witam,
    wykonałem układ z ATmega88, który m.in. wykorzystuje wyświetlacz alfanumeryczny VFD. Mikrokontroler poprzez USART wysyła polecenia i znaki w oparciu o następujący kod:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Funkcji USART_Transmit w formie:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    używam do wysyłania poleceń obsługujących wyświetlacz.

    Funkcji Send_String w formie:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    używam do wyświetlania tekstu.

    Wszystko działa prawidłowo. Niestety, jako początkujący programista, obsługę wyświetlacza (wypisywanie informacji) umieściłem w przerwaniach w rozmaitych funkcjach. Chciałbym jednak przenieść obsługę wyświetlacza do głównej pętli programu, a w przerwaniach zmieniać jedynie zawartość tablicy znaków. Niestety podstawienie do funkcji Send_String tablicy znaków powoduje wystąpienie błędu z powodu, jak mniemam, konfliktu typu zmiennych:
    Cytat:

    error: incompatible types when assigning to type ‘char[5]’ from type ‘char *’


    Co zrobić z tym fantem?

    W innym wątku znalazłem takie rozwiązanie:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    ale nie wiem czy w pętli for trzeba dla każdej tablicy określać wartość zmiennej i w zależności od ilości znaków?

    Podsumowując - jak to zrobić, żebym mógł w różnych częściach programu, w różnych sytuacjach podstawiać odpowiednie teksty do tablicy, a następnie zawartość tej tablicy wysyłać przez USART, gdy procesor nie będzie zajęty przerwaniami?

    0 25
  • #2 11 Wrz 2013 22:25
    Szymon Tarnowski
    Poziom 27  

    Ja bym zadbał żeby tablica miała ostatni znak '\0' i zrzutował char[5] na char*.

    0
  • #3 11 Wrz 2013 23:24
    Kudzu
    Poziom 14  

    Szymon Tarnowski napisał:
    Ja bym zadbał żeby tablica miała ostatni znak '\0' i zrzutował char[5] na char*.

    A to nie jest tak, że tablica automatycznie dodaje na końcu NUL?
    Co znaczy zrzutował? Jestem bardzo początkujący. Na potrzeby tego projektu zacząłem zagłębiać się w C i avr, choć uruchomienie komunikacji szeregowej z VFD, obsługa PGA2310 po SPI i parę innych drobiazgów dało mi dużo satysfakcji:)

    0
  • #4 11 Wrz 2013 23:31
    krru
    Poziom 32  

    Kudzu napisał:
    Szymon Tarnowski napisał:
    Ja bym zadbał żeby tablica miała ostatni znak '\0' i zrzutował char[5] na char*.

    A to nie jest tak, że tablica automatycznie dodaje na końcu NUL?


    W takim zapisie jak wyżej nie.
    W takim:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    tak - napis w "" to literał napisowy i zawiera końcowe zero.
    Przy braku zera twoja funkcja będzie wysyłała śmiecie, aż w końcu trafi na jakieś zero.

    0
  • #5 12 Wrz 2013 00:44
    Kudzu
    Poziom 14  

    Czyli rozumiem, że zamiast mojej funkcji Send_String z początku pierwszego postu, mam wykorzystać tą znalezioną, tylko w zapisie "", tak?
    I teraz pytanie, które zadałem na początku - jak w tej funkcji definiować zmienną 'i' w pętli for? Czy musi zliczać dokładnie tyle, ile znaków będzie miała tablica (a może być różnie)? Czy można dać maksymalną wartość jaka zmieści się w wierszu wyświetlacza? Tylko co się stanie wtedy, jeżeli tablica będzie krótsza?

    Dodano po 3 [minuty]:

    Szymon Tarnowski napisał:
    zrzutował char[5] na char*.

    I co to znaczy? Bo może wystarczy "zrzutować" i będę mógł wywoływać moją fukcję Send_String z tąż tablicą, co nie będzie wywoływało błędu, który cytowałem w pierwszym poście?

    0
  • #6 12 Wrz 2013 07:08
    krru
    Poziom 32  

    Przecież twoja pierwotna funkcja właśnie wysyła znaki, aż napotka końcowe \0. Bez tego zera jest problem, ale dodanie powinno rozwiązać problem. Tak w ogóle to pokaż trochę więcej tego kodu, który nie działa, bo nie wiadomo co tam było źle. Pokazałeś kawałki, które działają, ale nie pokazałeś tego, który powoduje problemy.

    I jeszcze jedna uwaga kosmetyczna: Zmień nagłówek funkcji na:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #7 12 Wrz 2013 13:15
    Kudzu
    Poziom 14  

    Niestety jestem laikiem, nie potrafię posługiwać się fachowymi określeniami, dlatego pewnie zupełnie się nie rozumiemy.
    Ja wiem, że moja funkcja działa i wysyła ciągi znaków. Pisałem, że program jako taki jest ok.
    To, czego chcę, to zamiast w przerwaniach wykonywać polecenie:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    i zajmować czas przerwania komunikacją z wyświetlaczem,
    robić to tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    W tej chwili wprost nie da się tego zrobić, ponieważ kompilator zgłasza wyżej wspomniany błąd.

    Wklejanie reszty kodu nie ma wg mnie sensu, bo nic nie wniesie do sprawy, a zmniejszy czytelność wątku (ok 1000 wierszy).

    0
  • Pomocny post
    #8 12 Wrz 2013 18:09
    krru
    Poziom 32  

    Ale błąd musi być gdzie indziej - taki kawałek powinien się skompilować bez problemów, jest całkowicie poprawny. Napisałem testowo taki kod:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    I nie ma nawet jednego ostrzeżenia.

    W C często komunikat błędu zgłasza się trochę później niż faktyczny błąd, bo np. brakuje średnika, zamknięcia nawiasu albo napisu (") i dopiero któraś następna linijka kodu nie pasuje do składni.
    Możesz spróbować wyizolować ze swojego kodu taki kawałek, który ciągle zgłasza błąd, ale jest na tyle mały, że da się go pokazać. Z resztą jest duża szansa, że zanim osiągniesz taki etap, już sam będziesz wiedział gdzie jest błąd.

    0
  • #9 12 Wrz 2013 20:05
    stanleysts
    Poziom 27  

    może niech kolega pokaże ten kawałek kodu.

    0
  • #10 12 Wrz 2013 20:25
    Kudzu
    Poziom 14  

    krru napisał:
    Ale błąd musi być gdzie indziej - taki kawałek powinien się skompilować bez problemów, jest całkowicie poprawny. Napisałem testowo taki kod:
    Kod: c
    Zaloguj się, aby zobaczyć kod



    Zgadza się - mnie też się skompilowało i w takiej formie działa bez problemu:) Ale jest to trochę inne niż moja wersja, bo ja miałem tak (było w pierwszym poście):
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Różnica jest w pętli while funkcji f. Mnie to działało, ale tylko wtedy, gdy argumentem funkcji f był tekst w "".

    Dlatego dziękuję wszystkim za pomoc, a szczególnie koledze @krru za zaangażowanie.

    Nie będę od razu zamykał wątku, bo może kolega @krru skomentuje jeszcze to rozwiązanie, żebym wyciągnął jakąś naukę z tego topiku:)

    0
  • #11 12 Wrz 2013 21:08
    stanleysts
    Poziom 27  

    Nic tam złego nie ma, błąd był gdzieś indziej (mówię o dokładnie takim kodzie jak jest wklejony (2gi kod).

    0
  • #12 12 Wrz 2013 21:18
    Kudzu
    Poziom 14  

    stanleysts napisał:
    Nic tam złego nie ma, błąd był gdzieś indziej (mówię o dokładnie takim kodzie jak jest wklejony (2gi kod).

    Ale nie działało, a nic więcej nie zmieniałem. Poza tym zrobiłem też tak, że usunąłem wszystko, pozostawiłem tylko ten fragment - nie działał.

    Dodano po 30 [sekundy]:

    Tzn pozostawiłem niezbędne minimum;)

    0
  • #13 12 Wrz 2013 21:18
    stanleysts
    Poziom 27  

    No nie wiem, tam nie ma błędu :P

    0
  • #14 12 Wrz 2013 21:46
    Kudzu
    Poziom 14  

    stanleysts napisał:
    No nie wiem, tam nie ma błędu :P

    Szlag człowieka czasem może z tym trafić;)
    I tak na razie muszę porzucić ten temat, bo mam większy problem - to co skompilowałem kiedyś w KontrollerLab i działało, teraz skompilowane przez avr-gcc nie działa i nawet hex mniej waży. Ale to chyba problem na inny wątek.

    0
  • #15 12 Wrz 2013 21:51
    stanleysts
    Poziom 27  

    Czemu nie działa jakieś błedy kompilatora, jak nie tak to może źle napisany kod i się przy większej optymalizacji wysypuje. Jak coś to wrzuć kod nie działający.

    0
  • #16 12 Wrz 2013 22:03
    Kudzu
    Poziom 14  

    stanleysts napisał:
    Czemu nie działa jakieś błedy kompilatora, jak nie tak to może źle napisany kod i się przy większej optymalizacji wysypuje. Jak coś to wrzuć kod nie działający.


    Heh, no ok, wrzucam więc kod. Od razu jednak uprzedzam, że to jest mój pierwszy program w C i mogą występować rażące programistów błędy. Poza tym kod jest nieco rozlazły - dla mnie bardziej przejrzysty.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #17 12 Wrz 2013 22:10
    stanleysts
    Poziom 27  

    Troche tego dużo i lepiej jakby było chyba na jakieś pliki podzielone, program się wogóle kompiluje? Btw na jaką atmege to jest kod?

    0
  • #18 12 Wrz 2013 22:19
    Kudzu
    Poziom 14  

    stanleysts napisał:
    Troche tego dużo i lepiej jakby było chyba na jakieś pliki podzielone, program się wogóle kompiluje? Btw na jaką atmege to jest kod?

    To jest na mega88a z kwarcem 1843200. Program się kompilował w KontrollerLab. To jest akurat wersja testowa, a muszę sprawdzić na jakiejś wersji stabilnej (ogólnie mam kilkanaście wersji kodu). Eclipse niestety wywala mi jakiś error, ale co on oznacza to jeszcze nie wiem.

    0
  • #19 12 Wrz 2013 22:20
    stanleysts
    Poziom 27  

    Wklej go tutaj, trzeba zacząć od tego. To ciekawe, bo mi się pod winavr i eclipsem ten projekt zbuował bez błędów.

    0
  • #20 12 Wrz 2013 22:21
    Kudzu
    Poziom 14  

    najlepszym dowodem na to, że program działa jest mój wzmacniacz, który cały czas pracuje - wyświetlacz działa, regulacja głośności działa, sterowanie przyciskiem, enkoderem i pilotem RC5 działa:)

    0
  • #21 12 Wrz 2013 22:26
    stanleysts
    Poziom 27  

    No to wrzuć tu ten bład jaki wyskakuje.

    0
  • #22 12 Wrz 2013 22:54
    Kudzu
    Poziom 14  

    Włączyłem optymalizację -Os i wszystko poszło ok. Program działa:) Ponieważ, jak się okazuje, Eclipse również korzysta z avr-gcc i wyświetla polecenie, więc wychodzi na to, że w moim poleceniu avr-gcc albo zabrakło jakiegoś parametru albo coś źle skonfigurowałem.

    Dodano po 2 [minuty]:

    avr-gcc -Wall -Os -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega88a -DF_CPU=1843200UL -MMD -MP -MF"source.d" -MT"source.d" -c -o "source.o" "../source.c"

    Cholera wie, co w tym jest ważne, a co nie;)

    0
  • Pomocny post
    #23 12 Wrz 2013 23:10
    stanleysts
    Poziom 27  

    avr gcc i do dzieła, wszystko będzie jasne :D

    avr-gcc -Wall (printuj wszystkie warnigs) -Os (optymalizacja pod kątem rozmiaru) -fpack-struct (pakuj struktury bez dziur (not aligned) -fshort-enums (upakuj enumy do jak najmniejszego rozmiaru) -std=gnu99 -funsigned-char (char traktuj jako unsigned) -funsigned-bitfields (to samo z polami bitowymi) -mmcu=atmega88a (procek) -DF_CPU=1843200UL (czestotliwosc) -MMD -MP -MF"source.d" -MT"source.d" (tego już nie wiem, jest dokumentacja) -c -o "source.o" "../source.c" no to już normalne polecenie kompilatora

    0
  • #24 13 Wrz 2013 00:07
    Kudzu
    Poziom 14  

    No i właśnie nic z tego nie wychodzi;)
    Moje podejrzenie pada na avr-objcopy. Ja kompiluję do pliku *.o i z tego robię *.hex. Eclipse kompiluje do *.elf i z tego robi hexa.

    Code:

    **** Build of configuration Release for project MiniAmp ****

    make all
    Building file: ../source.c
    Invoking: AVR Compiler
    avr-gcc -Wall -Os -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega88a -DF_CPU=1843200UL -MMD -MP -MF"source.d" -MT"source.d" -c -o "source.o" "../source.c"
    ../source.c:10:0: warning: "F_CPU" redefined [enabled by default]
    <command-line>:0:0: note: this is the location of the previous definition
    Finished building: ../source.c
     
    Building target: MiniAmp.elf
    Invoking: AVR C Linker
    avr-gcc -Wl,-Map,MiniAmp.map -mmcu=atmega88a -o "MiniAmp.elf"  ./source.o   
    Finished building target: MiniAmp.elf
     
    Invoking: AVR Create Extended Listing
    avr-objdump -h -S MiniAmp.elf  >"MiniAmp.lss"
    Finished building: MiniAmp.lss
     
    Create Flash image (ihex format)
    avr-objcopy -R .eeprom -O ihex MiniAmp.elf  "MiniAmp.hex"
    Finished building: MiniAmp.hex
     
    Create eeprom image (ihex format)
    avr-objcopy -j .eeprom --no-change-warnings --change-section-lma .eeprom=0 -O ihex MiniAmp.elf  "MiniAmp.eep"
    Finished building: MiniAmp.eep
     
    Invoking: Print Size
    avr-size --format=avr --mcu=atmega88a MiniAmp.elf
    AVR Memory Usage
    ----------------
    Device: atmega88a

    Program:    4272 bytes (52.1% Full)
    (.text + .data + .bootloader)

    Data:        187 bytes (18.3% Full)
    (.data + .bss + .noinit)


    Finished building: sizedummy
     

    **** Build Finished ****

    0
  • #25 13 Wrz 2013 00:14
    stanleysts
    Poziom 27  

    No ale to nie jest problem z kompilatorem... Zmień sobie to na hex.

    0
  • #26 13 Wrz 2013 12:15
    Kudzu
    Poziom 14  

    Ok, przedziwna sprawa. Potwierdza się, że fragment kodu:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    działa. Skompilowałem to w Eclipse. Błąd pojawiał się, kiedy próbowałem kompilować to samodzielnie przez avr-gcc. Może to jednak świadczyć o tym, że jest w całym kodzie programu jakiś błąd, ale jeden z dodatkowych parametrów do avr-gcc powoduje ominięcie tego problemu.
    W każdym razie temat został rozwiązany doraźnie. Nad źródłem problemu zastanowię się innym razem. Podobnie porzucam problem kompilacji przez avr-gcc.

    Dziękuję wszystkim za pomoc!

    0