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

rs485->uart. Jak procesor orientuje się, że wysłano do niego zapytanie?

5657jz 01 Maj 2011 15:42 1980 4
  • #1 9457922
    5657jz
    Poziom 14  
    Mam odbiornik MAX485 podłączony pod Atmegę16.

    Stany poczatkowe:
    -ustawione przerwanie na odbiór UARTa
    - stan niski na DE/RE w odbiorniku Max 485
    - Max 485 na RO,DI stan wysoki ( równierz Atmega RxD) !!?

    Wysyłam dane: (z odbiornika wychodzą prawidłowo 0 i 1)
    - Wchodzę w przerwanie i klapa. - same zera.

    Pytanie brzmi: co jest źle? Jak procesor orientuje sie ze wysłano do niego bajt?

    ISR(USART_RXC_vect )  //SIG_UART_RECV 
    {
    
    lcd_gotoxy( 0,0);
    write_znak('P',1); // znacznik że wszedłem w przerwanie
    
    unsigned char i=0;
      byte=UDR;
      bit(byte);  // umieszcza na wyswietlacu bity
     
    			if (byte==':')  // sprawdzenie czy poczatek ramki (:)
    				{bit_start=1; 	bit_stop=0;
    				lcd_gotoxy( 1,0);
    				write_znak('S',1);// znacznik
    				
    				}
    			if (byte==';' && bit_start==1)  // sprawdzenie czy koniec ramki (;)
    				{bit_start=0; 	bit_stop=1;
    				lcd_gotoxy( 2,0);
                    write_znak('R',2);//znacznik
    				_delay_ms(100);
    				}
    		
    			if (bit_start==1)  
    			  {RX_ramka[i]=byte; i++;
     				bit(byte);
     				 _delay_ms(500);}
    			if (bit_stop==1) 
    				odebr_zn='1';  // koniec ramki - do prog. glownego
    		    
    }

    void bit(unsigned char bit)
    {
    char i;
    lcd_gotoxy( 0,2);
    	 for(i=0;i<8;i++)
    		{
    			if (bit & 0x80)
    				    write_znak('1',1);
    			else	write_znak('0',1);
    
    			bit<<=1;
    		}
    }
  • #2 9458311
    mirekk36
    Poziom 42  
    Pierwsze i tragiczne to co robisz źle - to w przerwaniu nie dość że wwaliłeś obsługę wyświetlacza LCD to jeszcze jakieś delay'e po 500ms ! - to już jakby masakra niestety :(

    poczytaj sobie coś na temat na razie obsługi zwykłego RS'a i do tego buforów cyklicznych na przerwaniach - zarówno dla nadawania jak i odbioru. Bo z taką próbą obsługi daleko nie zajedziesz niestety :(
  • #3 9459263
    5657jz
    Poziom 14  
    Tak. wiem, że tak nie można.
    Niestety, inaczej też mi nie wychodzi.
    Wyglada to tak:
    rs485->uart. Jak procesor orientuje się, że wysłano do niego zapytanie?
    KOD:
    void uart_init(unsigned int ubrr) 
    {
      /* 9600 bit/s */
      UBRRH = (unsigned char)(ubrr>>8);
      UBRRL = (unsigned char)ubrr;       // 25 -> 4000000
             /* RxD=>ON;  ISR(koniec odbioru), TxD=>ON*/
      UCSRB = _BV(RXEN)|_BV(RXCIE)|_BV(TXEN);
            /* 8-bit dane, 1-bit stopu, brak bitu parzystosci */
      UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  //    (1<<USBS)|
            RS485_INIT();
    		RS485_OUT();
    		ALBITRAZ_UART_INIT();
    } 

    ISR(USART_RXC_vect )  //SIG_UART_RECV 
    {
    
    //lcd_gotoxy( 0,0);
    //write_znak('P',1); // znacznik że wszedłem w przerwanie
    
    unsigned char i=0;
      byte=UDR;
    odebr_zn='1';

    if (odebr_zn=='1') // flaga przerwania od RxD
    			{
    			odebr_zn='0';
    			unsigned char info_uart;
    			char x[2];
    			itoa(byte,x,10);
    			lcd_gotoxy(0, 1);
    			write_znak(x[0],1);write_znak(x[1],1);



    Wysyłam znak: 'A' w odpowiedzi mam: '0'
    Niestety, nie mam pomysłu jak dojść do błędu który popełniłem.
    Proszę o pomoc, podpowiedź , co kolwiek. Muszę to uruchomić.
    Z dużo kodu mam za sobą aby zrezygnować. RSa odłożyłem na koniec bo wydawał mi się najprostrzy. Niestety wyłożyłem się
  • Pomocny post
    #4 9459971
    Andrzej__S
    Poziom 28  
    Twój kod niewiele mówi. Podajesz za mało danych. Nie wiadomo np.:
    Czy byte to zmienna globalna (można się tego ewentualnie domyślić) i czy jest zadeklarowana jako volatile(to trudno przewidzieć)?
    Czy warunek if (odebr_zn=='1') sprawdzasz w przerwaniu, czy w pętli głównej?
    Czemu ma służyć deklaracja unsigned char i=0;?
    Co to za funkcje (makra?) RS485_INIT(); , RS485_OUT(); i ALBITRAZ_UART_INIT();?

    Tymczasowo zauważyłem co następuje:

    To, co próbowałeś robić:
    5657jz napisał:

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


    nie zda egzaminu choćby dlatego, że zmienna i powinna być w tym przypadku zadeklarowana jako static, bo tak jak obecnie to w każdym wywołaniu obsługi przerwania będzie ona inicjowana z wartością 0. Poza tym, jak już wcześniej napisał kolega mirekk36, najlepiej użyć do tego bufora cyklicznego, w przerwaniu zapisywać do niego tylko odebrane bajty bez obsługi wyświetlaczy i opóźnień, a interpretację danych robić w pętli głównej programu. Gorąco polecam poczytanie na ten temat.

    Funkcja itoa() oczekuje bufora (w Twoim przypadku) o rozmiarze minimum 4 bajty, a nawet 5, w przypadku liczb ujemnych, czyli zamiast char x[2]; powinno być char x[5]; przy użyciu funkcji itoa(), lub char x[4]; przy użyciu funkcji utoa(). Dlaczego? Zmienna byte może przyjąć w systemie dziesiętnym wartości 3 cyfrowe, a na końcu tablicy funkcja itoa() umieszcza dodatkowo znak '\0' (terminator string). Jeśli kompilator umieści za tablicą x jakąś zmienną, to funkcja itoa() będzie ją nadpisywać, niszcząc dane. Prawdopodobnie nie rozwiąże to Twoich problemów z transmisją, ale i tak należałoby to poprawić, bo program może przez to nie działać prawidłowo.

    Cytat:

    Muszę to uruchomić. Za dużo kodu mam za sobą aby zrezygnować.

    I tak trzymać! Obawiam się tylko, że czeka Cię jeszcze trochę pracy.
  • #5 9499974
    5657jz
    Poziom 14  
    Okazało sie że miałem uszkodzony procesor. Działa OK.
    Natomiast wyłożyłem sie na pamieci EEPROM 42C04. Poczatkowo zapisywałem,czytałem. Jednak resety czy błedy w transmisji unieruchomiły mi chyba EEproma. W nocie jest:
    MEMORY RESET: After an interruption in protocol, power loss or system reset, any 2-
    wire part can be reset by following these steps:
    1. Clock up to 9 cycles.
    2. Look for SDA high in each cycle while SCL is high.
    3. Create a start condition.

    jednak nie mogę zaskoczyc jak to fizycznie zrobić (możliwe że źle rozumiem ten opis)??? Może to inny bład?

    Wstyd mi prosić o pomoc, ale nie mam wyboru. Proszę.
REKLAMA