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

dziwne zachowanie uart? [m128][C]

AVRowiec 16 Lut 2010 04:13 1502 12
REKLAMA
  • #1 7701322
    AVRowiec
    Poziom 18  
    Do uartu przychodzą znaki. Algorytm ma za zadanie złożyć słowo ze znaków różnych od 0x0A (znak nowej linii).
    Nic prostszego:

     SIGNAL (USART0_RX_vect) 
    {
     odebranyZnak0 = UDR0; 
    
        if  (odebranyZnak0!=0x0A) 
    	{
                    slowo0[iii]=odebranyZnak0;
    	     iii++; 	
               }
         else
        {
             slowo0[iii]=0;   iii=0; 
    
             USART0_Transmit_Word(slowo0);
    	
        }
    
    }	


    Myślę że kod jest banalny, lecz mimo to zachowuje się przedziwnie.

    Jeśli wysyłam: abcde#010
    Wtedy odbieram: abcde

    Jeśli wysyłam: abcde#010#010
    Wtedy odbieram: abcde+puste słowo

    Jeśli wysyłam: abcde#010#010
    Wtedy odbieram: abcde+puste słowo+puste słowo

    Wszystko jest do tej pory ok. Jaja zaczynają się kiedy dam znak #010 (znak nowej linii zapisany dziesiętnie) z przodu.

    Jeśli wysyłam: #010abcde#010
    Wtedy odbieram: puste słowo+abcde+puste słowo

    Tak jest jeszcze ok. A teraz jest najlepsze:

    wysyłam: #010#010abcde#010
    odbieram: puste słowo+puste słowo+ab (<--- gdzie uciekła reszta znaków?!)

    wysyłam: #010#010#010abcde#010
    odbieram: puste słowo+puste słowo+puste słowo+ae

    wysyłam: #010#010#010#010abcde#010
    odbieram: puste słowo+puste słowo+puste słowo+puste słowo+d

    wysyłam: #010#010#010#010#010abcde#010
    odbieram: puste słowo+puste słowo+puste słowo+puste słowo+c

    Im więcej znaków #010 z przodu tym zachowanie programu dziwniejsze. Czy jest na to jakieś wyjaśnienie?

    Uart napewno jest dobrze ustawiony. To samo dzieje się niezależnie od prędkości transmisji. efuse=0xFF (czyli kompatybilność z m103 wyłączona). wg. mnie po stronie 'fizycznej' jest wszystko ok. coś jest w programie ale jest on tak prosty że nie moge doszukać się sam błędu.
    pomocy! :)

    Dodano po 38 [minuty]:

    odkryłem coś bardzo dziwnego. jak dodam linijke sprintf(buf,"%s",slowo0); to znaki są wysyłane normalnie (nic nie ginie) a puste słowa nie są tworzone.
    
     else 
        { 
             slowo0[iii]=0;   iii=0; 
    
          
                 sprintf(buf,"%s",slowo0);                  // <--- magic?
    	 USART0_Transmit_Word(buf);
         }
    


    Kompletnie nic już nie rozumiem..

    Dodano po 12 [minuty]:

    A jeszcze bardziej magiczne jest to że jak dam zamiast:

    USART0_Transmit_Word(buf);

    coś takiego:

    USART0_Transmit_Word(slowo0);

    to efekt jest taki sam. tak jakby sprintf modyfikował wejście a nie tylko wyjście..
  • REKLAMA
  • #2 7701576
    piti___
    Poziom 23  
    Czy tablica i zmienne sa volatile ?
  • #3 7701615
    szakal9999
    Poziom 11  
    A gdzie masz kończenie stringu (/0)?? Skąd funkcja ma wiedzieć, że tekst się skończył??
    Co prawda to i tak nie tłumaczy wszystkich twoich problemów, ale na pewno część.
  • REKLAMA
  • Pomocny post
    #4 7702013
    OlekM
    Poziom 17  
    Podejrzewam, że twoja funkcja USART0_Transmit_Word może zbyt długo czekać i bufor odbiorczy UARTu się przepełnia.

    Załóżmy, że powyższa funkcja wysyła znaki '\r' '\n' po każdym jej wywołaniu.

    Wówczas jeśli program otrzymuje tekst i po owym tekście #010, to cały komunikat trafia do wysłania i jest w porządku.

    Jeśli tekst zacznie się od #010, natychmiast wywoływana jest funkcja USART0_Transmit_Word wysyłająca (wedle mojego założenia) dwa bajty. W tym czasie do UART'u mogą przyjść kolejne dwa bajty z komputera - program może się jeszcze wyrobić bo bufory w MEGAch są dwubajtowe.

    Jeśli jednak po pierwszym znaku #010 (program czeka na wysłanie 2 bajtów), przyjdzie kolejny #010, wówczas po powrocie z pierwszego wywołania USART0_Transmit_Word, pobieramy kolejny znak #010 (w buforze UARTu pozostaje w tym momencie jeden nieodebrany znak) i ponownie program się blokuje na czas transmisji dwóch bajtów - jednak w buforze jest już miejsce tylko na jeden bajt.
    Każdy kolejny zostanie stracony.
  • #5 7702546
    AVRowiec
    Poziom 18  
    szakal --> tu masz zakończenie stringu: slowo0[iii]=0;

    piti --> wszystko jest volatile
    
    volatile unsigned char odebranyZnak0;
    volatile unsigned char slowo0[120];
    volatile unsigned char iii=0;
    


    Olek --> też mam wrażenie że to coś przy wysyłaniu. Ale ta cholera uciny tylko niektóre pierwsze znaki jeśli wcześniej jest #010. np testowałem na łańcuchu #010#010...#010123456789123456789#010 i ucieło tylko pierwsze cyfry 234 a potem 678 a reszta już normalnie poleciała.

    próbowałem dać przed else coś takiego:
    
    else if (iii>1) 
    

    ale niewiele to dało.

    nadal nie rozumiem dlaczego znaki nie giną jeśli wszystko przejdzie przez sprintf(). ale i to w niektórych przypadkach dziwnie sie zachowuje.

    Dodano po 10 [minuty]:

    ------------------
    Całe przerwanie odpowiedzialne jest za dogadanie się z telefonem. Bezczelnie na terminalu widze jak telefon wysyła znaki i na innym jak je odbiera, przyczym te odebrane są postrzępione (np zamiast OK przychodzi samo 0). Ale wystarczy odpalić te samą procedure po pewnym czasie (procedure która wysyła polecenie i czeka na ok) i działa. nie wiem od czego to zależy bo czyszcze wszystkie bufory, przepełnień nie ma. Nie wiem co jest grane. Może ma ktoś inny pomysł na dogadanie się z telefonem?
  • REKLAMA
  • #6 7702702
    loocasm
    Poziom 15  
    W takim razie może warto by się przyjrzeć temu jak wygląda USART0_Transmit_Word(...) ?
  • #7 7702892
    AVRowiec
    Poziom 18  
    tak wygląda: :)

    USART0_Transmit() - prosto z datasheeta

    /////////////////////////////////////////////////////
    void USART0_Transmit( unsigned char data )
    {
    /* Wait for empty transmit buffer */
    while ( !( UCSR0A & (1<<UDRE0)) )
    ;
    /* Put data into buffer, sends the data */
    UDR0 = data;
    }
    /////////////////////////////////////////////////////
    void USART0_Transmit_Word(unsigned char *data)
    {
         while (*data)
         USART0_Transmit(*data++);
    }


    Jeszcze jedna rzecz: znaki odbieram w przerwaniu UART0 a odpowiedzi/wyniki wysyłam na drugi UART - UART1. Czy w takim wypadku kolizja danych jest możliwa?

    Dodano po 2 [minuty]:

    dodam jeszcze że problem raczej nie tkwi w wysyłaniu. bo jeśli sprawdzam przysłaną treść ( strcmp() ) to funkcja nie zwraca tego co powinna. tak jakby nie dochodziła całość.
  • #8 7703187
    piti___
    Poziom 23  
    Ja na starcie sprawdziłbym flagi przerwań od nadawania, zamienił w przerwaniu USART0_Transmit_Word(); na flage i wysłał stringa w odpowiednim miejscu programu. Do tego na czas nadawania wyłączałbym przerwania RX.

    Pozdrawiam
  • REKLAMA
  • #9 7703291
    AVRowiec
    Poziom 18  
    po else dałem if (iii>0) i wszystko działa ale podpięte do PC. z telefonem nie chce pracować. i tylko z telefonem. procedury są więc ok.

    Dodano po 12 [minuty]:

    sprawdziłem wszystko już trzeci raz. układ nie może dogadać się z telefonem mimo że do urządzenia trafiają poprawne dane (obserwuje to co wysyła telefon przez port com). układ nie jest w stanie zinterpretować danych - jakby nic nie odbierał. jaki powinien być stan linii uart w czasie normalnej pracy? (zasilanie 3,7V)
  • #10 7704533
    Kamil557
    Poziom 11  
    Kiedyś robiłem także komunikację z Atmegi z telefonem(dokładnie Siemens ME45). 2 dni siedziałem nad programem do UART'ów, bo uC wysyłał komendy do telefonu, ale nie potrafił odebrać odpowiedzi.
    Zasilanie procka 3,3V czyli wszystko powinno śmigać na tym poziomie napięć, podpięte bezpośrednio do telefonu.

    Pomogło podniesienie napięcia. W tym układzie nie mogłem zmienić napięcia zasilania, ale do celów testowych podłączyłem to przez 2xMAX232(5V).

    [uC]<->MAX <-> MAX <-> ME45

    Od tej pory wszystko działało. Może u Ciebie jest coś podobnego.
    Pozdrawiam
  • #11 7704938
    AVRowiec
    Poziom 18  
    być może.. kto wie.
    jedno jest pewne. przerwanie nie radzi sobie z komunikatem typu:

    abc#013#013#010de#013#010 <-- typowa komenda odebrana z telefonu

    jak usunie się #013#010 (te pierwsze) to wszystko śmiga.

    mam wrażenie że wysyłanie odpowiedzi lub analiza treści trwa zbyt długo i dlatego flagi nie są ustawiane. z drugiej jednak strony jak usune ten malutki fragment to wszystko chodzi.
    napięcia podkręcać nie będe ale zastanawiam się nad dodaniem jakiś bramek.

    Dodano po 1 [minuty]:

    Kamil557 -> prośba: możesz wkleić kod swojego przerwania i obsługi uartu. może mój sposób odbierania komunikatów jest poprostu denny ;/

    Moderowany przez zumek:

    Już raz zwróciłem uwagę.
    https://www.elektroda.pl/rtvforum/topic1574803.html#7681519
    Regulamin p.6, 15 -> ostrzeżenie #1

  • #12 7705089
    Kamil557
    Poziom 11  
    Niestety odbierałem odpowiedzi w zwykłym:

    unsigned char USART0_Receive( void )
    {
    	while (!(UCSR0A&(1<<RXC0)));
    	return UDR0;
    }


    bo wiedziałem ile będzie znaków, i nie musiałem bawić się z przerwaniami. Poza tym jeszcze nic nie robiłem z przerwaniami UART'a - nigdy nie było mi to potrzebne.

    A jakbyś w przerwaniu zobaczył co dzieje się z flagą DataOverRun? Może jednak tracisz znaki?
  • #13 7705729
    AVRowiec
    Poziom 18  
    Przy ustawianiu flag (głównie OK i ERROR) program miał dodatkowo wypisywać na konsoli informacje. Podejrzewam że to przez to - przerwanie się nie wyrabiało. Pozatym
     else (iii>0)
    też pomogło bo jednoznakowe komunikaty nie są analizowane. w tej chwili układ załączania telefonu działa prawidłowo. Sam się inicjuje po włączeniu zasilania. Linie uartu są połączone bezpośrednio (ten temat męczyłem w innym poście bo myślałem że może tam jest problem).
    Ogólnie rzecz biorąc jeśli chce się coś zrobić bez liczenia czy UART się wyrobi (baudrate 19200 przy 8MHz) należy założyć że NIE :) i pousuwać wszystkie zbędne upiększające operacje.
    Wszystkim dziękuje za pomoc choć temat może nie jest zamknięty. Założe się że lada dzień coś mnie zaskoczy.
    Będe wdzięczny jeśli ktoś wrzuci swój sposób parsowania komunikatów bo mój gubi znaki z niewiadomych przyczyn - to że zaczeło działać nie oznacza że błąd przestał istnieć ;/
REKLAMA