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

[ATmega16][C] - komunikacja Terminal PC-> USART Atmega

piotrg85 02 Lip 2008 10:57 13280 2
REKLAMA
  • #1 5304884
    piotrg85
    Poziom 12  
    Witam,
    Chciałbym się komunikować z uK za pomocą portu COM (RS232). Komunikacja miałaby przebiegać w stronę PC->ATmega16. Do komunikacji ma służyć Terminal. ATmega na podstawie odebranego znaku ASCII, czyli kodu klawisza klawiatury, ma wykonać jakieś zadanie.

    Podłączyłem Atmega16 do PC według schematu:
    [ATmega16][C] - komunikacja Terminal PC-> USART Atmega

    Schemat pokazuje tylko idee podłączenia linii TX i RX. Oczywiście kondesatory 1uF również są podłączone do MAX232 wg. noty katalogowej. Napięcie jest także odpowiednio podane do ATmega i MAX232.

    Do ATmega jest wgrany kod, który ma za zadanie odebrać znak przez USART a następnie wyświetlić go w formie binarnej na porcie A. Do portu A są podpięte diody LED. Dioda świeci, jeśli na danym pinie jest "1".
    Do pinów PC7 i PC6 są podpięte klawisze, które mają zmieniać wartość zmiennej "a". Jeśli zostanie odebrany jakiś znak przez USART, to jest również przepisywany do zmiennej "a".
    Generalnie, na porcie A wyświetlana jest zawsze binarnie wartość zmiennej "a".
    Kod programu:

    
    
    #define F_CPU 16000000UL // rezonator kwarcowy 16 Mhz
    #include <avr/io.h>
    #include <util/delay.h>
    
    
    //deklaracja funkcji użytych w programie 
    
    void ustaw_USART (void);
    
    // zmienne globalne 
    volatile uint8_t a;
    
    
    void ustaw_USART(void)
    	{
    	UBRRH=0;
    	UBRRL=103; // prędkość 9600 błąd 0.2% wg noty katalogowej
    	UCSRB =_BV(RXEN)|_BV(TXEN); // włączenie odbiornika RX i nadajnika TX 
    	UCSRC=_BV(URSEL);
    	UCSRC|=_BV(UCSZ1)|_BV(UCSZ0); // transmisja 8N1
    	}
    
    int main(void)
    {
    DDRA=0xFF; // port A jako wyjście
    DDRC=0x00;// jako wejście 
    
    ustaw_USART ();
    
    a=90;
    	    	
        while(1)
        {
    
    	if(bit_is_clear(PINC,PC7)) // sprawdź czy wciśnięty
    		{
    		_delay_ms(15);
    		if(bit_is_clear(PINC,PC7)) // jeszcze raz sprawdź
    			{
    			a=a+1;
    			while(bit_is_clear(PINC,PC7)){}; // oczekiwanie na zwolnienie przycisku 
    			}
    		}
    
    	if(bit_is_clear(PINC,PC6))
    		{
    		_delay_ms(15);
    		if(bit_is_clear(PINC,PC6))
    			{
    			a=a-1;
    			while(bit_is_clear(PINC,PC6)){}; // oczekiwanie na zwolnienie przycisku
    			}
    		}
    
    	if(bit_is_set(UCSRA,RXC))
    		{
    		a=UDR; // wartość z RX do zmiennej a
    		_delay_ms(15); 
    		}
    	
    	PORTA=~a; 
        }
     
        return 0;
    }
    
    
    



    Korzystam na zmianę z Terminal v1.9b - 20040204 - by Bray++ oraz z Realterm.

    Problem polega na tym, że za każdym razem, gdy wysyłam cyfry od 0 - 9 to zawsze na porcie pojawia się stan 00011111 (1Fh ) Jeśli wysyłam litery, to stan portu nie ulega zmianie. Dlaczego tak się dzieje ? Podejrzewam, że źle odczytuję ramkę. Chyba, że Terminale wysyłają informacje w inny sposób. Oczywiście w Terminalach ustawiłem prędkość 9600, 8 bit danych, 1 bit stopu.
    Myślę, że układ elektryczny jest też poprawny. Po zwarciu nóżek 11-12 na Max232 otrzymuję prawidłowe echo.

    Z góry dzięki za pomoc.

    Pozdrawiam
  • REKLAMA
  • Pomocny post
    #2 5306450
    Korazon
    Poziom 12  
    Po pierwsze - czy ustawiłeś prawidłowo fusebity, aby procesor pracował na zewnętrznym oscylatorze?
    Po drugie - w karcie katalogowej jest informacja, że rejestr UBRRH i UCSRR znajdują się pod tym samym adresem, więc instrukcją
    UCSRC|=_BV(UCSZ1)|_BV(UCSZ0);

    wpisujesz tak naprawdę wartość do rejestru UBRRH! Aby wpisać ilość bitów danych do UCSRC trzeba ustawić dodatkowo bit URSEL podczas wpisywania tej wartości - nie można rozbić tego wpisu na dwie połówki jak w Twoim programie. Czyli
    UCSRC =_BV(URSEL)|_BV(UCSZ1)|_BV(UCSZ0);
  • #3 5306598
    piotrg85
    Poziom 12  
    Witam ponownie :)
    Fusebity mam dobrze ustawione - zawsze tego pilnuję.
    Natomiast z kodem miałeś rację. Należy za jednym razem napisać :
    UCSRC =_BV(URSEL)|_BV(UCSZ1)|_BV(UCSZ0);

    Transmisja PC-> ATmega ruszyła od razu. :D

    Myślałem, że zapis :
    
    UCSRC=_BV(URSEL);
    UCSRC|=_BV(UCSZ1)|_BV(UCSZ0); // transmisja 8N1
    

    będzie równie poprawny. Na początku ustawiam URSEL na "1" a potem używając operatora "|=" dodaję jedynki na UCSZ1 i UCSZ0.
    Widać, taki zapis nie przechodzi:| Swoją drogą, ciekawe dlaczego ? Nigdzie nie zeruję URSEL.

    Dzięki Korazon za pomoc. Klikam zasłużone "Pomógł".
REKLAMA