AVR USART Comportamiento aleatorio

3

Parece que estoy obteniendo caracteres aleatorios en mi salida de USART con un ATMEGA8

uart.c

#define FOSC 8000000
#define BAUD_RATE 9600
#define UBRR_VALUE (uint16_t)(FOSC/16/BAUD_RATE-1)

#include "uart.h"

volatile u8buf UART_RCV_BUFFER;
FILE uart0_str = FDEV_SETUP_STREAM(UARTSendByte, UARTReceiveByte, _FDEV_SETUP_RW);

ISR(USART_RXC_vect)
{
    //got a byte from USART. add to buffer
    volatile uint8_t data;
    scanf("%c",&data);
    if((UART_BUFFER_WRITE(&UART_RCV_BUFFER, data)==1) || (data=='.'))
    {
        //either buffer full or '.' received
        //stop the UART receiver unit + disable interrupt
        UCSRB &= ~((1<<RXEN) | (1<<RXCIE));
    }
}

ISR(USART_UDRE_vect)
{
    volatile uint8_t data;
    if(UART_BUFFER_READ(&UART_RCV_BUFFER, &data)==1)
    {
        //end of buffer reached. nothing more to transmit
        //disable RX
        UCSRB &= ~((1<<RXEN) | (1<<RXCIE));
        //reset buffer
        UART_BUFFER_INIT(&UART_RCV_BUFFER);
        //enable  RX side
        UCSRB |= ((1<<RXEN) | (1<<RXCIE));
    }
    else printf("%c",&data);
}

void UART_WRITE_STRING(char* str)
{
    //Sending a string without any command
    //disable RX/TX interrupts
    UCSRB &= ~((1<<RXCIE) | (1<<UDRIE));
    printf("%s",str);
    //re-enable RX/TX interrupts
    UCSRB |= (1<<RXCIE) | (1<<UDRIE);
}


void UART_INIT(void)
{
    UBRRH = (uint8_t)(UBRR_VALUE>>8); //set UBRR register
    UBRRL = (uint8_t)UBRR_VALUE;
    UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);//set frame format: asynchronous,8data,1stop,no parity
    UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE) | (1<<UDRIE);

    UART_BUFFER_INIT(&UART_RCV_BUFFER);
    stdin=&uart0_str;
    stdout=&uart0_str;  
}


void UART_BUFFER_INIT(volatile u8buf *buf)
{
    buf->index = 0;
}

uint8_t UART_BUFFER_WRITE(volatile u8buf *buf, volatile uint8_t data)
{
    if(buf->index<UART_RCV_BUF_SIZE)
    {
        buf->index = data;
        buf->index++;
        return 0;
    }
    else return 1;

}

uint8_t UART_BUFFER_READ(volatile u8buf *buf, volatile uint8_t *data)
{
    if(buf->index>0)
    {
        buf->index--;
        *data = buf->buffer[buf->index];
        return 0;
    }
    else return 1;
}

int UARTSendByte(char u8data, FILE *stream)
{
    if(u8data=='\n')
    {
        UARTSendByte('\r',0);
    }
    while(!(UCSRA&(1<<UDRE))){};
    UDR = u8data;
    return 0;
}

int UARTReceiveByte(FILE *stream)
{
    uint8_t data;
    // Wait for byte to be received
    while(!(UCSRA&(1<<RXC))){};
    data=UDR;
    //echo input data
    UARTSendByte(data,stream);
    // Return received data
    return data;
}

main.c

#include "uart.h"
#include "twi.h"



int main (void)
{
    DDRC = 0x01; //set PC0 as output
    PORTC = 0x01; //turn on PC0
    //PD0 = RXD = INPUT
    //PD1 = TXD = OUTPUT
    DDRD = 0x03;

    UART_INIT(); //initialize UART
    sei(); //Enable global interrpts

    //_delay_ms(500);   

    UART_WRITE_STRING("Hello World ! 1:)\n");
    UART_WRITE_STRING("Hello World ! 2:)\n");
    UART_WRITE_STRING("Hello World ! 3:)\n");
    for(;;)
    {

    }
}

Esto en la ejecución debe darme

Hello World ! 1:)
Hello World ! 2:)
Hello World ! 3:)

Pero lo que obtengo es

\n\nHello World ! 1:)
Hello World ! 2:)
Hello World ! 3:)

el número de \ n es aleatorio. A veces no hay ninguno, a veces 1 o 2 o 3. ¿Alguna idea de lo que estoy haciendo mal aquí?

    
pregunta Ankit

1 respuesta

4

Es un buen hábito vaciar el búfer de entrada de serie en su PC antes de comenzar a usarlo para asegurar que el remitente y el receptor estén sincronizados. Un truco útil es no enviar sus datos en bruto, sino encapsularlos en un marco en el que pueda reconocer fácilmente el inicio, el final y la carga útil. Es probable que también desee agregar una suma de comprobación, por lo que simplemente puede verificar si los datos que recibió son los mismos que los que intentó enviar.

Otras preguntas útiles similares:

respondido por el jippie

Lea otras preguntas en las etiquetas