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.

[AVR][C] Deklaracja ciagu znaków

m_misek 29 Sty 2018 21:48 1404 32
  • #1 29 Sty 2018 21:48
    m_misek
    Poziom 10  

    Witam.
    Opisze krótko :

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Wysłana poprzez UART jest poprawna.
    natomiast deklaracja jako :
    Kod: c
    Zaloguj się, aby zobaczyć kod

    powoduje wysłanie na UART samych 0xFF.

    Kod się kompiluje, UART dziala porpawnie, Procesor ATmega 2560.
    Kompilowałem pod AVRStudio 7, AVR Studio 6.2 i AVR Studio 4.19, wszedzie ten sam efekt.

    Gdzie zatem problem ?, skoro po skompilowaniu kodu pod x86 (gcc) wyswietla się prawidłowo.

    Dodam także ze wszelakie definiowanie przerwań, oraz ich obsługi powoduje reset procesora - moze to inna kwestia, ale być moze powiązana.

    0 29
  • #2 30 Sty 2018 00:40
    3099750
    Użytkownik usunął konto  
  • #3 30 Sty 2018 01:04
    Marek_Skalski
    Moderator Projektowanie

    Reset może wynikać z wielu rzeczy, ale skoro jest związany z przerwaniami, to obstawiam brak zdefiniowanej funkcji obsługi przerwania.
    Pokaż funkcję wysyłającą dane przez UART i/lub wyświetlającą dane na x86.

    @AnicoZ U mnie też się kompiluje bez błędów. Wiem, że w napis1 brakuje terminatora, ale kompilator tego nie może wychwycić, ponieważ jawnie zadeklarowana jest liczba elementów tablicy, a elementy są wpisywane pojedynczo. To nie jest string.

    0
  • #4 30 Sty 2018 01:28
    3099750
    Użytkownik usunął konto  
  • #5 30 Sty 2018 03:17
    JacekCz
    Poziom 36  

    wer 1. tworzy napis bez zwyczajowego/ wymaganego znaku zero \0 na końcu. Używa się czasem takiej formy, ale tzreba być świadomym. Nie każde użycie będzie prawidłowe.
    wer 1 i 2 zależnie jak są użyte w szerszym kontekście: są statyczne, lokalne w funkcjach, a co gorsza zwracana w funkcji będą się zachowywać bardzo rożnie

    0
  • #6 30 Sty 2018 08:48
    michcior
    Poziom 30  

    Jest zasadnicza różnica pomiędzy tymi deklaracjami. Obie z pozoru maja robić to samo. Pierwsza inicjuje zawartość tablicy wprost, wartościami dla wygody podawanymi jako znaki.
    Kompilator a dokładnie linker zbiera wszystkie inicjowane zmienne "do kupy". Umieszcza je w obrazie a następnie, tuż po starcie specjalny kod (czasami kompilator go generuje, czasami trzeba go tworzyć) kopiuje te wartości do RAM tam gdzie wskazują zmienne.
    Druga deklaracja, to "string literal". Domyślnie wszystkie takie teksty to są umieszczane w obrazie (w miejscu niemodyfikowanym) no bo to są stałe! GCC poprawnie jednak rozumie ten zapis i nie traktuje tego jako stały tekst, tylko inicjuje tym zmienną tak samo jak w #1. Właśnie, dlaczego tego nie robi w twoim przypadku kompilator AVR?
    1) sprawdź gdzie wskazują zmienne "napis1" i "napis2" obie powinny wskazywać na RAM (np. printf "%p\n\r",napis1);
    2) sprawdź zawartość pamięci wskazywanej przez napis2, jeśli tam są 0xFF to znaczy, że obszar nie jest inicjowany tak jak to opisałem.
    3) przeglądaj pliki wynikowe kompilacji, jeśli są tworzone raporty, czy jakieś mapy linkera to jest dobra "kopalnia" informacji co się na prawdę dzieje.
    4) przeszukaj obraz wyszukując tekstu "Napis", powinien leżeć tuż przy "Napis" z pierwszej deklaracji (zmień teksty, tak by się różniły).
    5) po cichu zakładam, że zmienne nie są lokalne dla funkcji tylko są globalne/statyczne?

    0
  • #7 30 Sty 2018 09:01
    BlueDraco
    Specjalista - Mikrokontrolery

    Bez pokazania kodu nie otrzymasz realnej pomocy - dywagacje Kolegów powyżej są ciut oderwane od rzeczywistości. NIC nie wiemy o tym, w jaki sposób wysyłasz te napisy na terminal, ani gdzie są one zadeklarowane, a to w tym leży problem, a nie w samych napisach.

    0
  • #8 30 Sty 2018 10:58
    JacekCz
    Poziom 36  

    michcior napisał:
    Jest zasadnicza różnica pomiędzy tymi deklaracjami. Obie z pozoru maja robić to samo. Pierwsza inicjuje zawartość tablicy wprost, wartościami dla wygody podawanymi jako znaki.
    Kompilator a dokładnie linker zbiera wszystkie inicjowane zmienne "do kupy". ....


    Wiele nieścisłości czy "medialnego dramatyzmu" jest w twojej wypowiedzi. A już z całą pewnością nie linker zbiera pojedyncze literki.
    Chciałeś dobrze, ale kilkakrotnie mijasz sie ze szczegółami.

    Recepta na analizę obrazów linkera, jak nie mamy najbardziej banalnego kodu ???

    BlueDraco napisał:
    Bez pokazania kodu nie otrzymasz realnej pomocy - dywagacje Kolegów powyżej są ciut oderwane od rzeczywistości. NIC nie wiemy o tym, w jaki sposób wysyłasz te napisy na terminal, ani gdzie są one zadeklarowane, a to w tym leży problem, a nie w samych napisach.


    To jest istota: bez reszty kodu nie da się pomóc.

    0
  • #9 30 Sty 2018 11:02
    michcior
    Poziom 30  

    JacekCz napisał:
    A już z całą pewnością nie linker zbiera pojedyncze literki.
    Chciałeś dobrze, ale kilkakrotnie mijasz sie ze szczegółami.

    Jeśli wiesz lepiej, podziel sie wiedzą, będzie to z korzyścią dla wszystkich zainteresowanych. Na razie, twoja wypowiedź to "wiem, ale nie powiem"

    0
  • #10 30 Sty 2018 11:10
    BlueDraco
    Specjalista - Mikrokontrolery

    michcior: Ty podzieliłeś się "wiedzą" na zasadzie "nie wiem, ale powiem", więc jakaś równowaga została przywrócona. Jedyna różnica pomiędzy tymi dwiema deklaracjami - to brak zera na końcu łańcucha w pierwszej i w konsekwencji różna (o jeden bajt) długość danej.

    0
  • #11 30 Sty 2018 12:26
    michcior
    Poziom 30  

    BlueDraco napisał:
    Jedyna różnica pomiędzy tymi dwiema deklaracjami - to brak zera na końcu łańcucha w pierwszej i w konsekwencji różna (o jeden bajt) długość danej.

    Nie jest to jedyna różnica, np:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Pierwsza deklaracja może być problematyczna za względu na kodowanie znaków, o czym poinformuje kompilator. Druga zadziała poprawnie.

    0
  • #12 30 Sty 2018 12:56
    BlueDraco
    Specjalista - Mikrokontrolery

    I znów piszesz nieprawdę. Standard C nie mówi nic o interpretacji przez kompilator znaków spoza zestawu ASCII - w obu przypadkach zachowanie jest nieokreślone.

    0
  • #13 30 Sty 2018 16:45
    m_misek
    Poziom 10  

    Ok, pędze z wyjaśnieniami :
    funkcja wysylająca na UART :

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Mozna powiedizeć ze klasyk wprost z dokumnetacji do procka. Funckje w osobnym pliku, wysylanie jednago znaku działa poprawnie.
    UARTSendChars - wysyla same 0xFF

    Zniechecony tym wszystkim - wpisalem to samo do funckji main()

    Kod: c
    Zaloguj się, aby zobaczyć kod

    rowniez daje same 0xFF
    natomiast jesli w petli wstawie na sztywno nr znaku z tablicy:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    To bez wzgledu na to czy przy deklaracji podam rozmiar tablicy,
    poprawnie przesyla , w tym przypadku 0x65, więc gdzieś ta tablica jest zapisana, tylko odwołanie do jej elementów w pętli jest jakby "niepoprawne"

    michcior napisał:
    5) po cichu zakładam, że zmienne nie są lokalne dla funkcji tylko są globalne/statyczne?

    Kompletnie jest to bez roznicy, globalna, lokana czy statyczna.

    Co do przerwań - nawet jak skompiluje kod sprzed 5-7 lat z atmega8 - po dostosaniu do Atmega2560 to dalej sie resetuje, ale poki co bardziej interesuje mnie kwestia jak w temacie.

    Czy moze to kwestia, kompilatora, uzyt3ego stopnia optymalizacji ?

    0
  • #14 30 Sty 2018 16:58
    gaskoin
    Poziom 38  

    m_misek napisał:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zniechecony tym wszystkim - wpisalem to samo do funckji main()

    Kod: c
    Zaloguj się, aby zobaczyć kod



    No to Twoim problemem jest brak terminatora.

    unsigned char message[5] ="tekst";

    Jak myślisz, skoro "tekst" ma 5 znaków, to gdzie jest terminator?

    0
  • #16 30 Sty 2018 17:05
    gaskoin
    Poziom 38  

    michcior napisał:
    A tak?
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Przecież napisał, że jak poda rozmiar to działa. Poza tym w Twoim programie też się "tekst" nie mieści w tablicy i brakuje mu dzięki temu terminatora. Dodatkowo nie widzę sensu w posługiwaniu się kopią wskaźnika na tablicę, co to zmienia?

    0
  • #17 30 Sty 2018 17:20
    3099750
    Użytkownik usunął konto  
  • #18 30 Sty 2018 17:24
    JacekCz
    Poziom 36  

    Kolego, poruszasz się po kodzie na oślep, masz tzw "parzystą ilość błędów" (to pewnego rodzaju hasło, kto programuje, to wie, chodzi o ukrywanie błędów)

    Wpadasz tu z sensacyjnym odkryciem błędu w formalnościach C, a może by na początek dobrze przeczytać warningi? Nie wierzę, że 6 znaków dało się wcisnąć do 5 bez protestów kompilatora (brak panowania nad signed / unsigned???)
    Używasz nieprawidłowo swojej własnej funkcji bibliotecznej, czasem przez nią przechodzisz, czasem pomijasz. Metodyka Kopiego &Pejsta?

    Mówisz o "resetowaniu", myślę że masz liczne inne błędy ... skąd wiem? Mocno przypuszczam, po tym jak tego "tajnego" kodu bronisz. Zgaduję błędy w tej samej proporcji jak masz błędy w pięciu liniach.

    0
  • #19 30 Sty 2018 18:33
    m_misek
    Poziom 10  

    JacekCz napisał:
    Mówisz o "resetowaniu", myślę że masz liczne inne błędy ... skąd wiem? Mocno przypuszczam, po tym jak tego "tajnego" kodu bronisz. Zgaduję błędy w tej samej proporcji jak masz błędy w pięciu liniach.

    Nic nie bronie, nie ma zadnego tajnego kodu, prosze bardzo :
    Kod: c
    Zaloguj się, aby zobaczyć kod

    W przykladzie powyzej nic sie nie resetuje, kompiluje sie bez warningow.
    Bez roznicy czy zadeklaruje to jako unsigned czy nie, wynik zawsze jest ten sam.
    Jak widac wyslanie pojedynczego znaku dizała. I jedyna zadeklarowana tablica ktora potrafi cos przeniesc procz 0xFF to test4, pod warunkiem ze odwołam sie bezposrednio a nie poprzez zmienną i -i to jest kwintesencja pytania - dlaczego tak jest ,ze odwołując się liczba jest ok, a odwołując się zmienną nie jest ok ?

    A czym że jest "parzysta ilośc błędów" - rozwiń myśl jeśli mozesz.

    0
  • #20 30 Sty 2018 18:52
    BlueDraco
    Specjalista - Mikrokontrolery

    Bardzo jestem ciekaw, skąd wiesz, która pętla wysyła które znaki. Zadeklaruj łańcuch po ludzku:

    char s[] = "abcde";
    (takie coś tworzy 6-bajtowy wektor zawierający pięć literek i 0 na końcu).
    I testuj na nim procedurę wysyłania łańcucha, która kończy, gdy napotka bajt 0.

    0
  • #22 30 Sty 2018 19:11
    el2010tmp
    Poziom 25  

    Przykład pierwszy z brzegu:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #23 30 Sty 2018 19:13
    BlueDraco
    Specjalista - Mikrokontrolery

    W Twoim programie nie pobierasz nic z "program space". Być może nie zgadza się typ procesora na płytce z tym zadeklarowanym w środowisku, albo masz ustawiony jakiś "tryb zgodności".

    0
  • #24 30 Sty 2018 19:17
    m_misek
    Poziom 10  

    Prosze bardzo :

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Powyzy kod daje mi na terminalu :
    FF FF FF FF FF FF !21 FF 01 FF AA
    czyli bzdury, po za ostanim znakiem ( jawnie zadeklarowanym)
    Zmienilem nawet z 8E1 na 8N1, ale róznica żadna.

    Wiec co teraz jest nie tak ? zła pętla ? no ale odwołanie bezpośrednio do s[1] tez wypisuje bzdury.

    BlueDraco napisał:
    W Twoim programie nie pobierasz nic z "program space". Być może nie zgadza się typ procesora na płytce z tym zadeklarowanym w środowisku, albo masz ustawiony jakiś "tryb zgodności".

    Procesor to Atmega2560, na płytce XDRduino Mega 2560 , programowany przez ISP, przy uzyciu USBasb ( AVRDUDES 2.4 - wykrywa poprawnie procesor) taki sam jest uzyty w projecke w AVRStudio.

    0
  • #25 30 Sty 2018 19:23
    el2010tmp
    Poziom 25  

    Spróbuj dla zasady:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #26 30 Sty 2018 19:35
    m_misek
    Poziom 10  

    Nic to nie zmienia.
    Moze inaczej. Czy moglbym prosic o plik hex z kodem jak powyzej? W ten sposob zweryfikuje czy moj kompilator nie robi jakis bzdur, albo sam procesoror.

    0
  • #27 30 Sty 2018 19:39
    3099750
    Użytkownik usunął konto  
  • #29 30 Sty 2018 19:58
    Marek_Skalski
    Moderator Projektowanie

    @m_misek Z ciekawości wrzuciłem Twój program do Atmel Studio i sprawdziłem jego wykonanie w symulatorze. Nie widzę żadnych błędów.
    Więcej, ciąg znaków najpierw jest kopiowany z Flash do RAM, a następnie na stos. To co widzisz jako 21 FF, to jest zawartość stosu bezpośrednio za tablica znaków wrzuconą na stos.
    Proponuje sprawdzić:
    1. Jaki układ masz ustawiony w projekcie i czy to na pewno jest Atmega2560. Jeżeli tak, to punkt 2.
    2. Czy program w symulatorze wykonuje się prawidłowo. Jeżeli tak, to punkt 3.
    3. Jak wygląda zasilanie uC. Czy jest odpowiednie napięcie, czy jest zapewniona odpowiednia wydajność prądowa, czy są wszystkie kondensatory blokujące. Jeżeli tak, punkt 4.
    4. Sprawdzić na innym egzemplarzu, najlepiej na innej płytce. Jeżeli nadal jest błąd to więcej propozycji nie mam.

    0
  • #30 30 Sty 2018 22:01
    michalko12
    Specjalista - Mikrokontrolery

    m_misek napisał:
    UART dziala porpawnie


    Even Parity świadomie włączone? Jeśli tak to też poprawnie skonfigurowane na drugim końcu kabla?

    0