Vamos a ver si soy capaz de armar un post que te clarifique los conceptos y no que por el contrario te los embrolle un pocos mas.
He estado mirando tu programa y es un poco-mucho confuso y voy a intentar rehacerlo desde el principio. Vamos a desbrozar primero qué vamos a hacer y después vamos a hacerlo.
Tendremos un buffer de 100 caracteres de largo sobre el que vamos a ir recibiendo, uno a uno, los caracteres transmitidos desde el PC, cuando recibamos el carácter especial 0x0D daremos por concluida la recepción y procederemos a escribir el contenido del buffer en la EEPROM del PIC, colocando el primer carácter en la dirección 0x00 de la misma, el segundo en la 0x01 y así sucesivamente. Una vez concluida la escritura reiniciamos todo y volvemos a empezar.
Vamos a aplicar un principio general que dice : "En una interrupción haz solo lo que tengas que hacer, el resto hazlo fuera de ella". Por ello vamos a construir nuestra interrupción #int_rda con lo mínimo imprescindible para nuestra aplicación y el resto lo colocaremos en el main().
Tendremos entonces tres variables en RAM: El buffer, el índice del mismo donde debe guardarse el siguiente carácter recibido y un flag que indique que ha acabado la recepción y podemos proceder a grabar en la EEPROM.
char rx_buffer[100]; // Buffer de recepción
int8 next_rx=0; // siguiente posición a utilizar
int1 flag_rx_complete=0 // flag que indica recepción completa
Es importante que al inicio tanto next_rx como flag_rx_complete estén inicializados a 0 para que su funcionamiento sea correcto desde el principio.
La rutina de recepción de caracteres queda como sigue:
#int_RDA
RDA_isr(void){
char c;
if(kbhit()){ // Si hay algo pendiente de recibir ...
c=getc(); // lo recogemos sobre la variable c
if(c==0x0D){ // Si lo recibido es el carácter especial de fin ...
flag_rx_complete=1; // marcamos el fin de la recepción y no hacemos nada mas.
}
else{ // En caso contrario ...
rx_buffer[next_rx++]; // lo guardamos en la posición next_rx de rx_buffer e incrementamos next_rx
}
}
}
Llegados a este punto tenemos el buffer con contenido y el flag_rx_complete marcará 1 cuando se reciba el carácter 0x0D. Vamos ahora al main() conde detectamos este estado del flag y hacemos lo que tengamos que hacer con el contenido del buffer.
void main(){
//////////////////////////////////////////////
// Aqui va el bloque de nacionalización del PIC
//////////////////////////////////////////////
while(true){
if(flag_rx_complete==1){ // Si la recepción está completa ...
escribe_buffer_en_EEPROM(); // escribimos el contenido del buffer en la EEPROM y ...
next_rx=0; // ponemos a cero la siguiente posición a utilizar y ...
flag_rx_complete=0 // ponemos a cero el flag que indica recepción completa.
}
}
}
Fíjate que en el momento de llamar a la función escribe_buffer_en_EEPROM(); (que todavía no hemos escrito) el buffer tiene todos los caracteres recibidos antes del último 0x0D y que next_rx tiene el número de caracteres recibidos. Esto es importante ya que es el número que vamos a utilizar para saber cuantos caracteres tenemos que escribir en la EEPROM y que solo
DESPUES de escribirlos pondremos a cero next_rx para comenzar a recoger caracteres recibidos de nuevo desde el principio.
Para escribir la EEPROM vamos a construirnos dos funciones, la que ya hemos llamado escribe_buffer_en_EEPROM(); y otra que denominaremos escribe_byte_en_EEPROM() que escribirá un único carácter en una dirección dada de la EEPROM. Recibirá como parámetros el carácter a escribir y la dirección donde hacerlo y lo único que la diferenciará de la función estandar write_eeprom() del CCS es que la nuestra hará uso de la interrupción #int_EEPROM para saber si es posible escribir ya que en caso contrario debe esperar a que se termine de escribir el anterior carácter.
La función escribe_buffer_en_EEPROM(); recorrerá todo el buffer rx_buffer desde la posición 0 hasta la next_rx menos uno llamando sucesivamente a escribe_byte_en_EEPROM():
void escribe_buffer_en_EEPROM(void){
int8 i;
for(i=0;i< next_rx;i++){
escribe_byte_en_EEPROM(rx_buffer[i],i);
}
}
Para utilizar la interrupción por fin de escritura de la EEPROM lo único que vamos a hacer es utilizar un flag para ponerlo en alto antes de mandar a escribir en la EEPROM y que sea la interrupción quien lo ponga a bajo cuando termine de escribir.
Así en la RAM declararemos:
int1 flag_Writing_INTERNAL_EEPROM;
Y nuestra interrupción de Fin de Escritura de EEPROM será simplemente:
#int_eeprom
void eeprom_isr(void){
flag_Writing_INTERNAL_EEPROM=0;
}
Y por fin la función para escribir un carácter en la EEPROM quedaría de esta forma:
void escribe_byte_en_EEPROM( char data, int8 memAddress){
flag_Writing_INTERNAL_EEPROM=1; // Ponemos en alto el flag de fin de escritura
enable_interrupts(int_eeprom); // Habilita la interrupción de fin de escritura de la EEPROM
write_eeprom (memAddress, data); // Escribe el dato en la dirección indicada
while(flag_Writing_INTERNAL_EEPROM==1){/*Espera hasta finalizar la escritura*/}
disable_interrupts(int_eeprom); // Deshabilita la interrupción de fin de escritura de la EEPROM
}
Y ya tenemos todos los elementos para poder construir nuestro programa. Que apilado todo sería:
char rx_buffer[100]; // Buffer de recepción
int8 next_rx=0; // siguiente posición a utilizar
int1 flag_rx_complete=0 // flag que indica recepción completa
int1 flag_Writing_INTERNAL_EEPROM; // flag que indica fin de escritura de EEPROM
#int_RDA
RDA_isr(void){
char c;
if(kbhit()){ // Si hay algo pendiente de recibir ...
c=getc(); // lo recogemos sobre la variable c
if(c==0x0D){ // Si lo recibido es el carácter especial de fin ...
flag_rx_complete=1; // marcamos el fin de la recepción y no hacemos nada mas.
}
else{ // En caso contrario ...
rx_buffer[next_rx++]; // lo guardamos en la posición next_rx de rx_buffer e incrementamos next_rx
}
}
}
#int_eeprom
void eeprom_isr(void){
flag_Writing_INTERNAL_EEPROM=0;
}
void escribe_byte_en_EEPROM( char data, int8 memAddress){
flag_Writing_INTERNAL_EEPROM=1;
enable_interrupts(int_eeprom);
write_eeprom (memAddress, data);
while(flag_Writing_INTERNAL_EEPROM==1){/*Espera hasta finalizar la escritura*/}
disable_interrupts(int_eeprom);
}
void escribe_buffer_en_EEPROM(void){
int8 i;
for(i=0;i< next_rx;i++){
escribe_byte_en_EEPROM(rx_buffer[i],i);
}
}
void main(){
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(true){
if(flag_rx_complete==1){ // Si la recepción está completa ...
escribe_buffer_en_EEPROM(); // escribimos el contenido del buffer en la EEPROM y ...
next_rx=0; // ponemos a cero la siguiente posición a utilizar y ...
flag_rx_complete=0 // ponemos a cero el flag que indica recepción completa.
}
}
}
Ponle lo específico de tu PIC y debería funcionarte todo.
Nota: He escrito todo el código C de cabeza sin compilarlo por lo que puede tener errores de sintaxis.