Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[ATmega328p] [C] RS232 - USART brak transmisji

MaX.J 26 May 2016 15:48 1470 20
IGE-XAO
  • #1
    MaX.J
    Level 12  
    Witam,

    Z powyższym problemem męczę się już bardzo długo. Naczytałem się o bicie URSEL(w 328p go nie ma),sprawdzałem przejściówkę USB->RS232 działała "na krótko" i przy połączeniu do modułu bluetooth HC05.
    Wyeliminowałem błąd "UART receiving framing error" z terminala RealTerm poprzez ustawienie buforu FIFO i zmianę buforu zapisu i odczytu.
    Słyszałem o błędach spowodowanych korzystaniem z płytek stykowych i wewnętrznym oscylatorem, więc polutowałem wszystko tak, żeby nie było niepewnych połączeń.
    Naczytałem się poradników, które się sprowadzały do stworzenia takiego kodu:
    Code: c
    Log in, to see the code


    W teorii wszystko fajne, tylko że nie działa. I już nie mam pojęcia gdzie szukać.

    Oczywiście książki p.Kardasia i p.Francuza przeczytałem, powyższy kod pochodzi z książki p.Francuza, kod p.Kardasia działał tak samo.

    Dodam jeszcze, że na przejściówce diody do wysyłania migają, RealTerm także pokazuje, że wysyła. Odbioru nie widać. Próbowałem wyświetlać odbierane dane na LCD, jednak nic się nie działo.

    Środowisko to Eclipse, programator USBasp.
    [ATmega328p] [C] RS232 - USART brak transmisji

    Pozdrawiam.

    [EDIT] Na schemacie się machnąłem, kwarc jest podpięty bezpośrednio do nóżek, kondensatory idą do masy.
  • IGE-XAO
  • #2
    User removed account
    User removed account  
  • #3
    MaX.J
    Level 12  
    Witam,

    Przejściówka od chińczyków za 5zł.
    [ATmega328p] [C] RS232 - USART brak transmisji


    Na innym temacie już się o niej rozpisywali, także odnośnie sterowników przy błędzie "USART receive framing error".
  • Helpful post
    #4
    maciej_333
    Level 36  
    Nie wiem dlaczego czytasz informacje "z drugiej" ręki, zamiast skupić się na dokumentacji ? Mam tu na myśli książki i jakieś poradniki. Wszystko jest tam idealnie opisane.

    Nie sprawdzałem tego kodu. Jeżeli nie chcesz przerwań i wystarczy Ci tzw. "polling", to jeszcze prościej. Zakładam zegar na 16 MHz.

    Inicjalizacja USART0 dla 9600 b/s, 8N1, jako interfejs asynchroniczny:
    Code: c
    Log in, to see the code


    Wysyłanie bajtu:
    Code: c
    Log in, to see the code


    Odbieranie bajtu:
    Code: c
    Log in, to see the code


    Proponuję testować to osobno w funkcji main(). Przykładowo najpierw samo wysyłanie przez mikrokontroler:
    Code: c
    Log in, to see the code


    Dosyć standardowo spytam, czy FUSEBIT'y są faktycznie ustawione na zewnętrzny kwarc ? Sam mikrokontroler "działa" ? Tzn. czy miga np. diodą ? Sprawdzałeś, czy jest coś wysyłane oscyloskopem ?
  • IGE-XAO
  • #5
    User removed account
    User removed account  
  • #6
    MaX.J
    Level 12  
    Dziękuję za odpowiedzi.

    Spróbowałem podłączenia układu i przejściówki na ATmega8, procedury skopiowane z datasheeta. Cały układ działa, wysyła i odbiera.

    Wracając do ATmega328p zaraz sprawdzę porady maciej_333, od razu mówię, że fusebity dobrze są ustawione.
  • #7
    maciej_333
    Level 36  
    majeranek53 wrote:
    Daję 80%, że potrzebny MAX lub odwrócenie logiki sygnałów. Datasheet scalaka nie precyzuje jasno, a raczej pisze o RS232 a nie o poziomach TTL, potrzebnych na bezpośrednie podłączenie do procesora.

    To jest raczej dość oczywiste. Można to dopasować na MX232, albo tranzystorach. PL2303 dostarczy sygnałów bipolarnych, ale nie ma gwarancji, że ten konwerter nie dostarcza od razu TTL. Proponuję zmierzyć napięcie na TXD bez wysyłania.
  • #8
    slx
    Level 19  
    Quote:
    /* Set frame format: 8data, 1stop bit */
    UCSR0C = (1<<USBS0)|(1<<UCSZ00);

    Przy takim ustawieniu to masz ramkę 6 bitow + 2 bity stopu.
  • #9
    MaX.J
    Level 12  
    Porada maciej_333 zadziałała, odbiera i wysyła. Skoro już to mam, zajmę się przerwaniami. Temat do zamknięcia i dziękuję za szybką odpowiedź :)
  • #10
    maciej_333
    Level 36  
    MaX.J wrote:
    Porada maciej_333 zadziałała, odbiera i wysyła. Skoro już to mam, zajmę się przerwaniami. Temat do zamknięcia i dziękuję za szybką odpowiedź :)

    Wychodzi na to, że lepiej czytać dokumentację. Właśnie na jej podstawie to napisałem. Wysyłanie i odbiór z kolei skopiowałem z pewnego mojego programu dla ATTINY2313. Wystarczyło zmienić nazwy rejestrów.

    Dlaczego Twój poprzedni kod nie działał ? Być może kolega slx znalazł błąd. Faktycznie przy takim ustawieniu jest tak, jak ów kolega napisał. W takiej sytuacji terminal (np. RealTerm) zwracałby błąd ramki, jeżeli miałby konfigurację 8N1.
  • #11
    MaX.J
    Level 12  
    Quote:
    Wychodzi na to, że lepiej czytać dokumentację. Właśnie na jej podstawie to napisałem. Wysyłanie i odbiór z kolei skopiowałem z pewnego mojego programu dla ATTINY2313. Wystarczyło zmienić nazwy rejestrów.


    Z dokumentacji skopiowany kod także nie zadziałał.


    Odnośnie wysyłania i odbierania coś jest jednak nie tak.
    Wysyłam 1 odbieram 1
    Wysyłam q odbieram q
    Wysyłam a odbieram q
  • #12
    maciej_333
    Level 36  
    MaX.J wrote:
    Odnośnie wysyłania i odbierania coś jest jednak nie tak.
    Wysyłam 1 odbieram 1
    Wysyłam q odbieram q
    Wysyłam a odbieram q

    Typowy problem z zegarem. Sprawdziłbym jeszcze raz ustawienie FUSEBIT'ów, tym razem z dokumentacją. Przepływność bitowa Atmegi nie jest dokładnie taka, jak powinna, albo RealTerm jest źle skonfigurowany. Najlepiej byłoby wysyłać np. bajt 0x00 i zmierzyć oscyloskopem czas trwania szczeliny bitowej na linii TXD Atmegi.

    Dodaję screen z RealTerm dotyczący poprawnej konfiguracji dla tego przypadku.
    [ATmega328p] [C] RS232 - USART brak transmisji
  • #13
    User removed account
    User removed account  
  • #14
    maciej_333
    Level 36  
    Piotrus_999 wrote:
    maciej_333 wrote:
    To jest raczej dość oczywiste. Można to dopasować na MX232, albo tranzystorach. PL2303 dostarczy sygnałów bipolarnych


    To jest przejściówka do USB ani RS232 to grzyba mu MAX232

    Szkoda, że Twojej wypowiedzi nie da się zrozumieć. Wiele konwerterów dostarcza sygnały bipolarne. W końcu muszą one "udawać" RS232. Chyba o to Ci chodziło.
  • #15
    User removed account
    User removed account  
  • #17
    User removed account
    User removed account  
  • #18
    jnk0le
    Level 18  
    Code: c
    Log in, to see the code

    Coś takiego da ci 6 bitów danych i 2 bity stopu.
  • #19
    MaX.J
    Level 12  
    Witam,

    Dziękuję za poprzednie odpowiedzi.


    Problem jest trochę inny, jednak pasuje do tematu. Na ATmega328p przy wysyłaniu znaków i odbieraniu przez terminal pokazują się inne znaki niż wysyłam, na LCD całkiem krzaki. Przy zmianie kodu znaku na liczbę wypisywane są zawsze 2 liczby np.
    Dla q wypisywane jest 6 i 254.

    Problem jest przy odbiorze znaku i wypisaniu w przerwaniu jak i odbiorze i wypisaniu w pętli głównej programu.

    Przy tej samej płytce i zamianie na ATmega8 bez jakiejkolwiek zmiany konfiguracji(schemat na początku tematu, tylko zmieniam procesor w gnieździe DIP28) program dziala jak najbardziej w porządku. Wypisuje to co wysyłam, w terminalu jak i na LCD.

    Kod dla ATmega328p
    Code: c
    Log in, to see the code


    ATmega8
    Code: c
    Log in, to see the code
  • #20
    maciej_333
    Level 36  
    Szkoda, że nie czytasz dokumentacji i nie korzystasz z moich porad. Program powinien być rozwijany w oparciu o kod, który wcześniej podałem. Nie zaś na przykładach z Google. Problem na 70 % związany jest i tak z zegarem.

    Oczywiście tu jest dość bezmyślny błąd:
    UCSR0B = (1<<RXEN0)|(1<<TXEN0) | (1<<RXC0);

    Powinno być tylko tyle:
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);

    Takim kodem włączyłbyś przerwanie, więc jeżeli w SREG przerwania są włączone masz nieuchwycone przerwanie. Tzn. takie dla którego nie ma ISR. Błędy takie są zwykle trudne do wykrycia w większym programie. Jeżeli jednak przerwania mają być, to powinno się zrobić to normalnie:
    UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);

    Pewny jesteś, że wartości wpisywane w ten sposób są poprawne ?
    UBRR0H=UBRRH_VALUE;
    UBRR0L=UBRRL_VALUE;

    Zresztą po co wpisywać coś do UBRR0H ? Ten rejestr i tak będzie zerowy. Nie prościej i bezpieczniej wpisać:
    UBRR0L = 207;

    Zgodnie z dokumentacją nie musisz ręcznie kasować flag RXC0 i UDRE0. TXC0 musiałby być kasowane, jeżeli nie korzystasz z przerwań.

    Tu widzę, że przerwania są stosowane, ale oczywiście LCD jest obsługiwany w przerwaniu. Jest to dość "genialne". Niestety tak się nie powinno robić. Wyświetlanie znaku na LCD trochę trwa. Nie pamiętam ile ale są to czasy porównywalne z długością trwania ramki UART, lub nawet większe. Powinieneś w przerwaniu zapisywać do jakiejś globalnie zdeklarowanej tablicy cały łańcuch. dopiero potem po jego odebraniu należy przesłać ten łańcuch bajt po bajcie do LCD, ale w pętli głównej. Odebranie odpowiedniej liczby bajtów powinno być związane z jakąś flagą, ustawianą w przerwaniu. Koniec łańcucha może być wykrywany standardowo za pomocą bajtu 0x00.

    Coś takiego co masz może będzie działać przy wysyłaniu wolno pojedynczych bajtów. Przesłanie kilku jeden po drugim nie zostanie prawidłowo obsłużone.

    MaX.J wrote:
    Przy zmianie kodu znaku na liczbę wypisywane są zawsze 2 liczby np.
    Dla q wypisywane jest 6 i 254.

    Cóż to znaczy ???
    Jeżeli z jakiegoś powodu musisz wyświetlić kod znaku, to trzeba wytworzyć najpierw z niego łańcuch za pomocą sprintf() i wysłać kilka bajtów do LCD. Zależy to od rodzaju formatowania HEX/DEC. Jednak sprintf() to ogromna funkcja.

    Czy wypisywanie stałych na LCD w ogóle działa ?
  • #21
    MaX.J
    Level 12  
    Witam,

    Problemy rozwiązałem wczoraj w nocy, zapomniałem napisać ;)
    Już wszystko działa, problem chyba był w tym:

    Code: c
    Log in, to see the code


    Całość zamieniłem na to:

    Code: c
    Log in, to see the code


    Reszta bez zmian. Na LCD wyświetla wszystko tak jak wysyłam. Na ATmega328p jak i na ATmega8.


    Z flagą w przerwaniu zamierzałem ją zastosować, jednak najpierw chciałem uruchomić przerwania w ogóle.

    Obecnie wszystko śmiga, temat do zamknięcia.