Justo hoy se me ocurrió exactamente en la misma posición, y escribí un programa a lo largo de las líneas de lo que Michael Karas sugiere en su respuesta, el uso de un buffer circular. He utilizado un PIC18, por lo que el código no compila, pero muestra claramente esta idea y debe ser fácil de puerto de este código de AVR, ...
Me declaró que algunas de las 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 stdint.h
se incluye el uint16_t
tipo.
La idea es:
- En el ISR, cuando se recibe un byte, lo almacenamos en
eusart_rx_buffer[eusart_rx_buffer_wr]
y el incremento de la posición de escritura.
- Cuando queremos leer los datos, se puede leer en
eusart_rx_buffer_rd
hasta eusart_rx_buffer_wr
.
Por supuesto, cuando más de 2048 bytes se almacenan en el mismo tiempo, el búfer se sobrescribirán y se perderá los datos. Hay algunos trucos que puede utilizar para evitar que a pesar de. Usted 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.
Entonces, ¿por dónde quieres leer los datos, puedes 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 utilizando el compilador XC8, pero la mayoría de que es el estándar de C y puede ser copiado directamente o portado fácilmente.