#include <16f628A.H>
#fuses NOMCLR
#fuses INTRC_IO
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES RESERVED //Used to set the reserved FUSE bits
#use delay (clock=4000000)
#use rs232(baud=9600, xmit=pin_B2, rcv=pin_B1)
#define display_1 PIN_B4
#define display_2 PIN_B5
#define display_3 PIN_B6
#define display_4 PIN_B7
unsigned char trama_serial[5], buffer[5];
int x=0;
char auxiliar;
#int_rda
void rda_isr(void)
{
if ( auxiliar == '\r' || auxiliar == '\n' )
{
x=0; // En caso de recibir un salto de linea o un retorno de carro vuelvo a 0
}
else
{
if ( x < 5 )
{
buffer[x] = auxiliar; // En caso que sea otro tipo de valor procede a guardarlo aca
++x;
if ( x == 5 )
{
unsigned int8 i;
for ( i = 0; i < 5 ; ++i )
{
trama_serial[i] = buffer[i]; // Guardo en trama serial el dato completo, de esa forma no cambia mientras va recibiendo, solo cuando recibio todo
}
}
}
}
}
void main(void)
{
unsigned int8 i;
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while (true)
{
///////////////////////////////////////////////////
//unidad_dis1 = (valor % 10); // Se extraen las unidades.
// decena_dis1 = (valor % 100)/10; // Se extraen las decenas.
////////////////////////////////////////////////////////////////////
for( i = 0; i < 5; ++i)
{
trama_serial[i]-=48;
if (trama_serial[i] > 9 )
{
trama_serial[i] = 0; // Proteccion por si envian cualquier caracter. Esto solo va a poner un 0 cuando no sea un numero
}
}
output_low(Display_4); // Apago el display anterior
output_a(trama_serial[0]); // Pongo el dato mientras estan todos apagados asi no se ve el cambio
output_high(Display_1); // Activo el display
delay_ms(1); // Muestro
output_low(Display_1);
output_a(trama_serial[1]);
output_high(Display_2);
delay_ms(1);
output_low(Display_2);
output_a(trama_serial[3]);
output_high(Display_3);
delay_ms(1);
output_low(Display_3);
output_a(trama_serial[4]);
output_high(Display_4);
delay_ms(1);
}
}
Algo asi ?
En la interrupcion ocurre lo siguiente:
Va guardando hasta que llegaron los 5 caracteres ( 34&32 ), en un array llamado buffer, cuando se completa lo pasa a trama_serial, asi podemos seguir recibiendo y guardando en buffer sin que cambien los valores a medida que se va recibiendo, y solo cambien cuando se recibio por completa la trama.
En caso de llegar mas datos (mas de los 5) que no sea una nueva linea ( \n ) o retorno de carro ( \r ) en la interrupcion simplemente no hace nada (se descartan).
Si llega una nueva linea o retorno de carro procede a poner a
x a 0, para comenzar a recibir de nuevo, de esa forma por mas que escriban 5000 caracteres no va a recibir mas que los 5 primeros.
En el main, procedo a restar 48 a todos los elementos ( incluso el '&' ), lo que hago es que si no esta entre el rango de 0 a 9, pongo un 0, asi si alguien envia esto:
a5&e2 , a la salida del for quedaria : 05002
25&38 , a la salida del for quedaria : 25038 , pero el 0 del & no lo usariamos. ( observa que no uso el indice 2 de trama_serial )
De esa forma me aseguro que si o si sean numeros ( de 0 a 9 ), luego muestro en el display esos numeros. Cambie el orden y lo explique en el comentario, primero apago todo, luego pongo el dato y recien alli enciendo el comun del display, es para que no este ese microsegundo encendido con el anterior valor.
Ahora si quisieras implementar varios tipos de forma de recepcion vemos cuales son y tratamos de crear algo que sirva para todos.