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

[avr][c][usart][rs485] zbyt wolna transmisja

Yazutsu 07 Lis 2011 21:39 3003 25
REKLAMA
  • #1 10114416
    Yazutsu
    Poziom 10  
    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 / 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 / C++
    Zaloguj się, aby zobaczyć kod

    a potem w pętli głównej lata sobie:
    Kod: C / 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ć?
  • REKLAMA
  • #2 10114591
    kriss68
    Poziom 20  
    A może tak?
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #3 10114731
    Yazutsu
    Poziom 10  
    Nie działa, nawet tak nie działa że dodanie delaya nie pomaga :/
  • #5 10114905
    Yazutsu
    Poziom 10  
    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 / C++
    Zaloguj się, aby zobaczyć kod


    ad3.

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


    Nie może mieć ona wpływu bo nie działa też jak nic nie klikam.
  • #6 10115450
    kriss68
    Poziom 20  
    A tak?
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #7 10115457
    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?
  • REKLAMA
  • #8 10115472
    kriss68
    Poziom 20  
    Jak dla mnie to problem jest w wyłączeniu nadajnika jeszcze przed końcem nadawania.
  • #9 10115492
    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.
  • #10 10115523
    Yazutsu
    Poziom 10  
    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
  • #11 10115526
    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.
  • #12 10115543
    Yazutsu
    Poziom 10  
    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?
  • #13 10115552
    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.
  • #14 10115570
    Yazutsu
    Poziom 10  
    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.
  • #15 10115578
    kriss68
    Poziom 20  
    Ja mam czas i chęci ale to dopiero jak będę w domu. Moje gg masz w moim profilu :)
  • REKLAMA
  • #16 10115646
    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 / 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 / C++
    Zaloguj się, aby zobaczyć kod


    no chyba że coś pokręciłem.
    Pozdrawiam
  • #17 10115660
    kriss68
    Poziom 20  
    W nocie m32 pisze, że TXC zeruje się poprzez zapis 1 a przynajmniej tak to zrozumiałem.
  • REKLAMA
  • #18 10115669
    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: text
    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
  • #19 10115742
    Yazutsu
    Poziom 10  
    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 / C++
    Zaloguj się, aby zobaczyć kod


    A w pętli głównej programu śmiga sobie taki while:
    Kod: C / 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ć.
  • #20 10115756
    kriss68
    Poziom 20  
    A kwarce masz "uartowe" tzn o odpowiedniej częstotliwości?
  • #21 10115767
    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 ?
  • #22 10115811
    Yazutsu
    Poziom 10  
    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 / 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:
    $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.
  • #23 10115844
    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.
  • #24 10115905
    Yazutsu
    Poziom 10  
    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 / 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?
  • #25 10115927
    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 / 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.
  • #26 10119313
    Yazutsu
    Poziom 10  
    Witam,

    Postanowiłem zrobić tak:

    normalna transmisja wyglądała tak:
    
    $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:
    $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 / C++
    Zaloguj się, aby zobaczyć kod


    zmienną panel_gotowy_na_odbior ustawiam na 1

    a przy wysyłaniu robie tak:
    Kod: C / 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 / 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:
    
    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....
REKLAMA