Xbee no responde a tiempo. Gran retraso entre cada transmisión

He preparado una configuración para 2 Xbees, uno conectado a la PC a través de XCTU y el otro conectado con Atmega 168. El software de la terminal enviará 1 y el xbee con Atmega 168 devolverá 1.

El código es el siguiente.

#include<avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>

    unsigned char data; //to store received data from UDR1



//Function To Initialize UART0
// desired baud rate:9600
// char size: 8 bit
// parity: Disabled
void uart0_init(void)
{
 UCSR0B = 0x00; //disable while setting baud rate
 UCSR0A = 0x00;
 UCSR0C = 0x06;
 UBRR0L = 0x06; //set baud rate lo
 UBRR0H = 0x00; //set baud rate hi
 UCSR0B = 0x98;
}


ISR(USART_RX_vect)      // ISR for receive complete interrupt
{
    data = UDR0;  //making copy of data from UDR0 in 'data' variable 
    if(data == 0x31)
    UDR0 = data;                //echo data back to PC

}

//Function To Initialize all The Devices
void init_devices()
{
 cli(); //Clears the global interrupts
 uart0_init(); //Initailize UART0 for serial communiaction
 sei();   //Enables the global interrupts
}

//Main Function
int main(void)
{
    init_devices();
    while(1);
}

Este código funciona bien y el siguiente es el resultado deseado y obtenido...

ingrese la descripción de la imagen aquí

Ahora el problema es cuando quiero obtener la respuesta 3 para una transmisión de 3 desde la PC. Estoy usando avr studio 4 (sí, sé que soy retroactivo) y Atmega 168PA-PU. La configuración para ambos casos es como se muestra en la imagen...

ingrese la descripción de la imagen aquí

Así que copié el programa anterior por completo y simplemente cambié la línea.

ISR(USART_RX_vect)      // ISR for receive complete interrupt
{
    data = UDR0;  //making copy of data from UDR0 in 'data' variable 
    if(data == 0x31)
    UDR0 = data;                //echo data back to PC

}

a lo siguiente

ISR(USART_RX_vect)      // ISR for receive complete interrupt
{
    data = UDR0;  //making copy of data from UDR0 in 'data' variable 
    if(data == 0x33)
    UDR0 = data;                //echo data back to PC

}

Pero el resultado obtenido no está ni cerca de lo que se supone que debe ser. La siguiente imagen debería aclarar.

ingrese la descripción de la imagen aquí

PD: Utilizamos por separado (Atmega 168A-PU y Atmega 168PA-PU) para los dos programas. Puede suceder que haya alguna discrepancia en el oscilador interno. He leído en alguna parte que puede haber una inexactitud de +/- 10%.

¿Otros personajes tienen el problema? por ejemplo, podrías hacer data = UDR0; UDR0 = data;eco de cualquier personaje

Respuestas (2)

Este problema no está relacionado con su software, porque ejecutó el mismo programa en ambos casos, ¿verdad? Así que debe ser hardware. La irregularidad en el segundo caso sugiere que hay algún desajuste en la velocidad de transmisión. Entonces concluyo que el problema definitivamente se debe a los osciladores RC internos que no son precisos como usted mismo mencionó.

Intente usar un oscilador de cuarzo externo. Conéctelo con XTAL1 y XTAL2 con condensadores adecuados. Yo personalmente uso 12MHz con tapas de 22pF. Cambie la configuración del fusible antes de grabar el programa. Intente buscar en Google la calculadora de fusibles avrdude .

Si funciona avisame!!

No estoy 100% seguro de que esto solucione su problema, pero normalmente antes de enviar datos, querrá verificar que el registro de retención del transmisor esté vacío antes de enviar un carácter. Podrías intentar esto:

ISR(USART_RX_vect)      // ISR for receive complete interrupt
{
    data = UDR0;  //making copy of data from UDR0 in 'data' variable 
    if(data == 0x33)
    {
        while(!(UCSR0A & (1 << UDRE0))) // Wait for data register to be empty
            ;
        UDR0 = data;                //echo data back to PC
    }
}

Pero hacer la espera dentro de la interrupción puede hacer que se pierdan los caracteres recibidos. En cambio, normalmente haría algo más como esto:

volatile unsigned char data, got_data;
unsigned char buffered_data;

ISR(USART_RX_vect)      // ISR for receive complete interrupt
{
    data = UDR0;  //making copy of data from UDR0 in 'data' variable 
    got_data = 1;
}

int main(void)
{
    init_devices();
    while (1)
    {
        if (got_data)
        {
            // Ideally you should disable interrupts here
            buffered_data = data;
            got_data = 0;
            // And re-enable interrupts here
            if (buffered_data == 0x33)
            {
                while(!(UCSR0A & (1 << UDRE0))) // Wait for data register to be empty
                    ;
                UDR0 = buffered_data;                //echo data back to PC
            }
       }
    }
}

También acabo de notar su adición sobre el reloj que tiene una inexactitud potencial de +/- 10%, que es un poco grande para comunicaciones confiables. Si bien normalmente apunto a una precisión del 2% cuando uso comunicaciones en serie, debe apuntar a menos del 5%; de lo contrario, puede llegar a la mitad al final de los 10 bits.