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][c][usart][rs485] zbyt wolna transmisja

Yazutsu 07 Lis 2011 21:39 2772 25
  • #1 07 Lis 2011 21:39
    Yazutsu
    Poziom 9  

    Witam,

    Komunikuje ze sobą dwa Uc:
    Atmega8 - panel z wyświetlaczem i guzikami
    Atmega32 - baza gdzie mam wszystkie czujniki
    Kwarce 14.746 Mhz w obydwu przypadkach
    Transmisja dwukierunkowa half-duplex przez rs-485.

    W uproszczeniu panel z wyświetlaczem ma za zadanie wyświetlać wszystko co mu wyśle baza, czyli 21 znaków x 8 lini = 168 bajtów.

    Wysyłanie realizuję tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Niestety nie wiem dlaczego ale bez tego opóźnienia nie działa, tz może być większe ale nie mniejsze.

    Skutkuje to tym że wyświetlacz zapełnia mi się zdecydowanie za wolno
    168 bajtów , każde opóźnione o 2ms a to daje mi prawie 350ms.

    Odbiór w panelu z wyświetlaczem jest na przerwaniu:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    a potem w pętli głównej lata sobie:
    Kod: c
    Zaloguj się, aby zobaczyć kod



    Wydawało mi się że może zbyt wcześnie zmieniałem kierunek transmisji na odbieranie. Przeniosłem zmianę kierunku do przerwania które wykonuje się już po udanej transmisji (USART_TXC_vect) a bez tego delaja nadal nie dziala...


    Co to może być?

    0 25
  • #2 07 Lis 2011 22:09
    kriss68
    Poziom 20  

    A może tak?

    Kod: c
    Zaloguj się, aby zobaczyć kod

    1
  • #3 07 Lis 2011 22:32
    Yazutsu
    Poziom 9  

    Nie działa, nawet tak nie działa że dodanie delaya nie pomaga :/

    0
  • #4 07 Lis 2011 22:55
    JarekC
    Poziom 27  

    Witam,

    Kilka dodatkowych pytań:

    1. jaka prędkość transmisji
    2. ile bitów STOPu ?
    3. czy w programie obsługującym wyświetlacz jest obsługa innych przerwań niż
    przerwanie od odbiornika UART?

    Pozdrawiam
    JarekC

    0
  • #5 07 Lis 2011 23:14
    Yazutsu
    Poziom 9  

    JarekC:

    ad1.
    Próbowałem przy wszystkich prędkościach od 9600 do 230400.
    Jedyna różnica była taka że przy 230400 wystarczał już delay na 1ms , ale raz na jakiś czas pojawiał się na ekranie krzak.

    ad2.
    Tak mam to poustawiane:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    ad3.

    Jest tylko zwykła obsługa przycisków:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Nie może mieć ona wpływu bo nie działa też jak nic nie klikam.

    0
  • #6 08 Lis 2011 09:26
    kriss68
    Poziom 20  

    A tak?

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #7 08 Lis 2011 09:32
    snnaap
    Poziom 25  

    Problem jest nie w komunikacji tylko w wyświetlaczu. Po prostu wyświetlacz się nie wyrabia czytaj może błędnie napisana procedura obsługi wyświetlacza, pokaż jak masz napisaną obsługę wyświetlacza, używasz opóźnień czy flagi zajętości wyświetlacza?

    1
  • #8 08 Lis 2011 09:38
    kriss68
    Poziom 20  

    Jak dla mnie to problem jest w wyłączeniu nadajnika jeszcze przed końcem nadawania.

    0
  • #9 08 Lis 2011 09:47
    snnaap
    Poziom 25  

    kriss68 napisał:
    Jak dla mnie to problem jest w wyłączeniu nadajnika jeszcze przed końcem nadawania.


    Po czym tak wnioskujesz?
    Jeżeli kolega używa Max485 to najdłuższy czas jakiegokolwiek nieprzełączania w układzie to 2000ns i jest to czas pomiędzy wyjściem ze stanu uśpienia układu w stan odbioru lub nadawania.
    Maksymalny czas pomiędzy przełączeniem się ze stanu nadawania do odbioru to również 2000ns a typowy czas to 800ns. Dane z noty.


    Do 2ms jeszcze "troszkę" brakuje.

    Pozdrawiam

    PS. Wyłączenie nadajnika powinno nastąpić po 3000ns od zakończenia nadawania. Nota.

    0
  • #10 08 Lis 2011 10:00
    Yazutsu
    Poziom 9  

    Cieszę się że ktoś się zainteresował tematem, bo sam już rwałem włosy z głowy.


    kriss68:
    Tak też nie, a może ktoś by pokazał jak ma to zrobione u siebie, jestem pewien że nie ja pierwszy wpadłem na taki pomysł.

    snnaap:
    No właśnie wg mnie problem nie leży w samym wyświetlaczu, sprawdzałem i to.
    Bezpośrednio w kodzie panela z wyświetlaczem umieszczałem cały ekran textu po 10 razy na sekunde i się wyrabiał bez problemu.
    Wyświetlacz jest na KS0108 , sterownik od Radzia, używa busyflag więc nie mam tam opóźnień na sztywno.

    Może szczegółowiej opiszę jak to wygląda:

    Normalnie gdy wypełniam wyświetlacz tekstem bezpośrednio z Uc, wyświetlacz wypełnia się tak szybko że moje oko nie rejestruje kolejności pojawiania się literek.

    Przy dotychczasowej transmisji tekst pojawia się od góry i płynie w dół.a wyświetlenie jednego pełnego ekranu zajmuje prawie 0,5sek ...

    snnaap:
    Dokładnie rzecz ujmując jest to SN75176

    0
  • #11 08 Lis 2011 10:02
    kriss68
    Poziom 20  

    Patrz ustawiasz nadawanie, wpisujesz dane do nadania i odrazu przełączasz na odbieranie co się stanie? Napewno cała ramka nie przejdzie więc odbiornik to zignoruje. Teraz przed przełączeniem czekasz te 2ms i przechodzi cała ramka. Dlatego trzeba czekać nazakończenie wysyłania ramki przed przełączeniem na odbieranie. Sprawdź czy drugi układ odbiera cokolwiek.

    0
  • #12 08 Lis 2011 10:09
    Yazutsu
    Poziom 9  

    kriss68 napisał:
    Patrz ustawiasz nadawanie, wpisujesz dane do nadania i odrazu przełączasz na odbieranie co się stanie?

    Właśnie dla tego przerzuciłem zmianę kierunku spowrotem na odbieranie do przerwania które jest wywoływane dopiero po udanym wysłaniu, no chyba że się mylę i przerwanie USART_TXC_vect wywoływane jest jeszcze gdy trwa wysyłanie?

    0
  • #13 08 Lis 2011 10:14
    kriss68
    Poziom 20  

    Tamto było bardziej do kolegi snnaap. No właśnie dziwne to zachowanie bo według noty TXC jest ustawiane po wysłaniu całej ramki a zerowane jest przez przerwanie albo wpisanie 1 w jego miejscu. A spróbuj dodać kilka asm("nop") przed zmianą tego pinu w przerwaniu.

    0
  • #14 08 Lis 2011 10:20
    Yazutsu
    Poziom 9  

    w czym asm("nop") będzie lepsze od _delay_ms(1) przy którym tez nie działa?

    Wolałbym całego kodu nie umieszczać na forum, jeśli ktoś ma czas i chęci mogę wysłać na priva.

    0
  • #15 08 Lis 2011 10:25
    kriss68
    Poziom 20  

    Ja mam czas i chęci ale to dopiero jak będę w domu. Moje gg masz w moim profilu :)

    0
  • #16 08 Lis 2011 10:51
    snnaap
    Poziom 25  

    No tak moja wina nie zrozumiałem z lekka albo przeczytałem z niezrozumieniem.

    Poniższy tok rozumowania i związany z nim kod:

    kriss68 napisał:
    A tak?
    Kod: c
    Zaloguj się, aby zobaczyć kod


    jest niby prawidłowy z tym że dlaczego jest


    UCSRA |= 1<<TXC;
    a nie tak:
    UCSRA &= ~(1<<TXC);
    flaga TXC jest ustawiana "1" gdy wysłanie zostało zakończone, tak?

    według mnie procedura powinna wyglądać tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    no chyba że coś pokręciłem.
    Pozdrawiam

    0
  • #17 08 Lis 2011 10:58
    kriss68
    Poziom 20  

    W nocie m32 pisze, że TXC zeruje się poprzez zapis 1 a przynajmniej tak to zrozumiałem.

    0
  • #18 08 Lis 2011 11:10
    snnaap
    Poziom 25  

    kriss68 napisał:
    W nocie m32 pisze, że TXC zeruje się poprzez zapis 1 a przynajmniej tak to zrozumiałem.


    Faktycznie

    Dodano po 9 [minuty]:

    Dobra ostatnie moje słowo ;) reasumując powyższe

    Kod: cpp
    Zaloguj się, aby zobaczyć kod



    Główną zmianą jest opróżnianie pomiędzy przełączeniem na nadajnik a rozpoczęciem wysyłania.

    Proszę o sprawdzenie.

    Pozdrawiam

    0
  • #19 08 Lis 2011 11:42
    Yazutsu
    Poziom 9  

    Niestety nie, ja myślę chyba jednak żeby zostawić tą transmisję, a winę za konieczność stosowania delaya zrzucić na kod obsługi wyświetlania tego co przyjdzie.
    Porobiłem troszkę testów i tak:
    ustawiłem bitrate na 230400
    i zacząłem zmniejszać wartość delay i tak dla:
    1300us - jeden krzak na wyświetlaczu(zawsze w tym samym miejscu)
    1100us - dwa krzaki na wyświetlaczu(zawsze w tym samym miejscu)
    900us - trzy krzaki na wyświetlaczu(zawsze w tym samym miejscu)
    błędy pojawiają się po dłuższych stringach.
    poniżej 700us już są prawie same krzaczki.

    I tak sobie myślę że to chyba jednak jest wina programu panela.

    Odbieram w ten sposób i tu się raczej wszystko wyrabia:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    A w pętli głównej programu śmiga sobie taki while:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    I myślę że ta pętla nie wyrabia się z pobieraniem danych z bufora.

    Coś się da na to poradzić?

    Czy może wrzucić obsługę wyświetlacza do przerwania od odbierania z RS-a?
    Czy wtedy dopóki nie wyświetli nie pobierze kolejnych ramek danych?
    Ale tak się chyba nie powinno robić.

    0
  • #20 08 Lis 2011 11:53
    kriss68
    Poziom 20  

    A kwarce masz "uartowe" tzn o odpowiedniej częstotliwości?

    0
  • #21 08 Lis 2011 11:59
    snnaap
    Poziom 25  

    Gdzie pojawią się te błędy na końcu stringa na początku?

    Zrób potwierdzenia odbioru.
    Układ nadaje - następnie czeka na potwierdzenie odbioru jak je otrzymał nadaje kolejną ramkę.

    PS. Atmega32 ma 2 UARTy. Podłącz go przez drugiego UARTA do PC i po odebraniu znaku z Atmega8 prześlij go do PC. Zobacz co się wyświetli, będziesz miał wtedy pewność co zawodzi.

    PS2. czemu wysyłasz stringi? co tak w ogóle wysyłasz ?

    0
  • #22 08 Lis 2011 12:25
    Yazutsu
    Poziom 9  

    Kriss68:
    Kwarce 14.746 Mhz w obydwu przypadkach

    snnaap:

    Jest tak, dajmy na to ostatnią linię wysyłam w ten sposób z bazy:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    przy udanej transmisji wynik na wyświetlaczu wygląda tak: "Ilosc wyslan: 110"
    przy zmniejszeniu czasu delay tak:"Ilosc wysla00840072"

    Tak wygląda to co wysyłam:
    Code:
    $0000007
    
    Ilosc wyslan:
    $0084007


    Tak jakby ten ciąg cyfr które ja nazywam krzakami to była pozostałość po transmisji pozycji umieszczenia tekstu.
    Tak jakby zdążył ustawić karetke na dobrej pozycji "$0000007"
    Zdążył wyświetlić "Ilosc wyslan:"
    ale z ostatniego $0084007 wyciął znak $ i uznał to za zwykłego stringa do wyświetlenia.

    Dodano po 4 [minuty]:

    snnaap napisał:
    PS. Atmega32 ma 2 UARTy. Podłącz go przez drugiego UARTA do PC i po odebraniu znaku z Atmega8 prześlij go do PC. Zobacz co się wyświetli, będziesz miał wtedy pewność co zawodzi.


    Atmega32 ma dwa uarty??

    Mniejsza z tym, mam przejściówkę usb-rs-485 i sobie podsłuchiwałem co się dzieje na lini, transmijsa przebiega poprawnie.

    0
  • #23 08 Lis 2011 12:39
    snnaap
    Poziom 25  

    A wyślij takie coś:

    $0000007
    Ilosc :
    $0084007

    i daj znać co jest.

    Z tymi UARTAMI to może źle się wysłowiłem chodzi mi o to że można mieć 2 UARTY - 2 programowy np.

    Dodano po 2 [minuty]:

    Jaka wartość ma zmienna: UART_MAXBUFF?

    Dodano po 3 [minuty]:

    Pomiędzy tymi liniami:
    x=0;y++;
    LCD_GoTo(x++,y); USART_SendStringEND((unsigned char*)"Ilosc wyslan:"); x+=13;
    LCD_GoTo(x++,y); USART_SendStringEND((unsigned char*)itoa(ilosc_wyslan,buffer_t,10));

    daj opóźnienie ok 10ms.

    0
  • #24 08 Lis 2011 13:06
    Yazutsu
    Poziom 9  

    Więc tak dla zupełnej pewności podpiąłem zakurzony usb-rs-485 i sprawdziłem, nawet przy transmisji 230400 bez żadnego delaya w sekcji nadawania z bazy REALTERM bez problemu odczytuje wszystkie dane.

    Czyli problem musi być po stronie odbierania.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Tu miejsca nie brakuje.

    snnaap napisał:
    daj opóźnienie ok 10ms.

    Ja walczę z opóźnieniem rzędu 2ms a ty proponujesz 10 ??
    nawet bez sprawdzania wiem że to pewnie pomoże ale to nie jest lekarstwo na problem.

    Zapytam jeszcze raz trochę inaczej, co się stanie jak zatrzymam na chwilę przerwanie USART_RXC_vect ??
    Czy panel pominie wtedy dane wysyłane z bazy czy będzie czekać na nadanie reszty?

    0
  • #25 08 Lis 2011 13:23
    snnaap
    Poziom 25  

    Ty wprowadzasz o późnienie 2 ms w momencie wysłania każdego znaku co daje nam np przy 10 znakach 20 ms.
    Ja proponuje zrezygnować z tego opóźnienia a dać niewielkie2ms po każdej linii a nie znaku.
    Czyli opróżnianie po wysłaniu 3 linii (trzech paczek) wyniesie 6ms.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dodano po 3 [minuty]:

    Yazutsu napisał:

    Zapytam jeszcze raz trochę inaczej, co się stanie jak zatrzymam na chwilę przerwanie USART_RXC_vect ??
    Czy panel pominie wtedy dane wysyłane z bazy czy będzie czekać na nadanie reszty?


    panel zgubi dane z bazy i będzie wielkie g.

    Można zrobić tak. Baza wysyła do panelu i czeka aż panel zgłosi że odebrał dane. To będzie znak dla bazy że może wysłać kolejną porcję danych. Tylko że tu będzie pełna komunikacja 2 kierunkowa. Ale tak to się prawidłowo robi. Master wysyła dane slave je odbiera i potwierdza masterowi że odebrał prawidłowe dane.

    0
  • #26 09 Lis 2011 12:31
    Yazutsu
    Poziom 9  

    Witam,

    Postanowiłem zrobić tak:

    normalna transmisja wyglądała tak:

    Code:

    $0030000    //komenda ustawienia karetki na pozycji
    temp NAW  //bez znaku $ więc zwykły tekst
    $0000001   ////komenda ustawienia karetki na pozycji
    23             ////bez znaku $ więc zwykły tekst

    Baza musi poczekać z wysłaniem kolejnego stringa aż panel odpowie że już wyświetlił poprzedniego.
    Już to zrobiłem w panelu dzięki temu transmisja wygląda tak:
    Code:
    $0030000
    
    5temp NAW
    5$0000001
    523


    Za każdym razem panel po odebraniu nadaje "5".

    Problem pojawia się z kodem bazy, robie tak:
    Odbieram przerwaniem:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    zmienną panel_gotowy_na_odbior ustawiam na 1

    a przy wysyłaniu robie tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    niestety coś to nie działa, wiem że ładniej by to byo gdyby zamiast if było tam:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Ale opcja z while nie wiem czemu nie działa, a bardzo by to ułatwiło bo nie musiałbym na sztywno ustawiać czasu opóźnienia.

    Drugim błędem który mnie blokuje jest to jak wygląda kod po wysyłaniu dłuższych stringów:
    Code:

    5$0000006
    5Ilosc odebran:
    $50090006      // TUTAJ "5" PRZESKAKUJE NA DRUGĄ POZYCJĘ
    51425


    Czyli tak jakby mój kod że ma wysłać dopiero jak flaga panel_gotowy_na_odbior ustawi się na 1 nie działa....

    0