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

[ATmega328p] [C] RS232 - USART brak transmisji - konfiguracja i kod UART

MaX.J 26 Maj 2016 15:48 1809 20
REKLAMA
  • #1 15700448
    MaX.J
    Poziom 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:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    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 - konfiguracja i kod UART

    Pozdrawiam.

    [EDIT] Na schemacie się machnąłem, kwarc jest podpięty bezpośrednio do nóżek, kondensatory idą do masy.
  • REKLAMA
  • #2 15700474
    Konto nie istnieje
    Konto nie istnieje  
  • #3 15700486
    MaX.J
    Poziom 12  
    Witam,

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


    Na innym temacie już się o niej rozpisywali, także odnośnie sterowników przy błędzie "USART receive framing error".
  • REKLAMA
  • Pomocny post
    #4 15700548
    maciej_333
    Poziom 38  
    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:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Wysyłanie bajtu:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Odbieranie bajtu:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Proponuję testować to osobno w funkcji main(). Przykładowo najpierw samo wysyłanie przez mikrokontroler:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    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 ?
  • #5 15700574
    Konto nie istnieje
    Konto nie istnieje  
  • #6 15700581
    MaX.J
    Poziom 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 15700584
    maciej_333
    Poziom 38  
    majeranek53 napisał:
    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 15700585
    slx
    Poziom 19  
    Cytat:
    /* Set frame format: 8data, 1stop bit */
    UCSR0C = (1<<USBS0)|(1<<UCSZ00);

    Przy takim ustawieniu to masz ramkę 6 bitow + 2 bity stopu.
  • #9 15700609
    MaX.J
    Poziom 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 15700627
    maciej_333
    Poziom 38  
    MaX.J napisał:
    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.
  • REKLAMA
  • #11 15700638
    MaX.J
    Poziom 12  
    Cytat:
    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 15700665
    maciej_333
    Poziom 38  
    MaX.J napisał:
    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 - konfiguracja i kod UART
  • #13 15700705
    Konto nie istnieje
    Konto nie istnieje  
  • #14 15700728
    maciej_333
    Poziom 38  
    Piotrus_999 napisał:
    maciej_333 napisał:
    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 15700767
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #17 15700879
    Konto nie istnieje
    Konto nie istnieje  
  • #18 15701165
    jnk0le
    Poziom 18  
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Coś takiego da ci 6 bitów danych i 2 bity stopu.
  • #19 15705413
    MaX.J
    Poziom 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
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    ATmega8
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #20 15706552
    maciej_333
    Poziom 38  
    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 napisał:
    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 15706633
    MaX.J
    Poziom 12  
    Witam,

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

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Całość zamieniłem na to:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    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.
REKLAMA