Hoy mismo estaba en la misma posición, y escribí un programa siguiendo las líneas de lo que sugiere Michael Karas en su respuesta, utilizando un búfer circular. Utilicé un PIC18, por lo que es posible que algunos códigos no se compilen, pero muestra la idea claramente y debería ser fácil portar este código a AVR, ...
Declaré algunas variables globales:
#define EUSART_BUFFER_SIZE 2048
char eusart_rx_buffer[EUSART_BUFFER_SIZE]; // the actual buffer, now 2048 bytes long
uint16_t eusart_rx_buffer_rd = 0; // the current read position
uint16_t eusart_rx_buffer_wr = 0; // the current write position
Esto supone que se incluye stdint.h
para el tipo uint16_t
.
La idea es:
- En el ISR, cuando recibimos un byte, almacenémoslo en
eusart_rx_buffer[eusart_rx_buffer_wr]
e incrementemos la posición de escritura.
- Cuando queremos leer los datos, puedes leer desde
eusart_rx_buffer_rd
hasta eusart_rx_buffer_wr
.
Por supuesto, cuando se almacenan más de 2048 bytes al mismo tiempo, el búfer se sobrescribirá y perderá datos. Hay algunos trucos que puedes usar para evitar eso. Puede cambiar EUSART_BUFFER_SIZE
para satisfacer sus necesidades. Un valor más bajo, por supuesto, requiere menos memoria de datos.
Ahora, en mi ISR, tengo:
if (PIR1bits.RCIF) { // EUSART data received
eusart_rx_buffer[eusart_rx_buffer_wr++] = RCREG; // Store the received data
if (eusart_rx_buffer_wr >= EUSART_BUFFER_SIZE) // Increment write pointer
eusart_rx_buffer_wr = 0;
PIR1bits.RCIF = 0; // Clear interrupt flag
}
Por supuesto, en un AVR, este código tendrá un aspecto ligeramente diferente, pero la idea es la misma.
Luego, cuando desee leer los datos, puede hacer algo como:
while (eusart_rx_buffer_rd != eusart_rx_buffer_wr) { // While there's data in the buffer
do_sth(eusart_rx_buffer[eusart_rx_buffer_rd++]); // Do something with it
if (eusart_rx_buffer_rd >= EUSART_BUFFER_SIZE) // Increase read pointer
eusart_rx_buffer_rd = 0;
}
Este código fue escrito para PIC18 usando el compilador XC8, pero la mayoría es estándar C y se puede copiar directamente o portar fácilmente.