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.

[BASCOM] - UART- dwu kierunkowy przesył zmiennych.

werewolf15 05 Sie 2013 06:35 4491 38
  • #1 05 Sie 2013 06:35
    werewolf15
    Poziom 14  

    Zrobiłem płytkę do sterownika domowego na której znajdują się dwa procki: atmega128(procesor główny) i atmega32(procesor muzyczny). Konieczna jest w tym przypadku komunikacja tych procesorów w obu kierunkach przez uart.
    Całą noc zajęło mi napisanie programu do takiej właśnie komunikacji i w rezultacie mam coś takiego:

    At128-

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    At32-
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    W założeniach miało to działać tak że at128 wysyła zmienną o wartości 1 do at32, która po odebraniu tego sygnału wysyła sygnał powrotny w postaci zmiennej o wartości 222. At128 po odebraniu zmiennej zwrotnej wyświetla ją na lcd. Taki prosty test komunikacji w obie strony.

    Program działa ale nie do końca dobrze ponieważ na lcd zamiast pojawić się wartości odebranej (222) pojawia sie w 1 sek odcinkach czasu najpierw 1(wartość zmiennej którą wysyłam na początku) potem pojawia się 22 i na końcu dopiero 222 która się już nie zmienia. Próbowałem do programu wstawić coś takiego jak "clear serialin" oraz próbowałem z programowym uartem ale efekt jeszcze gorszy.

    Proszę o pomoc w udoskonaleniu programu aby od razu odczytywał dokładne wartości zmiennych.

    0 29
  • #2 05 Sie 2013 07:45
    atom1477
    Poziom 43  

    werewolf15 napisał:

    Program działa ale nie do końca dobrze ponieważ na lcd zamiast pojawić się wartości odebranej (222) pojawia sie w 1 sek odcinkach czasu najpierw 1(wartość zmiennej którą wysyłam na początku) potem pojawia się 22 i na końcu dopiero 222 która się już nie zmienia.

    No to wszystko jest zgodne z programem.
    Masz tam przecież właśnie wyświetlanie zmiennej Outbin a dopiero potem Inbin.

    0
  • #3 05 Sie 2013 11:17
    werewolf15
    Poziom 14  

    Może to źle wytłumaczyłem ale chodzi mi o to żeby odczyt na wyświetlaczu pokazał tylko inbin odebrane z at32(wartość 222). Polecenie "print outbin" miało tylko wysłać tą zmienną do drugiego procka a nie odczytywać na wyświetlaczu.


    Teraz dopisałem taki fragment że program pomija wyświetlanie tych dwóch pierwszych błędnych wartości i wyświetla dopiero właściwą wartość po 3-krotnym powtórzeniu pętli. Ale to chyba nie jest poprawny zapis. Czy ktoś pomoże udoskonalić?

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    0
  • #4 05 Sie 2013 11:54
    atom1477
    Poziom 43  

    Faktycznie coś mi się pomieszało.
    W takim razie program się chyba po prostu nie wyrabia (ten z LCDkiem).
    I nic dziwnego.
    Bo na 1 wysłany bajt drugi procesor odsyła mu w kółko nieskończony ciąg "222" i to nawet bez żadnych przerw.

    0
  • #5 05 Sie 2013 12:03
    werewolf15
    Poziom 14  

    A jak zrobić żeby oba procesory wiedziały że ten drugi odebrał zmienną? Wtedy nie musiał by wysyłać w nieskończoność?

    0
  • #6 05 Sie 2013 12:06
    atom1477
    Poziom 43  

    No nie wiem. Potwierdzić jeden raz?

    0
  • #7 05 Sie 2013 12:14
    werewolf15
    Poziom 14  

    A co zrobić żeby nie wczytywał mi zmiennej którą właśnie wysłał?

    0
  • #8 05 Sie 2013 12:26
    atom1477
    Poziom 43  

    Tego nie wiem. Bo zgodnie z programem nie powinien tego robić.
    Może to jakies zwarcie pomiędzy pinami TXD i RXD.
    A wyświetla ją również jak ten drugi procesor nie jest podpięty?

    0
  • #9 05 Sie 2013 12:45
    werewolf15
    Poziom 14  

    Zwarcia niema bo uart świetnie działa w jedną stronę. Niestety nie mam możliwości podłączenia lcd do drugiego procka.
    Ten układ sprawia wrażenie jakby podczas wysyłania instrukcja "print" umieszczała w buforze zmienną o wartości 1(jak w programie) i kolejna po niej funkcja "input" wyciąga tą zmienną bo najwidoczniej sygnał z drugiego procka nie zdążył jeszcze dojść. Niewiem czy to prawda ale gdzieś czytałem że instrukcja input wyciągając zmienną powoduje jej usunięcie z bufera co zapewne dzieje się podczas pierwszej pętli. W drugiej pętli program już nie wysyła żadnej zmiennej czym nie zaśmieca bufora, a zatem drugi procek ładuje się ze soją zmienną i wyświetla prawidłowy wynik.
    Czy dobrze myślę?

    0
  • #10 05 Sie 2013 12:55
    atom1477
    Poziom 43  

    Nie bardzo.
    Bufor nadawczy jest niezależny od odbiorczego.
    A dobre działanie UARTa w jedną stronę nie wyklucza zwarcia.
    Odpowiedz na pytanie co się dzieje bez tego drugiego procka.

    0
  • #11 05 Sie 2013 13:14
    werewolf15
    Poziom 14  

    Napisałem tak:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    I bez drugiego procka nic nie wyświetla na lcd nawet zera.
    Z drugim prockiem wyświetla 1
    Sprawdziłem miernikiem między rxd a txd i na jednym i drugim procku wyświetlało 1460.

    0
  • #12 05 Sie 2013 13:50
    piotrva
    Moderator na urlopie...

    werewolf15 napisał:
    Sprawdziłem miernikiem między rxd a txd

    Co sprawdziłeś miernikiem?
    A powodem tego, że nie wyświetla nic, jest to, że instruckja Input jest blokująca - czyli dopóki nie odbierze kompletnego ciągu zakończonego (o ile dobrze pamiętam) znakiem '\n' to program będzie na niej stał w nieskończoność.

    0
  • #13 05 Sie 2013 14:04
    werewolf15
    Poziom 14  

    Sprawdziłem miernikiem czy jest zwarcie pomiędzy rxd a txd, nie wiem jak fachowo się nazywa ten zakres na mierniku który podczas zwarcia kabli daje sygnał dźwiękowy :)

    0
  • #15 05 Sie 2013 14:21
    werewolf15
    Poziom 14  

    Kolega piotrva dał mi dużo do myślenia pisząc że instrukcja input blokuje program i czeka na odebranie kompletnego sygnału. Pomyślałem wiec po co tak sobie utrudniać jakimiś waitms' ami, pętlami i zrobiłem tak:

    At128-

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    At32-

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Teraz program działa tak jak chciałem. Wyświetla od razu odpowiednią wartość zmiennej na lcd. Niewiem tylko dla czego musiałem zamienić print i input na printbin i inputbin żeby zadziałało?

    Jeszcze raz dzięki za oświecenie!

    0
  • #16 05 Sie 2013 15:21
    atom1477
    Poziom 43  

    piotrva napisał:
    Poza tym sprawdzałeś przejście między RxD a TxD tego samego procesora? Jeśli tak to rób tak dalej, a uszkodzisz kiedyś coś ;)

    A niby to dlaczego?

    werewolf15 napisał:
    Teraz program działa tak jak chciałem. Wyświetla od razu odpowiednią wartość zmiennej na lcd. Niewiem tylko dla czego musiałem zamienić print i input na printbin i inputbin żeby zadziałało?

    Printbin i Inputbin działają binarnie.
    A Print i Input tekstowo.
    Z tego powodu działanie Printbin i Inputbin bo odbierają każdy znak bo nie czekają na \n. I nie zgłupieją jak przyjdzie jakiś znak niebędący cyfrą.

    0
  • #17 05 Sie 2013 20:20
    werewolf15
    Poziom 14  

    I znowu mam taki mały problem z tym uartem.
    Atmega32 współpracuje z kartą sd a at128 z lcd graficznym(wszystko na jednej płytce).
    Chciałem na początek napisać program dzięki któremu na lcd zobaczę rozmiar i wolne miejsce z karty sd. Napisałem coś takiego:

    At128-

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    At32-
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Program dobrze przesyła i odczytuje pierwszą wartość czyli "rozmiar" karty- wyświetla 58mb(tyle samo pokazuje na kompie). Problem pojawia się przy drugiej zmiennej "wolne" w której ma być zapisana wartość wolnego miejsca na sd. Wyświetla się ona każdorazowo w postaci "3801088". Chcę tylko dodać że zmienne są przeliczone na mb a karta jest dopiero co sformatowana.

    Proszę o pomoc w znalezieniu błędu. Najlepsza by była jakaś propozycja jak zrobić żeby oba procki wiedziały że drugi odebrał już zmienną bo znowu wplątałem się w te dziwne pętle i bardzo ciężko jest mi trafić instrukcją wysyłania z jednego procka w tym samym czasie kiedy drugi właśnie próbuje coś odebrać.

    0
  • #18 05 Sie 2013 20:53
    atom1477
    Poziom 43  

    W tej wersji ciężko będzie Ci pomóc.
    Skoro program się rozbudowuje to nie ma co brnąć w rozwiązania z pętlami.
    I pora to zrobić porządnie czyli:
    1. Na przerwaniach
    2. Na ramce danych i dodatkowo np. z sumą kontrolną.

    Mimo że raczej tego nie pochwalam, to poratuję gotowcem bo akurat go mam :D

    Kod odbiornika:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    Oczekuje na ramkę o długości 6 bajtów.
    Rozpoczętą bajtem o wartości 23, a zakończoną bajtem CRC.
    Czyli do wykożystania są 4 środkowe bajty.
    Kod nadajnika musi więc być taki:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Trzeba przyznać że ten gotowiec za porządny nie jest. Ale może Ci pomoże na początek.
    Proponuję w przerwaniu tylko odbierać dane. A w programie głównym sprawdzać co przyszło i w razie czego odsyłać potwierdzenia.
    Jeżeli ten gotowiec wydaje Ci się zbyt trudny to na początek po prostu uruchom samo przerwanie i odbieraj po jednym bajcie (bez tego CRC i innych cudów).
    Ważne tylko żeby to było w przerwaniu a więc żeby nie blokowało programu głównego.

    0
  • #19 05 Sie 2013 23:01
    werewolf15
    Poziom 14  

    Wielkie dzięki za program ale niestety jest on dla mnie bardzo trudny do zrozumienia. Szukałem jakiś wiadomości na temat tych przerwań do uart i znalazłem w helpie bascoma coś takiego:

    Cytat:
    ON źródło_przerwania nazwa_podprogramu [ NOSAVE ]

    gdzie:
    źródło_przerwania symboliczna nazwa źródła przerwania,
    nazwa_podprogramu etykieta określająca gdzie znajduje się podprogram obsługi przerwania.

    URXC przerwanie układu sprzętowego UART – odebranie znaku
    UTXC przerwanie układu sprzętowego UART – wysłanie znaku
    UDRE przerwanie układu sprzętowego UART – bufor pusty


    Problem w tym że nie wiem jak się wywołuje takie przerwania, a może one się same wywołują, może trzeba je zainicjować w programie głównym jakąś funkcją, no nie mam pojęcia jak z nich korzystać.Chyba najprościej było by mi zrobić to na timerze ale chyba mi ich braknie bo używam do: RC5(timer2), zegara wewnętrznego(timer0), panelu dotykowego(timer1).
    Tak więc proszę o jakieś informacje jak korzystać z tych przerwań do uart'a.

    0
  • #20 06 Sie 2013 08:33
    atom1477
    Poziom 43  

    Tobie potrzeba przerwanie od odebrania znaku.
    Czyli robisz:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    potem deklarujesz sobie zmienne i inne cuda:
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod



    Gdzieś na początku programu przez pętlą główną zezwalasz na obsługę przerwania:
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    A gdzieś na końcu kodu dajesz obsługę tego przerwania:
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Przerwanie będzie się samo wywoływało przy każdym przychodzącym znaku.

    W programie głownym robisz np. coś takiego:
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    0
  • #21 06 Sie 2013 11:43
    werewolf15
    Poziom 14  

    Napisałem taki programik testowy do wysyłania i odbierania jednej zmiennej:

    At128-

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    At32-
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    At128 wysyła sygnał w postaci zmiennej o wartości 1. At32 odbiera ten sygnał i odsyła inną zmienną która ma pojawić się na lcd.
    Program niestety nie działa, na lcd nic nie wyświetla.
    Co jeszcze można poprawić?

    Dodano po 5 [minuty]:

    Przepraszam już działa!

    zamiast print:
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    dałem printbin:
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Teraz czas na próbę z kartą sd :)

    0
  • #22 06 Sie 2013 11:56
    atom1477
    Poziom 43  

    A ja się zastanawiam po co Ci to:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    Bo jeżeli ręcznie odbierasz znaki w przerwaniu (a odbierasz) to to jest zbędne.
    Albo może i nawet szkodliwe.

    0
  • #23 06 Sie 2013 13:04
    werewolf15
    Poziom 14  

    I udało się!
    Tak wygląda gotowy działający program do wyświetlania informacji o karcie sd na lcd:

    At128-

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    At32-
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Jeżeli ktoś by jeszcze jakiś błąd zauważył proszę pisać :)

    0
  • #24 06 Sie 2013 13:56
    atom1477
    Poziom 43  

    A jesteś pewien że działa?
    Bo wysyłasz zmienne Long a odbierasz Byte.
    A więc to raczej nie działa.

    0
  • #25 06 Sie 2013 14:05
    werewolf15
    Poziom 14  

    Ale właśnie że jest dobrze: at128 wysyła byte i at32 dbiera byte, at32 wysyła long
    i at128 odbiera long.
    Zobacz jeszcze raz do programu :)

    0
  • #26 06 Sie 2013 14:31
    atom1477
    Poziom 43  

    A faktycznie :D
    Tylko Ci to trochę wstrzymuje program.
    Bo instrukcja InputBin w przerwaniu poza odebraniem pierwszego bajtu czeka też na kolejne 3.
    Poza tym prawdopodobnie ustawiają one na nowo flagę przerwania więc po odebraniu tych 3 bajtów i wyjściu z przerwania program znowu wchodzi w przerwanie.
    Odbieranie zmiennej Long w przerwaniu ostatecznie może zostać ale pasowało by w takim razie ręcznie kasować flagę przerwania przy wychodzeniu z tego przerwania.

    0
  • #27 06 Sie 2013 16:40
    werewolf15
    Poziom 14  

    To prawda że muszę odczekać kilka sekund aż program się wykona.
    Czyli ustawić wszystkie zmienne komunikacyjne na long?
    A co to znaczy "ręcznie kasować flagę" ?

    Dodano po 56 [minuty]:

    W helpie bascoma znalazłem taki fragment o instrukcji inputbin:

    Cytat:
    ...Liczba odczytywanych bajtów jest określana na podstawie typu podanej zmiennej. Gdy jako parametr będzie użyta zmienna typu Byte, instrukcja odbierze jeden znak. Przy zmiennych typu Integer odczytane zostaną dwa znaki. ...

    Uwaga! Instrukcja INPUTBIN nie kończy się gdy zostanie odebrany znak <CR> (kod 13), tylko gdy wszystkie bajty zostaną odebrane.


    Tak więc chyba nie ma różnicy jaką zmienną odbieram?

    0
  • #28 06 Sie 2013 16:47
    atom1477
    Poziom 43  

    Jest różnica bo używasz InputBin w przerwaniu.
    Ono odbiera 4 bajty ale skoro są włączone przerwania to flaga od odebranego znaku jest ustawiana.
    Ręcznie skasować flagę to można chyba tylko bezpośrednim wpisem do rejestru.
    Tutaj BASCOM nie pomoże. Musowo zajrzeć do datasheeta.

    0
  • #29 06 Sie 2013 17:08
    werewolf15
    Poziom 14  

    Ustawiłem wszystkie zmienne na byte, oprócz rozmiar i wolne w at32 do których trafia bezpośredni odczyt z sd, które potem i tak zamieniam na byte.

    At128-

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    At32-
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Program oczywiście działa.
    Czy teraz niebędzie problemu skoro do odebrania jest zawsze tylko jeden bajt?

    0
  • #30 06 Sie 2013 17:17
    atom1477
    Poziom 43  

    Nie widzę zamieniania Long na Byte.
    W tym przypadku trzeba zrobić albo:
    1. Odpytywać układ po kolei o każdą część zmiennej Long (czyli 4 razy).
    2. Zrobić ramkę danych która to prześle w całości (coś jak mój kod tylko jakoś prościej może na początek). Da to kontrolę błędów a więc pewniejszą transmisję jak się przesyła raz zmienne Byte a raz Long.
    3. Przesyłać zmienne Long (i tylko zmienne Long) + dodać kasowanie flagi przerwania w przerwaniu.

    0