Autor Tema: Ayuda: Recepción serial sin pérdidas  (Leído 1940 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado THX1138

  • PIC10
  • *
  • Mensajes: 3
Ayuda: Recepción serial sin pérdidas
« en: 12 de Julio de 2007, 18:16:49 »
Hola:

·Estoy trabajando en una aplicación que requiere recibir data en forma serial, procesarla (operaciones XOR), y luego reenviarla. El problema es que en lo posible no debo perder bytes, pero además debo enviar una secuencia de sincronía en forma periódica. El siguiente código es mi intento para hacer lo que necesito:

Código: C
  1. #include <18F252.h>
  2. #fuses HS,NOWDT,NOPROTECT
  3. #use delay(clock=20000000)
  4. #use rs232(baud=9600, parity=N, bits=8, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
  5.  
  6. //DEFINICIONES
  7. #define nop delay_cycles(1)     // nop;
  8.  
  9. //VARIABLES GLOBALES
  10. int1 CTS_MDM = 0;
  11. int sync = 0, fullb = 0;
  12. int data = 0;
  13. int i = 0, j = 0, k = 0;
  14. int inbuff[4],outbuff[4];
  15. int32 ctr = 0;
  16.  
  17. #INT_RDA
  18. void serial_isr()
  19. {
  20.         inbuff[i] = getc();
  21.         i++;
  22.        
  23.         if(i==4)
  24.         {
  25.                 i = 0;
  26.  
  27.                 outbuff[0] = inbuff[0];
  28.                 outbuff[1] = inbuff[1];
  29.                 outbuff[2] = inbuff[2];
  30.                 outbuff[3] = inbuff[3];
  31.  
  32.                 fullb = 1;
  33.         }
  34. }
  35.  
  36. //LAZO PRINCIPAL
  37. void main(void)
  38. {
  39.         //Habilitar interrupciones necesarias
  40.         enable_interrupts(GLOBAL);
  41.         enable_interrupts(INT_RB);
  42.         enable_interrupts(INT_RDA);    
  43.  
  44.         for(i=0;i<4;i++)
  45.         {
  46.                 inbuff[i] = 0;
  47.                 outbuff[i] = 0;
  48.         }
  49.  
  50.         i = 0;
  51.  
  52.         while(1)
  53.         {
  54.                 if(sync == 1)
  55.                 {
  56.                         k++;
  57.  
  58.                         putc(0xFF);
  59.                         putc(0xFF);
  60.                         putc(0x00);                                    
  61.                         putc(k);
  62.  
  63.                         sync = 0;
  64.                 }
  65.  
  66.                 if(fullb == 1)
  67.                 {
  68.                         putc(outbuff[j] ^ 0x20);
  69.                         ctr++;
  70.                         j++;
  71.  
  72.                         if(j==4)
  73.                         {
  74.                                 j = 0;
  75.                                 fullb = 0;
  76.                         }
  77.  
  78.                         if(!(ctr%16))
  79.                                 sync = 1;
  80.                 }
  81.  
  82.         }
  83.  
  84. }

·En el fondo, lo que busco es que si yo envío una cadena de bytes, ej.

Código: ASM
  1. A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A B C D E F G H

el micro reenvíe lo siguiente:

Código: C
  1. a b c d e f g h i j k l m n o p (0xFF) (0xFF) (ctr1) (ctr2) q r s t u v w x y z a b c d e f (0xFF) (0xFF) (ctr1) (ctr2)

*Los últimos 2 bytes (G,H) se almacenan hasta que se llene el buffer de entrada (2 bytes más).

·De momento tengo 2 problemas:

*Cuando trato de simular en MPLAB, el programa corre bien al principio, pero luego deja de transmitir sin motivo aparente (TXREG deja de actualizarse).
*Al armar el circuito, la lógica del buffer de 4 bytes funciona correctamente, pero al enviar la trama de sincronía (cuando recibo 16 bytes), pierdo justamente 4 bytes. Pensé que la USART siendo full dúplex no tendría este problema...

·Si alguien puede ayudarme a resolver el cómo evitar la pérdida de datos a pesar de añadir una trama de sincronía entre medio, le estaré muy agradecido.

Atte.
THX1138

PD: Tengo las versiones 3.249 y 4.038 del compilador CCS.

Desconectado vet2

  • PIC10
  • *
  • Mensajes: 10
Re: Ayuda: Recepción serial sin pérdidas
« Respuesta #1 en: 20 de Julio de 2007, 07:50:53 »
Buenas, creo que parte de tu problema puede estar en que no deshabilitas la interrupción del puerto serie cuando la estas
atendiendo, prueba a deshabilitarla cuando vayas a coger un dato y vuelve a habilitarla cuando lo hayas recogido.

Mas o menos esto:

#int_RDA
RDA_isr(){

   disable_interrupts(int_RDA); //deshabilidatos la interrupcion
   .
   .
   .//recogemos el dato
   .
   .
   enable_interrupts(int_RDA); //habilidatos la interrupcion
}

Saludos.

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Ayuda: Recepción serial sin pérdidas
« Respuesta #2 en: 20 de Julio de 2007, 08:54:05 »
Estoy trabajando en una aplicación que requiere recibir data en forma serial, procesarla (operaciones XOR), y luego reenviarla. El problema es que en lo posible no debo perder bytes, pero además debo enviar una secuencia de sincronía en forma periódica. El siguiente código es mi intento para hacer lo que necesito:
Es posible siempre y cuando no recibas más de lo que puedas transmitir.  Es decir, si no hay 'tiempo' muerto entre los bytes que recibes y los que transmites, a corto o largo plazo se te llenará el buffer.  Supongo por cómo armaste tu código que esto es así.


*Cuando trato de simular en MPLAB, el programa corre bien al principio, pero luego deja de transmitir sin motivo aparente (TXREG deja de actualizarse).
La verdad no se si la función putc verifica que el buffer TXREG esté vacío antes de cargar otro dato, pero 'debiera' verificarlo.  Para disipar dudas, puedes activar un chequeo del bit TRMT antes de enviar un dato.


Al armar el circuito, la lógica del buffer de 4 bytes funciona correctamente, pero al enviar la trama de sincronía (cuando recibo 16 bytes), pierdo justamente 4 bytes. Pensé que la USART siendo full dúplex no tendría este problema...
Y estas en lo cierto, es full duplex pero lo que no es full duplex es tu código.


·Si alguien puede ayudarme a resolver el cómo evitar la pérdida de datos a pesar de añadir una trama de sincronía entre medio, le estaré muy agradecido.

Veo claramente en tu código que cuando envías, puedes sobreescribir tu recepción.  Tampoco haría lo que te aconsejaron de apagar las interrupciones porque no se cumple el objetivo principal que es siempre estar listo para recibir datos, simplemente buscaría una mejor forma de resolver el problema.

Una forma simple es que uses 2 buffers de recepción los cuales los vas conmutando , una vez recibes con uno, y otra vez recibes con otro.
- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado THX1138

  • PIC10
  • *
  • Mensajes: 3
Re: Ayuda: Recepción serial sin pérdidas
« Respuesta #3 en: 24 de Julio de 2007, 16:53:08 »
Hola:

·Gracias por tu consejo; probé creando un segundo buffer, pero aún no puedo solucionarlo; al parecer lo que ocurre es que cuando envío la sincronía sigo recibiendo data, y al llenar el otro buffer me cambia lo que tenía en memoria. Ej:

*Envío:
abcdefghijklmnopqrstuvwxyz

*Recibo:

abcdefghijklmnop#$&*qrwx

e incluso:

abcdefghijklmnop#$&*qrsx

·De esto, deduzco que mientras enviaba la sincronía (#$&*), recibió "qrst" y "uvwx" en cada buffer, pero no alcanzó a vaciar completamente el buffer de salida, y por lo tanto finalmente envió "qrwx" o "qrsx".

·El código que utilicé es el siguiente:

Código: C
  1. #include <18F252.h>
  2. #fuses HS,NOWDT,NOPROTECT
  3. #use delay(clock=20000000)
  4. #use rs232(baud=9600, parity=N, bits=8, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
  5.  
  6. //DEFINICIONES
  7. #define nop delay_cycles(1)     // nop;
  8.  
  9. //VARIABLES GLOBALES
  10.  
  11. int1 sync = 0, fullb = 0;
  12. int i = 0, j = 0, k = 0, b = 1;
  13. int inbuff1[4],inbuff2[4],outbuff[4];
  14. int32 ctr = 0;
  15.  
  16. #INT_RDA
  17. void serial_isr()
  18. {
  19.         if(b==1)
  20.                 inbuff1[i] = getc();
  21.  
  22.         if(b==2)
  23.                 inbuff2[i] = getc();
  24.  
  25.         i++;
  26.        
  27.         if((i>3)&&(b==1))
  28.         {
  29.                 i = 0;
  30.  
  31.                 outbuff[0] = inbuff1[0];
  32.                 outbuff[1] = inbuff1[1];
  33.                 outbuff[2] = inbuff1[2];
  34.                 outbuff[3] = inbuff1[3];
  35.  
  36.                 fullb = 1;
  37.                 b = 2;
  38.         }
  39.  
  40.         if((i>3)&&(b==2))
  41.         {
  42.                 i = 0;
  43.  
  44.                 outbuff[0] = inbuff2[0];
  45.                 outbuff[1] = inbuff2[1];
  46.                 outbuff[2] = inbuff2[2];
  47.                 outbuff[3] = inbuff2[3];
  48.  
  49.                 fullb = 1;
  50.                 b = 1;
  51.         }
  52.  
  53. }
  54.  
  55. //PROTOTIPOS DE FUNCIONES
  56.  
  57. //LAZO PRINCIPAL
  58. void main(void)
  59. {
  60.         //Habilitar interrupciones necesarias
  61.         enable_interrupts(GLOBAL);
  62.         enable_interrupts(INT_RDA);    
  63.  
  64.         while(1)
  65.         {
  66.  
  67.                 nop;
  68.        
  69.                 if(sync)
  70.                 {
  71.                         putc(0x23);
  72.                         putc(0x24);
  73.                         putc(0x26);                                    
  74.                         putc(0x2A);
  75.  
  76.                         //k++;
  77.                         sync = 0;
  78.                 }
  79.  
  80.                 if(fullb)
  81.                 {
  82.                         putc(outbuff[j] ^ 0x00);
  83.                         ctr++;
  84.                         j++;
  85.  
  86.                         if(j==4)
  87.                         {
  88.                                 j = 0;
  89.                                 fullb = 0;
  90.                         }
  91.  
  92.                         if(!(ctr%16))
  93.                                 sync = 1;
  94.                 }
  95.  
  96.         }
  97. }

*Eliminé el XOR con 0x20, para ver con más facilidad si estaba perdiendo data.

·Alguna sugerencia de cómo podría mejorar la rutina, para conseguir el objetivo deseado? De antemano agradezco la ayuda y sugerencias!

Atte.
THX1138

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Ayuda: Recepción serial sin pérdidas
« Respuesta #4 en: 24 de Julio de 2007, 19:55:56 »
THX1138 para serte sincero lo ideal para sugerirte modificaciones sería que me ponga a simular muchas veces tu código para encontrar flaquezas y solucionarlas o mejorarlas , pero como no tengo ese tiempo por ahora, te sigo sugiriendo pistas como para que puedas resolver tu dilema.

¿Qué sucede si aumentas el buffer de salida?

En realidad, tu asumes muchas cosas y yo lo dejaría todo más "libre" aunque para el programa tal vez sea algo más complejo.  Yo tomaría 2 buffers, uno de entrada y uno de salida.  Ambos con un tamaño respetable (o el que te parezca que sea necesario para 'descargar' el input antes de que se llene el output).

En cada buffer tienes 2 punteros o índices que apuntan a el primer byte que estás usando y al ultimo byte importante del buffer.  A esto se lo llama "buffer cíclico". 

1) Cuando los índices apuntan al mismo byte, significa que el buffer está vacío
2) Cuando ingresa un nuevo byte, el byte se ocupará en la posición del indice final y éste se incrementará en 1.  Si el indice final llega al máximo del buffer, toma el valor del 1er elemento del buffer.
3) Cuando un byte pasa a transmisión, se descarga del buffer de recepción incrementandose el puntero de "inicio" del buffer de recepción.

Es la misma operatoria para el buffer de transmisión.

Espero se haya entendido, sino, te sugiero busques sobre buffer cíclicos, realmente es un tema que se pudiera explicar con muuuchos gráficos para detallar bien todo pero no tengo tiempo.

Saludos
- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)


 

anything