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 ATmega8A C - Initializacja UART, perzesył danych przez Bluetooth, LED

Mag-Łoch 23 Lis 2015 11:23 1359 20
  • #1 23 Lis 2015 11:23
    Mag-Łoch
    Poziom 6  

    Witam, pisałem już tu z takim problemem. Mianowicie próbuję skonfigurować UART tak aby móc przez bluetooth odebrać konkretne dane, które maja potem sterować diodą, na początku, ale później mają służyć do czegoś więcej, bo chciałbym zrobić zamek do drzwi kontrolowany przez aplikację mobilną.
    Korzystam z ATmega8A, a jako moduł bluetooth wykorzystuje XM-15B. Poniżej przedstawię kod, próbuję go na różne sposoby zmieniać i kombinuje i nic nie idzie.

    Nie wiem czy mam dobrze ustawiony UART, czy FOSC jest dobra, bo raczej UBRR jest dobrze przeliczony. Zakomentowałem w pewnym momencie switch w głównej funkcji i wrzuciłem fragment migający diodą, dioda zaczęła migać. Natomiast kiedy switch był i gdy dodałem default, w którym umieściłem właśnie miganie diody, czyli gdyby przychodziły obojętnie jakie śmieci to powinna migać, ale nie migała, tak jakby program nie wchodził w ogóle do switcha, podobnie z if było. Próbuję kilkakrotnie na różne sposoby, zmieniam też argumenty w switch, zamiast '1' czy '2' wpisuje 0x01 i 0x02 i też nie działa. Pomóżcie, bo nie wiem gdzie mam błąd.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0 20
  • #2 23 Lis 2015 11:45
    tmf
    Moderator Mikrokontrolery Projektowanie

    A jak to ma wg ciebie działać? Jednocześnie odblokowujesz przerwania odbioru USART i czytasz UDR w wątku głównym. To nie ma prawa działać, musisz się zdecydować - albo przerwania albo pooling. Druga sprawa - już we poprzendim wątki pisałem ci, że rejestr UDR odczytujesz raz dla każdego odbieranego bajtu. a w twoim ISR masz UDR odczytywane dwukrotnie.

    0
  • #3 23 Lis 2015 12:14
    Mag-Łoch
    Poziom 6  

    Wgrałem coś takiego i dalej nic

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #4 23 Lis 2015 12:25
    tmf
    Moderator Mikrokontrolery Projektowanie

    Ale ty zastanawiasz się nad tym co robisz, czy losowo przestawiasz kod w nadziei, że zadziała?
    Taki kwiatek:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Niby jak to ma działać, jeśli def. funkcji odbierz wygląda tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #5 23 Lis 2015 12:34
    Mag-Łoch
    Poziom 6  

    Napisano mi wcześniej, że nie mogę bezpośrednio użyć UDR w switch czy w if, żeby wrzucić z UDR do zmiennej tymczasowej i tą zmienną sprawdzać. Tak więc zrobiłem.

    0
  • #6 23 Lis 2015 13:05
    Andrzej__S
    Poziom 28  

    Mag-Łoch napisał:
    Napisano mi wcześniej, że nie mogę bezpośrednio użyć UDR w switch czy w if, żeby wrzucić z UDR do zmiennej tymczasowej i tą zmienną sprawdzać. Tak więc zrobiłem.


    Niestety zrobiłeś to źle.

    Napisano Ci również, że po odebraniu każdego bajtu rejestr UDR można odczytać tylko raz, a Ty wywołujesz funkcję odbierz(), która odczytuje i zwraca wartość rejestru UDR, po czym ponownie odczytujesz rejestr UDR przypisując jego wartość zmiennej ODB:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Powinieneś od razu przypisać wartość zwracaną przez funkcję odbierz() do zmiennej ODB:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    EDIT: No i nie ustawiaj bitu zezwolenia na przerwanie RXCIE w rejestrze UCSRB, jeśli usunąłeś procedurę obsługi przerwania USART_RXC_vect i zdecydowałeś się na odczyt poprzez polling.

    0
  • #7 23 Lis 2015 13:08
    2675900
    Użytkownik usunął konto  
  • #8 23 Lis 2015 14:22
    Mag-Łoch
    Poziom 6  

    Wgrałem taki kod, poprzednio też stosowałem się do Waszych zaleceń. Przestawiałem kod, zgadza się, próbując dość do tego co jest nie tak. Jeśli coś jest nie tak z funkcją odbierz to proszę napiszcie mi co, bo ja ja wziąłem bezpośrednio z datasheeta.


    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #9 23 Lis 2015 14:43
    2675900
    Użytkownik usunął konto  
  • #10 23 Lis 2015 18:07
    Andrzej__S
    Poziom 28  

    Mag-Łoch napisał:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Tutaj masz kolejny błąd. Rejestry UBRRH i UCSRC współdzielą ten sam adres. Aby wpisać coś do rejestru UCSRC musisz więc ustawić bit URSEL, bo w innym przypadku nadpisujesz wartość UBRRH i prawdopodobnie masz źle skonfigurowaną prędkość transmisji.

    Powinno być:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #11 23 Lis 2015 18:50
    Mag-Łoch
    Poziom 6  

    Zmieniłem, ale dalej coś nie śmiga, w głównej funkcji mam coś nie tak, ale nie mam pojęcia co

    0
  • #12 23 Lis 2015 22:16
    jnk0le
    Poziom 18  

    Czy jesteś pewien że atmega działa rzeczywiście na 4MHz ? (_delay_ms(1000); to dokładnie jedna sekunda?)

    Możesz zobaczyć też na gotowcu czy sprzętowo wszystko jest poprawnie.

    0
  • #13 23 Lis 2015 22:20
    Mag-Łoch
    Poziom 6  

    atmega działa na max 16MHz, ale dałem 4 bo przeczytałem gdzieś żeby dla bezpieczeństwa dać 1/4
    tak delay_ms(1000) to jedna sekunda

    0
  • #14 24 Lis 2015 11:31
    Mag-Łoch
    Poziom 6  

    Sprawdzałem inicjalizację UARTA i okazało się, że definicja UBRR nie może zawierać nawiasów, zmieniłem i teraz układ odbiera jakieś dane. Switch działa, bo dałem default i w nim zamiganie diodą na znak czy wszystko śmiga, a jak wysyłam mu '1' to wchodzi w default zamiast w case '1', więc nie chce mi tylko chyba wejść do innych case. Sprzętowo wszystko działa, bo sprawdzałem na innym układzie, podłączone tez jest dobrze.


    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #15 24 Lis 2015 19:07
    Andrzej__S
    Poziom 28  

    Nie napisałeś, w jaki sposób wysyłasz dane do modułu? Z komórki, laptopa, PC? Z jakiego programu/terminala korzystasz?

    Czasami programy typu terminal automatycznie dołączają np. znak końca linii na końcu transmisji. W takim przypadku zanim zdążysz zaobserwować odebranie '1' nadejdzie następny znak (CR, LF lub obydwa) i switch ponownie wejdzie do sekcji default. Aby tego uniknąć należałoby wyłączyć opcję dołączania jakichkolwiek znaków do transmisji przez terminal.

    EDIT:
    Muszę jeszcze coś zdementować.

    Mag-Łoch napisał:
    Sprawdzałem inicjalizację UARTA i okazało się, że definicja UBRR nie może zawierać nawiasów...

    To nie sprawa nawiasów a promocji typów i kolejności operacji. Po prostu wartość w nawiasie (16*BAUD) jest obliczana jako pierwsza, a wynik wykracza poza zakres liczby całkowitej 16-bitowej. Powinno pomóc zadeklarowanie stałych jako unsigned long:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Jak masz ochotę to sprawdź :)

    0
  • #16 24 Lis 2015 20:21
    BlueDraco
    Specjalista - Mikrokontrolery

    Nie jest prawdą, że:
    - definicja UBRR nie może zawierać nawiasów
    - BAUD musi być zdefiniowany jako UL

    Definicja UBRR MUSI zawierać nawiasy.
    Wzór na UBRR jest błędny, o czym była mowa tutaj wielokrotnie. Prawidłowy sposób policzenia UBRR jest już zdefinowany w plikach nagłówkowych Atmela.

    #define MYUBRR ((FOSC/16 + BAUD/2) / BAUD - 1)

    0
  • #17 24 Lis 2015 21:08
    2675900
    Użytkownik usunął konto  
  • #18 24 Lis 2015 22:34
    Mag-Łoch
    Poziom 6  

    Szczerze mówiąc spróbowałem to zamienić te nawiasy i po prostu wystartowało, coś odebrał uC, a wysyła dane z programu Bluetooth Terminal na telefonie.

    0
  • #19 25 Lis 2015 07:03
    Andrzej__S
    Poziom 28  

    Nie korzystałem wprawdzie z tego programu, ale sądząc z opisu w Setup jest opcja "Append newline(\r\n)". Aby uzyskać efekt, którego oczekujesz, powinieneś mieć tę opcję wyłączoną (zdaje się, że domyślnie jest włączona).

    Alternatywnie można po prostu usunąć całkowicie sekcję default (lub kod, który zawiera) i wtedy powinieneś zauważyć efekty wejścia programu do case '1' i case '2' (oczywiście jeśli transmisja przebiega prawidłowo).

    EDIT:

    Piotrus_999 napisał:


    i stąd ten mały bład w liczeniu. Teoretycznie nie powinno mieć to wpływu na transmisję.

    W tym konkretnym przypadku (FOSC=16000000, BAUD=9600) sposób liczenia nie ma znaczenia, bo wynik jest taki sam. Niemniej kolega BlueDraco ma jak najbardziej rację. Ta 1/2 (która notabene została dodana tylko w celu prawidłowego zaokrąglenia wyniku) często ma kluczowe znaczenie, szczególnie przy niskich wartościach UBRR. Problem w tym, że sam Atmel w swoich notach katalogowych podaje wzory na obliczenie UBRR=fosc/(16BAUD)-1 i przykłady kodu, w których definiuje:
    #define MYUBRR FOSC/16/BAUD-1
    co nie zawsze się jednak sprawdza, bo ta metoda liczenia powoduje zawsze zaokrąglenie w dół (podczas dzielenia liczb całkowitych), a w niektórych przypadkach wynik trzeba zaokrąglić w górę, aby uzyskać akceptowalny błąd.

    0
  • #20 25 Lis 2015 09:03
    Mag-Łoch
    Poziom 6  

    Domyślnie ta opcja była wyłączona, kurde i wciąż nie śmiga, zakomentowałem defaulta i nie wchodzi w case '1' i '2'

    0
  • #21 25 Lis 2015 10:02
    Andrzej__S
    Poziom 28  

    A nie masz czasami zaznaczonej opcji "Send hexadecimal"?

    Czy jesteś pewien, że moduł wysyła dane z prędkością 9600bps?

    Spróbuj na sztywno wpisać wartość MYUBRR. Dla 16MHz, 9600bps i bitu U2X=0 wartość UBRR powinna wynosić 103 (dziesiętnie).

    Spróbuj może odebrać echo na próbę:
    1. Zaznacz opcję "Append newline(\r\n)".
    2. Odłącz piny Rx i Tx modułu od mikrokontrolera.
    3. Połącz ze sobą piny Rx i Tx modułu.
    4. Wyślij '1' lub '2' i zobacz, czy i co moduł odeśle z powrotem.

    Ewentualnie wypróbuj inny terminal.

    0