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

[ATmega32][GCC]Obsługa USART

loczi 30 Maj 2010 10:51 2448 4
REKLAMA
  • #1 8132676
    loczi
    Poziom 13  
    Witam,
    może mi ktoś powiedzieć co w tym kodzie jest nie tak?

    Kod jest prosty-uczę się USART. Pierwszy znak jaki przyjdzie na RS232 wyświetla się na diodach. (Jedynie, że to jest 0B10000000 to jeszcze kolejny). Tylko, że zawsze mi diody gasną(0xFF). Z komputera nadaje za pomocą programu Hercules.(HyperTerminal wiesza mi komputer lub nie działa)

    #include <avr/io.h>                // dostęp do rejestrów
    #include <avr/interrupt.h>
    #include <avr/delay.h>
    
    #define F_CPU 16000000UL       //częstotliwość zegara w Hz
    #define UART_BAUD   9600         //prędkość transmisji
    #define UART_CONST   (F_CPU/(16ul*UART_BAUD)-1)
    
    	void USART_Transmit( unsigned char data )
    	{
    	while ( !( UCSRA & (1<<UDRE)) );   /* Czekaj na pusty bufor transmisji */
    	UDR = data;                  /* włóż dane do bufora i wyślij je */
    	}
    
    	unsigned char USART_Receive( void )
    	{
    	while ( !(UCSRA & (1<<RXC)) );            /* czekaj na dane do wysłania*/
    	return UDR;                           /*odbierz i zwróć odebrane dane z bufora */
    	}
    
    SIGNAL(SIG_UART_RECV) // podprogram przerwania od USART
    {
    unsigned char data=UDR;
    if (PORTB == 0B10000000) PORTB = data;
    }
    
    int main(void)
    {
    DDRB=0xFF; 
    PORTB=0B10000000;
    
    UBRRH = (unsigned char)(UART_CONST>>8);         /* ustaw prędkość transmisji*/
    UBRRL = (unsigned char)UART_CONST;   
    UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE); //włącz obsługę przerwań USART
    //UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);   /*  8bitów danych, 2bity stopu */
    UCSRC = (1<<URSEL)|(3<<UCSZ0);
    
    
    sei();              // włącz obsługę przerwań
    while(1)
    	{    
    	}         
    } 
    
  • REKLAMA
  • #2 8132744
    sulfur
    Poziom 24  
    SIGNAL(SIG_UART_RECV) // podprogram przerwania od USART 
    { 
    unsigned char data=UDR; 
    if (PORTB == 0B10000000) PORTB = data; 
    }


    Pomijając, że teraz wypadałoby używać ISR, to w powyższym kodzie sprawdzasz, czy PORTB jest równy 128 i tylko wtedy zapisujesz odebraną dane do tego portu (pomijam, czy tak można zrobić i czy wynik jest poprawny). Nic więc dziwnego, że wyświetlanie znaku kończy Ci się na pierwszym odebranym. Ponadto, nie liczyłbym na to, że dużo zobaczysz na diodach przy "szybkiej" transmisji.

    9600 bitów na sekundę przy Twoich ustawieniach 11 bitów na znak (1 bit startu, 8 bitów danych i 2 bity stopu) daje jakieś 872 znaki na sekundę. Calkiem sporo jak na obserwację za pomocą LEDów. Możesz zatem widzieć tylko znak kończący w zależności jaki to będzie, znak nowego wiersza (\n) lub powrót karetki (\r).

    Oczywiście ograniczenie to nie wystąpi, jeśli znaki będą wysyłane po jednym.

    Podsumowując, na początek usuń
    if (PORTB == 0B10000000) 

    z kodu obsługi przerwania odebrania nowego znaku.
  • REKLAMA
  • #3 8132876
    hotdog
    Poziom 26  
    sulfur napisał:
    SIGNAL(SIG_UART_RECV) // podprogram przerwania od USART 
    { 
    unsigned char data=UDR; 
    if (PORTB == 0B10000000) PORTB = data; 
    }


    Pomijając, że teraz wypadałoby używać ISR, to w powyższym kodzie sprawdzasz, czy PORTB jest równy 128 i tylko wtedy zapisujesz odebraną dane do tego portu (pomijam, czy tak można zrobić i czy wynik jest poprawny). Nic więc dziwnego, że wyświetlanie znaku kończy Ci się na pierwszym odebranym. Ponadto, nie liczyłbym na to, że dużo zobaczysz na diodach przy "szybkiej" transmisji.

    9600 bitów na sekundę przy Twoich ustawieniach 11 bitów na znak (1 bit startu, 8 bitów danych i 2 bity stopu) daje jakieś 872 znaki na sekundę. Calkiem sporo jak na obserwację za pomocą LEDów. Możesz zatem widzieć tylko znak kończący w zależności jaki to będzie, znak nowego wiersza (\n) lub powrót karetki (\r).

    Oczywiście ograniczenie to nie wystąpi, jeśli znaki będą wysyłane po jednym.

    Podsumowując, na początek usuń
    if (PORTB == 0B10000000) 

    z kodu obsługi przerwania odebrania nowego znaku.


    Ale przecież kolega napisał, że chce wyświetlić tylko pierwszy znak który przyjdzie.

    Program wygląda dobrze. Sprawdź czy masz poprawnie terminal ustawiony (9600, 1 bit stopu).

    Czy ten sam kod działa Tobie bez przerwań (czy problem nie leży po stronie sprzętu etc)?

    Pozdr
  • REKLAMA
  • #4 8132982
    sulfur
    Poziom 24  
    loczi napisał:
    Pierwszy znak jaki przyjdzie na RS232 wyświetla się na diodach. (Jedynie, że to jest 0B10000000 to jeszcze kolejny). Tylko, że zawsze mi diody gasną(0xFF).


    Moim zdaniem problem polega właśnie na tym, że autor wątku chce wyświetlać znaki które przechodzą przez USART, ale wyświetla się tylko pierwszy odebrany znak, nie licząc konfiguracji portu podczas startu systemu. Drugim problemem jest gaśnięcie LEDów, ale powodu tego bez schematu nie jestem w stanie stwierdzić, przynajmniej ja. Może koledzy potrafią.

    Jeśli jednak mylę się co do problemu postawionego w wątku, to przepraszam za spam.
  • #5 8133070
    loczi
    Poziom 13  
    W ramach wyjaśnień.

    Chcę napisać program który odbierze TYLKO jeden znak po przez USART(jak odbiorę już jeden to myślę, że z większą ilością znaków sobie poradzę).

    Program który umieściłem pobiera z przerwania zawsze 0xFF, niezależnie od tego co wysyłam, czy z znakami końca czy bez.

    Jaki terminal polecacie, może kiedyś coś przestawiło się "samo".

    Układ to "PRO-ATMEGA32" Adatronik

    WOW (po polsku łał :D )

    Zrobiłem, już program, ale jest jedno ale...

    Przy połączeniu z kompem muszę wybrać prędkość 600(gdy w programie mam 9600). Wie ktoś może czemu tak jest?


    Program dla tych co by szukali kiedyś rozwiązanie :)

    /*****************************************************************************************/
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include "Atmega32LCD.c"
    
    
    #define F_CPU 16000000L			// F_CPU = 16MHz
    #define BAUDRATE 9600			// Baudrate = 9600
    #define UBRRVAL	(F_CPU/(16ul*BAUDRATE)-1)
    
    /*****************************************************************************************/
    /* Function prototypes */
    void InitUART( );
    unsigned char ReceiveByte( void );
    void TransmitByte( unsigned char data );
    void TransmitSTRING(char *text);
    
    char ttt[]="tekscik\x0d\x0a";
    
    // http://en.wikipedia.org/wiki/C_syntax#Backslash_escapes
    
    // ***********************************************************
    void opoznienie(int ms)
    	{
    	for (unsigned int i = 0;i<ms;i++)
    		{
    		_delay_ms(1);
    		}
    	}
    /*****************************************************************************************/
    /* Main */ 
    int  main(void)
    	{
    	LCDinit();
    	opoznienie(2);
    	LCD_DISPLAY(LCDdon);
    	LCDclr;
    
    	char bufor[4];
    	sprintf(bufor, "%d", UBRRVAL);
    	LCDtext(bufor);   
    
    	DDRC = 0b11111111; // lub np 0xFF;
    	PORTC = UBRRVAL; 
    
    	InitUART(); 
    	sei();                // włącz obsługę przerwań
    
    	while(1) 
    		{
    		TransmitSTRING( ttt );
    		PORTC ^=_BV(0);
    		_delay_ms(1000);
    		}
    	}
    /*****************************************************************************************/
    /* Przerwania *//* Przerwania *//* Przerwania */
    /* Przerwania */                /* Przerwania */
    /* Przerwania *//* Przerwania *//* Przerwania */
    
    
    SIGNAL (SIG_UART_RECV) 
    	{ 
    	uint8_t data;
    	data = UDR; // read the received data
    	if (data == 'L')
    		PORTC ^=_BV(2);
    	PORTC ^=_BV(3);
    	}
    
    /*****************************************************************************************/
    /* Function *//* Function *//* Function */
    /* Function */              /* Function */
    /* Function *//* Function *//* Function */
    
    
    /***********************************************/
    /* Initialize usart */
    void InitUART() 
    	{
    	UBRRH = (uint8_t)(UBRRVAL >> 8);
    	UBRRL = (uint8_t)UBRRVAL;                   /*  Set the baud rate */
    
    		UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); /* Set frame format: 8data, 2stop bit */
    	//UCSRC = (1 << UCSZ1) | (1 << UCSZ0);/* set to 8 data bits, 1 stop bit {PUTTY} */
    	UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXC); 
    	//UCSRB = (1<<RXEN)|(1<<TXEN);/* Enable receiver and transmitter */
    	}
    
    
    /***********************************************/
    /* Read usart */
    unsigned char ReceiveByte( void )
    	{
    	while ( !(UCSRA &  (_BV(RXC))) );     /*  Wait for incomming data   */
    	return UDR;/* Return the   data */
    	}
    
    /***********************************************/
    /* Write usart */
    void TransmitByte( unsigned char data ) 
    	{
    	while ( !(UCSRA & (_BV(UDRE))) );	/* Wait for empty transmit buffer */
    	UDR =  data;	/* Start transmittion   */
    	}
    
    /***********************************************/
    /* Write usart 2 */
    void TransmitSTRING(char *text) 
    	{
    	while(*text)
    		{
    		while (!( UCSRA & (1<<UDRE)));
    			UDR = *text;
    		text++;
    		}
    	} 
    /*****************************************************************************************/
    
REKLAMA