Para una aplicación que estoy haciendo requería recibir una cantidad de caracteres terminados con un 0x0D (retorno de carro) y 0x0A (nueva línea). El caracter de nueva línea se quedaba pendiente en el buffer RCREG del PIC y además seguían llegando caracteres después de esa cadena.
Una vez que yo recibía la cadena terminada con 0x0D ya no me interesaba qué más llegaba y deshabilitaba la interrupción RS232. Al hacer esto el buffer RCREG guardaba un dato y el registro de desplazamiento superior al RCREG se desbordaba por no vaciar RCREG a tiempo por la llegada de todos los demás caracteres. Esto levantaba la bandera Overrun Error OERR (bit 1 de RCSTA en 0x0FAB) y cancelaba toda recepción posterior de caracteres aún cuando las interrupciones global y rs232 estuvieran habilitadas.
Para lograr una recepción intermitente RS232 en la que a veces uno lee y a veces no, dejo el siguiente código. Solo es necesario bajar el bit CREN Continuous Receive Enable (bit 4 de RCSTA en 0xFAB) y volverlo a levantar para que el bit OERR regrese a su estado normal.
int1 com_completo=false;
////////////////////////////////////////////////////////////////////////////////
//Subrutina de interrupción RS232
#int_rda
void recibe_comando()
{
disable_interrupts(int_rda);
if(kbhit())
{
gets(com_rx); //recibe hasta encontrar 0x0D
delay_ms(2000); //espera a que se manden todos los demás caracteres que ignoraré
com_completo = true;
}
}
////////////////////////////////////////////////////////////////////////////////
...
////////////////////////////////////////////////////////////////////////////////
void main()
{
...
while(1)
{
if(com_completo == true) //ya llegó un comando
{
cmp = strcmp(com_rx, COM_GET); //compara lo recibido con lo esperado
if(cmp == 0x00)
enviar_respuesta_ok();
com_completo = false;
//Vacía buffer de entrada antes de rehabilitar interrupción
while(kbhit())
getc();
//Limpia el bit Overrun Error OERR limpiando el bit CREN de RCSTA
//Útil para cuando se quiere ignorar una cadena RS232
bit_clear(*0x0FAB,4);
//Y lo vuelve a activar
bit_set(*0x0FAB,4);
enable_interrupts(int_rda);
}
}
}
////////////////////////////////////////////////////////////////////////////////
Espero que les sea de utilidad.