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

[Mega16][C][WinAvr]Brak transmisji poprzez rs485

revcorey 21 Sie 2011 14:24 3312 7
REKLAMA
  • #1 9847164
    revcorey
    Poziom 12  
    Sugerując się tym tematem
    https://www.elektroda.pl/rtvforum/topic1380925.html
    Napisałem prostą obsługę rs485 dla dwóch mega16 jeden to master drugi slave. Niestety nic się nie dzieje błąd tkwi w kodzie lub połączeniu na płytce albo w obu.
    Master:
    #include <avr/io.h>
    #include <inttypes.h>
    #include <util/delay.h>
    #include <stdio.h>
    #include <avr/interrupt.h>
    void USARTInit(uint16_t ubrr_value)
    {
    
       UBRRL = ubrr_value;
       UBRRH = (ubrr_value>>8);
    
       UCSRC = 0x86;
       UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
       PORTD &=~_BV(4);
       _delay_ms(1);
    }
    
    
    
    
    
    void USARTWriteChar(char data)
    {
    	//while(!(UCSRA & (1<<UDRE)))
      // {}
    UDR=data;
    }
    
    void main()
    {
    	sei();
    	DDRA=0xff;
    	PORTA=0xff;
    	USARTInit(51);
    while(1){
    	 PORTD |= _BV(4); //nadawanie
    	USARTWriteChar('b'); //umownie b to adres modułu
    	PORTD &=~_BV(4);//RS485 - odbior
    	_delay_ms(500);
    	PORTA=0xf0;
    }
    }
    ISR(USART_RXC_vect)
    {
       char received_byte;
       received_byte = UDR;
       if(received_byte == 'x'){
       PORTA=0x0f;
       }
    
    }

    slave:
    #include <avr/io.h>
    #include <inttypes.h>
    #include <util/delay.h>
    #include <stdio.h>
    #include <avr/interrupt.h>
    void USARTInit(uint16_t ubrr_value)
    {
    
       UBRRL = ubrr_value;
       UBRRH = (ubrr_value>>8);
    
       UCSRC = 0x86;
       UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
       PORTD &=~_BV(4);
       _delay_ms(1);
    }
    
    void main()
    {
    
    	sei();
    	USARTInit(51);
    
    while(1){
    
    }
    }
    ISR(USART_RXC_vect)
    {
       char received_byte;
       received_byte = UDR;
       if(received_byte == 'b'){
       PORTD |= _BV(4); //nadawanie
       UDR = 'x'; // odpowiedź dla mastera
       }
       PORTD &=~_BV(4);//odbiór
    }

    Schemat(przepraszam że trochę chaotyczny):
    [Mega16][C][WinAvr]Brak transmisji poprzez rs485

    układ max485: RE i DE podłączone do PD4,R0 do Rxd a Di do Txd następnie pomiędzy linie A I B oporniki 120 ohm jako terminatory na końcach linii, dwa oporniki 1,2k ten z A do GND a ten z B do Vcc ma to zapewnić poprawną polaryzację.
    Korzystam z wewnętrznego oscylatora ustawionego na 8 mhz, rs232 przy prędkości 9600 działa na takim zegarze.

    Niestety układ nie działa.
  • REKLAMA
  • Pomocny post
    #2 9847346
    snnaap
    Poziom 25  
    Pomiędzy zmianą funkcji na nadajnik a wysłaniem danej dodaj opóźnienie ok 1ms tak samo pomiędzy nadawaniem a przełączaniem na odbiornik.

    PORTD |= _BV(4); //nadawanie
    _delay_ms(1)
    USARTWriteChar('b'); //umownie b to adres modułu
    _delay_ms(1)
    PORTD &=~_BV(4);//RS485 - odbior

    Musisz to zrobić w nadajniku i odbiorniku.
  • REKLAMA
  • #3 9847552
    revcorey
    Poziom 12  
    Pomogło wielkie dzięki, i przy okazji się okazało że jedna z atmega16 miała uszkodzone porty A i dopiero po wymianie chodzi.
  • REKLAMA
  • #4 10158532
    jarenty13
    Poziom 10  
    Witam. Mam pytanie odnośnie wektora przerwań ISR(USART_RXC_vect) który występuje w kodzie mastera. Czy to przerwanie uaktywania się zaraz po ustawieniu portu PORTD &=~_BV(4); na odbiór i odebraniu całego bajtu czy może uaktywania się na końcu pętli while?
  • #5 10160322
    revcorey
    Poziom 12  
    Witaj, Otóż układ max485 wymaga żeby podczas nadawania na dwa wejścia RE i DE była ustawiona jedynka, podczas odbioru na zero. Czyli wysyłam zapytanie do modułów(u mnie b było adresem), zaraz po wysłaniu przestawiam się w tryb odbioru(w pętli while) i czekam na odpowiedź. Nie mógłbym tego zrobić w przerwaniu ponieważ na początku ustawiłem sobie nadawanie i przerwanie nie miało by jak zadziałać.
  • #6 10160390
    jarenty13
    Poziom 10  
    Rozumiem o co Ci chodzi ale ja chciałem zobaczyćw którym momencie uruchamiane jest przerwanie i napisalem sobie taki oto kod:

    kod mastera:

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


    Moim zdaniem powinna najpierw zgasnąć pierwsza dioda potem wystąpić przerwanie i zgasnać druga a na końcu powinna zgasnać dioda trzecia, jednak po wgraniu kodu na uC kolejnosc jest nastepujaca: 1 ->3 -> 2 I nie wiem w tym momencie jak mam to rozumieć?
  • #7 10163029
    revcorey
    Poziom 12  
    jednej rzeczy u ciebie nie widzę. Nadawania czego kol wiek.
    najpierw za pomocą
    USARTWriteChar() nadaj jakiś znak do drugiego avr i czekaj na odpowiedź.
  • REKLAMA
  • #8 10163709
    jarenty13
    Poziom 10  
    Na razie zaczynam robić komunikacje i master ma jedynie odbierać znaki a slave ciagle nadaje. Dorzucam kod slave:

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


    To jak to jest z tymi przerwaniami w końcu? W którym miejscu się one uaktywaniaja? Bo z tego co wyczytalem z karty katalogowej i innych źródeł wynika że przerwanie powinno wystapić gdy odebrany jest cały bajt czyli tak jak jest w moim kodzie przed zgaszaniem diody numer 3 a z moich obserwacji wynika ze najpierw gasnie dioda pierwsza potem trzecia i dopiero nastepuje przerwanie sygnalizowane zgaszeniem diody drugiej.
REKLAMA