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/32][C] - nadawanie-odbiór UART

karolczyzycki 20 Gru 2010 18:27 2923 8
REKLAMA
  • #1 8892982
    karolczyzycki
    Poziom 20  
    Witam,
    Na dwóch ATmegach chciałem zrobić komunikację za pomocą UARTu.
    Miałoby to działać na zasadzie: jeśli ATmega odbierze string (hasło) np.: "1234" to wykona jakieś zadanie
    Kod nadajnika działa prawidłowo, potrafię wysłać string (kod w załączniku)
    Mam problem z kodem odbiornika, kod działa tak że reaguje tylko na znak, nie potrafi odebrać stringa.
    Czy ktoś wie jak to przerobić?

    #include <avr/io.h>
    #include <stdlib.h>
    #include <string.h>
    #include <avr/pgmspace.h>
    #include <util/delay.h>
    #include <avr/interrupt.h> 
    #include <avr/signal.h> 
    #define F_CPU 16000000
    
    #define __CR 0x0a
    #define osc_freq 16 
    
    #define FOSC 16000000// Clock Speed
    #define BAUD 4800
    #define MYUBRR FOSC/16/BAUD-1
    
    void USART_Init( unsigned int ubrr)
    {
    /* Set baud rate */
    UBRRH = (unsigned char)(ubrr>>8);
    UBRRL = (unsigned char)ubrr;
    /* Enable receiver and transmitter */
    UCSRB = (1<<RXEN)|(1<<TXEN);
    /* Set frame format: 8data, 2stop bit */
    UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);
    }
    
    void usart_send( unsigned char data )
    {
    /* Wait for empty transmit buffer */
    while ( !( UCSRA & (1<<UDRE)) )
    ;
    /* Put data into buffer, sends the data */
    UDR = data;
    }
    
    unsigned char USART_Receive( void )
    {
    /* Wait for data to be received */
    while ( !(UCSRA & (1<<RXC)) );
    /* Get and return received data from buffer */
    return UDR;
    }
    
    volatile unsigned char i=0; 
    int main(void){
    DDRD|= (1<<DDD6); // konfiguracja - WYJSCIE ustawianie jedynki 
    sei();
    lcd_init();	
    USART_Init(MYUBRR);
      
    while(1)
    {
    i=USART_Receive();
    
    if (i==47) {
      
    	PORTD|= (1<<PORTD6);   //przypisanie "1" na portD6  
    	}
    else
    	{
    PORTD&= ~(1<<PORTD6);  //przypisanie "0" na portD6   	
    	}			
    		
    }	
     return (0);
    }
  • REKLAMA
  • #2 8893122
    szelus
    Poziom 34  
    Musisz np. odbierane znaki wpisywać do bufora (tablicy) i po odebraniu znacznika końca komendy (np. <CR> czy <LF>) porównywać cały napis.
  • #3 8893226
    karolczyzycki
    Poziom 20  
    No teorię to ja mniej więcej znam... tylko jak to zamienić na kod. Coś takiego?

    #include <avr/io.h>
    #include <stdlib.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
      
    ///////////////////// USART//////////////////////////
    #define FOSC 16000000// Clock Speed
    #define BAUD 4800
    #define MYUBRR FOSC/16/BAUD-1
    ////////////////////////////////////////////////////
    
    int liczba;	 
    char tablica[3]="";
    
    //////////////////////funkcje USART///////////////////////////
    
    void USART_Init( unsigned int ubrr)
    {
    /* Set baud rate */
    UBRRH = (unsigned char)(ubrr>>8);
    UBRRL = (unsigned char)ubrr;
    /* Enable receiver and transmitter */
    UCSRB = (1<<RXEN)|(1<<TXEN);
    /* Set frame format: 8data, 2stop bit */
    UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);
    UCSRB |= _BV(RXCIE);
    }
    
    void usart_send( unsigned char data )
    {
    /* Wait for empty transmit buffer */
    while ( !( UCSRA & (1<<UDRE)) )
    ;
    /* Put data into buffer, sends the data */
    UDR = data;
    }
    
    unsigned char USART_Receive( void )
    {
    /* Wait for data to be received */
    while ( !(UCSRA & (1<<RXC)) );
    /* Get and return received data from buffer */
    return UDR;
    }
    
    
    SIGNAL(SIG_UART_RECV)
    {
    
    	 if (h==57){ 
    		tablica[3]=0;		
    		
    	   }else{  
    		liczba++;
    		tablica[liczba] = h;
    		 }
    	
    }	 	 
    	
    int main(void){
    sei();
    lcd_init();	
    USART_Init(MYUBRR);
    while(1){
    }
    						
            return (0);
    }
    
    
    
  • REKLAMA
  • #4 8895792
    szelus
    Poziom 34  
    Nie musisz koniecznie robić na przerwaniach. W pierwszym przybliżeniu możesz całą obsługę robić w main, np:
    
    #define BUFLEN 16
    #define SEPARATOR '\n'
    char buffer[BUFLEN];
    
    int main()
    {
    ...
        for(;;)
        {
            int i = 0;
            for (;;)
            {
                unsigned char c = UART_Receive();
                if (c != SEPARATOR)
                {
                    buffer[i] = c;
                    if (i < (BUFLEN - 1))
                    {
                        ++i;
                    }
                }
                else
                {
                    buffer[i] = '\0';
                    break;
                }
            }
    
            if (strcmp_P(buffer, PSTR("komenda1")) == 0)
            {
            }
            else if (strcmp_P(buffer, PSTR("komenda2")) == 0)
            {
                ...
            }
    ...
        }
    }
    


    I taka uwaga. Jak deklarujesz tablica[3], to ostatnim elementem, do którego się możesz odwołać jest tablica[2], bo indeksowanie jest od 0. Uważaj na to.
  • REKLAMA
  • #5 8896255
    karolczyzycki
    Poziom 20  
    W którym miejscu mam wstawić jakąś komendę która ma się wykonać po odebraniu poprawnego tekstu?
    Nie rozumiem tego zapisu:
            if (strcmp_P(buffer, PSTR("komenda1")) == 0)
            {
            }
            else if (strcmp_P(buffer, PSTR("komenda2")) == 0)
            {
                ...
            } 
  • #6 8896512
    szelus
    Poziom 34  
    Możesz użyć zwykłego strcmp(), ale zajmie Ci to dodatkowo RAM. strcmp_P() i obsługa napisów/danych w pamięci FLASH jest opisana w manualu do avr libc.
    Wydawało mi się to oczywiste, że obsługa pod if-ami.
  • #7 8896619
    karolczyzycki
    Poziom 20  
    Czyli przykładowo tak?:
    if (strcmp_P(buffer, PSTR("komenda1")) == 0)
    			{
    			PORTD|= (1<<PORTD6);   //przypisanie "1" na portD6  
    			}
              else if (strcmp_P(buffer, PSTR("komenda2")) == 0)
    			{
    			PORTD&= ~(1<<PORTD6);  //przypisanie "0" na portD6   
    			}
  • REKLAMA
REKLAMA