Recibiendo por el puerto serie asíncrono

Hola a todos, a ver si podéis echarme una mano con esto, porque me estoy volviendo loco.

Estoy recibiendo datos por el puerto serie asíncrono. Estoy en un pic 18F4620 programando en C del compilador CSS. Durante los últimos días mi rutina funcionaba perfectamente, y sin haber tocado nada de la recepción, ha dejado de funcionar misteriosamente.

Simplemente utilizo la interrupción generada al recibir un dato en el puerto serie, y lo almaceno en un Buffer para tratarlo posteriormente y no perder ningún dato:

Código:
#INT_RDA
void rda_isr ()
{
      Buffer[LlenadoBuffer] = getc();
      LlenadoBuffer++;
}

Mas tarde llamo a la función ExtraeBuffer, que me devuelve el primer elemento del buffer, y desplaza los elementos de este para que se comporte como una cola FIFO:

Código:
int ExtraeBuffer ()  // Es un sistema FIFO
{
   aux = Buffer[0];
   printf("Recibido %x\r\n", Buffer[0]);
   LlenadoBuffer--;
   for (i = 1; i < LlenadoBuffer; i++) 
   {  
      buffer[i] = buffer[i+1];
   }  
   return aux;
}

Pues... ha dejado de funcionar. Ahora cuando le envio un valor por el puerto serie, si pongo un printf dentro de la rutina de interrupcion, leo el valor correcto. Tras almacenarlo en el Buffer e incrementar LlenadoBuffer, si hago printf(Buffer[LlenadoBuffer-1]) sigo leyendo el valor correcto, señal de que se ha almacenado bien en el buffer...

Sin embargo cuando llego a la función ExtraeBuffer, me saca el valor que le da la gana (curiosamente siempre los mismos, eso sí: 30, 5F, 00, 00, 20... y luego parece que se le antoja empezar a guardarlos bien, aunque se me cuelga el sistema y deja de recibir datos tras recibir 3 más). :confused:

Gracias de antemano y perdonad si esto iba en programación en lugar de microcontroladores, que es mi primera vez y no lo tenía del todo claro.
 
Hola,
Necesitariamos que pongas el programa completo, pones en cero las variables en algun momento, por ejemplo LlenadoBuffer.
 
Nada, ya lo solucioné, fue un error de novato por mi parte al declarar el buffer sin asignarle un tamaño máximo, debía estar fastidiándome alguna variable por ahí.

De todos modos sigo teniendo un problema que es bastante extraño. Ahora recibo correctamente, pero de vez en cuando hay un caracter que no llega bien, y siempre pasa en las mismas posiciones.

Si envío un chorro de caracteres muy grande, el de la posición 25 aparece en la posicion 26, y el que aparece en la posicion 25 en su lugar no es el que debería estar en el 2, sino que está mal. Más adelante 38 y 39 también intercambian sus posiciones, aunque esta vez ambos caracteres son los correctos aunque cambiados. En 51 52 53 también aparecen problemas, siendo el 51 erroneo y estando cambiados 52 y 53 entre sí.

Si envio en varias veces chorros más pequeños (de unos 30 caracteres), me encuentro con que falla siempre cada 25, tal y como describí antes el problema entre el 25 y el 26.

El código que recibe sería simplemente:

Esta es la interrupción que recibe, y las funcion extraeBuffer a la que estoy llamando constantemente desde el bucle principal:
Código:
#INT_RDA
void rda_isr ()
{
      if (LlenadoBuffer < TAMANO_BUFFER)
      {
         Buffer[LlenadoBuffer++] = getc();
      }
      else
      {
         printf("Buffer lleno, imposible recibir por USART\r\n");
      }
}

int ExtraeBuffer ()  // Es un sistema FIFO
{
   int8 i;
   aux = Buffer[0];
   printf("Recibido %x\r\n", Buffer[0]);
   LlenadoBuffer--;
   for (i = 0; i < LlenadoBuffer; i++) 
   {  
      buffer[i] = buffer[i+1];
   }  
   return aux;
}

Aquí muestro parte de la función donde analizo lo que se ha recibido, y en el caso de estar recibiendo texto (habiéndose enviado para ello el comando correspondiente), se trabaja con él así:

Código:
void AnalizaBuffer (int CharRecibido)
{

...

// Si no consideramos ASCII extendido, a partir de 7F cualquier caracter recibido será un error
               // salvo 0xCA que inicia la cadena de finalización del envío
               if (CharRecibido == 0xCA)
               {
                  Fase++;
               }
               else if ( (CharRecibido != 0xCA) && (CharRecibido > 0x7F) )
               {
                  Fase = 0;
                  EnviandoTexto = 0;
                  EstoyEjecutandoUnComando = 0;
                  printf("Error al enviar el comando de envio de texto\r\n");
               }
               else
               {
                  TextoRecibido[TamanoTextoRecibido++]=CharRecibido;
               }

...

Y más adelante en el código, le añado un '\n' cuando envío ciertos valores hexadecimales que indican que he acabado de enviar texto, pero bueno eso funciona bien y el problema no está por ahí.

Las declaraciones:
Código:
#define TAMANO_BUFFER 128
#define MAX_TEXTO 100

int buffer[TAMANO_BUFFER];
int8 LlenadoBuffer;
int TextoRecibido [MAX_TEXTO];
int8 TamanoTextoRecibido;

Me está extrañando mucho este comportamiento, siempre en esas posiciones. A ver si alguien puede arrojar un poco de luz al respecto :)
 
Esta es la interrupción que recibe, y las funcion extraeBuffer a la que estoy llamando constantemente desde el bucle principal:

No es muy seguro hacer eso... Por lo menos si no usás algúnos locks para evitar que las dos funciones escriban y lean de "buffer" y "LlenadoBuffer" a la vez...

Estoy casi seguro que eso es el problema...

Un saludo,
Gonzalo
 
Bueno, no se sí el problema será ese o no, pero desde luego tienes razón, no suena nada bien...

¿Cómo hago eso? ¿Hay algo parecido a los semáforos en CSS?
 
Atrás
Arriba