Autor Tema: Continuar lectura de trama tras leer "0x00"  (Leído 5127 veces)

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

Desconectado Andres.mza

  • PIC10
  • *
  • Mensajes: 5
Continuar lectura de trama tras leer "0x00"
« en: 01 de Octubre de 2019, 11:08:40 »
Hola a todos! Soy nuevo, por lo que no estoy del todo seguro si el tema va en este subforo, pido disculpas si no es el lugar correcto.

Me encuentro en la tarea de leer una trama desde la interrupcion "RDA_isr" con "fgetc()", la cual contiene caracteres "0x00" (NULL o EOF -end of file-).
El problema parece ser que "fgetc()" solo almacena los caracteres hasta que lee "0x00" dejando la trama a la mitad. Hay alguna forma de que esto no pase?

El problema surge al querer leer una trama que envia un Powermeter con protocolo modbus. Trama de ejemplo: 01 03 00 43 5D 00 1F 3C FD

Uso uC 18F67K22.
El codigo se que funciona, pero tengo ese problema cuando recibo "0x00"

Gracias!
« Última modificación: 01 de Octubre de 2019, 13:21:08 por Andres.mza »

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1297
Re:Continuar lectura de trama tras leer "0x00"
« Respuesta #1 en: 01 de Octubre de 2019, 13:58:55 »
Que tal andres.mza,

Usa getc() en lugar de fgetc(), y si te es posible usa el kbhit() para saber que ha llegado un caracter.

elreypic.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Continuar lectura de trama tras leer "0x00"
« Respuesta #2 en: 01 de Octubre de 2019, 14:58:17 »
Opino que deberia recibir el 0x00 igual con fgetc o getc como quiera usarlo, el unico que reconoceria el 0x00 como final de string es el gets o fgets

¿Estas seguro que es por eso? o es algo de la logica de tu programa?

Desconectado Andres.mza

  • PIC10
  • *
  • Mensajes: 5
Re:Continuar lectura de trama tras leer "0x00"
« Respuesta #3 en: 01 de Octubre de 2019, 16:16:32 »
Usa getc() en lugar de fgetc(), y si te es posible usa el kbhit() para saber que ha llegado un caracter.
elreypic.

Lo intenté, pero no tuvo resultado. Luego vi que en el .h del pic figura lo siguiente:

Código: C
  1. #define getc getch
  2. #define fgetc getch
  3. #define getchar getch

Por lo que entiendo, estaria ejecutando la misma funcion de cualquer forma que lo escriba.

Opino que deberia recibir el 0x00 igual con fgetc o getc como quiera usarlo, el unico que reconoceria el 0x00 como final de string es el gets o fgets

Tambien probé con fgets y gets y de esta forma el programa directamente se cuelga. No se si puedo estar haciendo algo mal :/
Adjunto parte del codigo.
¿Estas seguro que es por eso? o es algo de la logica de tu programa?

La verdad estoy un poco mareado en este punto, he probado decenas posibilidades entre fgetc, getc, fgets, gets, getchar... tambien cambie de "byte" a "char" variable que almacena los datos recibidos de fgetc. Lo unico que logré encontrar al simular una trama con docklight fue que con fgetc() puedo leer la trama y guardarla siempre y cuando no contenga "0x00"

Interrupcion:
Código: C
  1. void RDA2_isr(void) {
  2.     buffer_aux[byte_r2] = fgetc(AUX);
  3.    
  4.     if (buffer_aux[byte_r2] == '>') {
  5.         byte_r2 = 0;
  6.         buffer_aux[byte_r2] = '>';
  7.     }
  8.    
  9.     if(buffer_aux[byte_r2] == '#'){ //caracter de fin de la trama nueva
  10.         sharp_ = 1;
  11.     }
  12.    
  13.     if(buffer_aux[byte_r2] == '<'){ //caracter de fin de la trama nueva
  14.         prompt = 1;
  15.     }
  16.    
  17.     byte_r2++;
  18.  
  19.     if(byte_r2 >= MAX_AUX) {
  20.         byte_r2 = 0;
  21.     }
  22. }

Envio y espero respuesta:
Código: C
  1. byte_r2 = 0;
  2.     memset(buffer_aux, NULL, MAX_AUX);
  3.     fprintf(AUX, "peticion\r\n");
  4.    
  5.     fprintf(AUX, "%c%c%c%c%c%c%c%c",0x01,0x03,0x00,0x0D,0x00,0x02,0x55,0xC8); // Hago la peticion al Powermeter. Envio trama en HEX
  6.     enable_interrupts(INT_RDA2);
  7.    
  8.     while (++cont_err < 3000) //lectura de datos y espera de datos                      
  9.     {
  10.         delay_ms(1);
  11.     }
  12.     disable_interrupts(INT_RDA2);
  13.     fprintf(AUX, "buffer:%s",buffer_aux);    //trama de respuesta

buffer_aux estaba definido como "byte" y lo cambie a "char" pero no obtuve resultados diferentes.

Si desde docklight envio "3E 01 03 00 0D 00 02 55 C8" solo obtengo "3E 01 03"
Pero si envio "3E 01 03 22 0D FF 02 55 C8" recibo "3E 01 03 22 0D FF 02 55 C8" sin problemas

He simplificado el codigo ya que forma parte de un programa mucho mas grande el cual estoy modificando para esta nueva funcionalidad.

Gracias por comentar!
« Última modificación: 01 de Octubre de 2019, 16:25:28 por Andres.mza »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Continuar lectura de trama tras leer "0x00"
« Respuesta #4 en: 01 de Octubre de 2019, 22:23:34 »
¿Sabes que me parece extraño con lo que me contas? Te lo cuento.

El gets o fgets espera un 13 ( 0x0D) que es un Retorno de carro, si o si debe estar al final, sino NO sale de esa funcion, y mas que obvio que esa funcion en una interrupcion NO se debe usar.

Pero estaria bueno probar si con esa funcion recibe o no el 0x00. Podrias enviar: 3E 01 03 00 0D solamente. Y terminarias con un string con sus lugares asi si es correcto: 3E 01 03 00 00

Si no recibis eso, iria a usar el kbhit para saber si llego algo y leer directamente el registro de la UART. Unicamente serviria si usas un solo "stream" es decir que tengas una sola recepcion.

Si aun asi NO recibis el 0x00, y estaria pensando que lo que envia, no estaria enviando el 0x00 correctamente.

Desconectado Andres.mza

  • PIC10
  • *
  • Mensajes: 5
Re:Continuar lectura de trama tras leer "0x00"
« Respuesta #5 en: 02 de Octubre de 2019, 01:21:12 »
Hola de nuevo, de momento no puedo hacer las pruebas pero si puedo adelantar que por desgracia Si utilizo otro stream.

Quizás pueda hacerlo a modo de prueba pero no sería una solución a fin de cuentas.

Mañana actualizo con nueva información

Y de nuevo gracias por contestar!

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:Continuar lectura de trama tras leer "0x00"
« Respuesta #6 en: 02 de Octubre de 2019, 03:15:44 »
¿Sabes que me parece extraño con lo que me contas? Te lo cuento.

El gets o fgets espera un 13 ( 0x0D) que es un Retorno de carro, si o si debe estar al final, sino NO sale de esa funcion, y mas que obvio que esa funcion en una interrupcion NO se debe usar.

Pero estaria bueno probar si con esa funcion recibe o no el 0x00. Podrias enviar: 3E 01 03 00 0D solamente. Y terminarias con un string con sus lugares asi si es correcto: 3E 01 03 00 00

Si no recibis eso, iria a usar el kbhit para saber si llego algo y leer directamente el registro de la UART. Unicamente serviria si usas un solo "stream" es decir que tengas una sola recepcion.

Si aun asi NO recibis el 0x00, y estaria pensando que lo que envia, no estaria enviando el 0x00 correctamente.

Hola Killer.

  Al menos en CCS el gets() finaliza tras recibir null /0. Eso lo aseguro por que tengo muchos programas corriendo así.

  Lo primero que debería de hacer es colocar la línea de datos a un terminal y recibir varias tramas en hexadecimal y ver que efectivamente todas finalizan con NULL .

  Si no es así, yo usaría un while que evalúa que mientras no se reciba “x” (carácter de fin de trama) se reciban byte a byte y vaya cargándolos en una string con buffer suficiente. Así de paso implementa un timeout con kbhit() y ya no se le cuelga el programa esperando caracteres

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Continuar lectura de trama tras leer "0x00"
« Respuesta #7 en: 02 de Octubre de 2019, 08:12:12 »
Al menos en CCS el gets() finaliza tras recibir null /0. Eso lo aseguro por que tengo muchos programas corriendo así.

Segun el manual no es asi, yo tambien creia que era el 0x00 pero no:

Citar
Syntax: gets (string)
            value = fgets (string, stream)
Parameters:
            string is a pointer to an array of characters.
            Stream is a stream identifier (a constant byte)
Returns:
            undefined
Function:
            Reads characters (using getc()) into the string until a RETURN (value 13) is encountered. The string is terminated with a 0. Note that INPUT.C has a more versatile get_string
            function.
            If fgets() is used then the specified stream is used where gets() defaults to STDIN (the last USE RS232).

Completa con un 0x00 a lo recibido para dejarlo como un string, pero para al encontrar el valor 13 o 0x0D lo realiza.

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:Continuar lectura de trama tras leer "0x00"
« Respuesta #8 en: 03 de Octubre de 2019, 03:11:59 »
Al menos en CCS el gets() finaliza tras recibir null /0. Eso lo aseguro por que tengo muchos programas corriendo así.

Segun el manual no es asi, yo tambien creia que era el 0x00 pero no:

Citar
Syntax: gets (string)
            value = fgets (string, stream)
Parameters:
            string is a pointer to an array of characters.
            Stream is a stream identifier (a constant byte)
Returns:
            undefined
Function:
            Reads characters (using getc()) into the string until a RETURN (value 13) is encountered. The string is terminated with a 0. Note that INPUT.C has a more versatile get_string
            function.
            If fgets() is used then the specified stream is used where gets() defaults to STDIN (the last USE RS232).

Completa con un 0x00 a lo recibido para dejarlo como un string, pero para al encontrar el valor 13 o 0x0D lo realiza.

 Pues ahora que lo dices lo revisé y es verdad. Lo que yo tenía en mis códigos que finaliza con 0x00 son los string enviados como punteros.

  Pero las gets es cierto que finalizan con endline.   

  Aún así nunca he sido muy amigo de usar los gets ni fgets por la falta de control que te dejan. A la mínima que haya un frameout u otra cosa se cuelga todo.

   Yo me hago mi while donde espero kbhit durante un tiempo que depende de la naturaleza de lo envío de trama del dispositivo emisor y cargo los bytes manualmente en un buffer. 

Desconectado Andres.mza

  • PIC10
  • *
  • Mensajes: 5
Re:Continuar lectura de trama tras leer "0x00"
« Respuesta #9 en: 03 de Octubre de 2019, 13:42:34 »
Hola gente, he intentado nuevamente con fgets y gets, pero el buffer me lo muestra vacio. No se si lo estoy implementandolo mal.

Código: C
  1. #INT_RDA2
  2.  
  3. void RDA2_isr(void) {
  4.     fgets(buffer_aux,AUX);


  Aún así nunca he sido muy amigo de usar los gets ni fgets por la falta de control que te dejan. A la mínima que haya un frameout u otra cosa se cuelga todo.

   Yo me hago mi while donde espero kbhit durante un tiempo que depende de la naturaleza de lo envío de trama del dispositivo emisor y cargo los bytes manualmente en un buffer. 

Eso seria con fgetc pero en un while?
Como lo podria implementar con kbhit?



[Update]
Incluí input.c y estoy intentando leer con "get_string(10, AUX)" pero se cuegla y no sigue el programa. Tampoco se si esta implementado correctamente.
« Última modificación: 03 de Octubre de 2019, 16:49:30 por Andres.mza »

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:Continuar lectura de trama tras leer "0x00"
« Respuesta #10 en: 03 de Octubre de 2019, 18:25:25 »
Hola gente, he intentado nuevamente con fgets y gets, pero el buffer me lo muestra vacio. No se si lo estoy implementandolo mal.

Código: C
  1. #INT_RDA2
  2.  
  3. void RDA2_isr(void) {
  4.     fgets(buffer_aux,AUX);


  Aún así nunca he sido muy amigo de usar los gets ni fgets por la falta de control que te dejan. A la mínima que haya un frameout u otra cosa se cuelga todo.

   Yo me hago mi while donde espero kbhit durante un tiempo que depende de la naturaleza de lo envío de trama del dispositivo emisor y cargo los bytes manualmente en un buffer. 

Eso seria con fgetc pero en un while?
Como lo podria implementar con kbhit?



[Update]
Incluí input.c y estoy intentando leer con "get_string(10, AUX)" pero se cuegla y no sigue el programa. Tampoco se si esta implementado correctamente.

  Mira, imagina que tus tramas acaban con 0x13. Para Implementar eso haces más o menos así:
Código: C
  1. while(buffer[index] != 0x13) {
  2.  if (kbhit()) {buffer[index+] = getc(); timeout = 0;}
  3.   timeout++; delay_ms(1);
  4.  if (timeout >= 100) break;
  5. }
  Esto básicamente lo que hará será recibir byte a byte y los va sumando al buffer. El bucle termina si se recibe 0x13 o si no se recibe nada en 100 ms.






Desconectado Andres.mza

  • PIC10
  • *
  • Mensajes: 5
Re:Continuar lectura de trama tras leer "0x00"
« Respuesta #11 en: 04 de Octubre de 2019, 10:03:45 »

  Mira, imagina que tus tramas acaban con 0x13. Para Implementar eso haces más o menos así:
Código: C
  1. while(buffer[index] != 0x13) {
  2.  if (kbhit()) {buffer[index+] = getc(); timeout = 0;}
  3.   timeout++; delay_ms(1);
  4.  if (timeout >= 100) break;
  5. }
  Esto básicamente lo que hará será recibir byte a byte y los va sumando al buffer. El bucle termina si se recibe 0x13 o si no se recibe nada en 100 ms.

Hola remi04, hice la prueba pero por alguna razon no se esta almacenando la trama.
Esto es lo que veo desde Docklight:
Código: C
  1. -peticion<CR><LF>
  2.  
  3. -<SOH><ETX><NUL><CR>                                  
  4. -<NUL><STX>UÈ<SOH><ETX><EOT>C_Ïa   //trama enviada 01 03 00 0D 00 02 55 C8 y recibida 01 03 04 43 5F C2 8F CF 61
  5.  
  6. - buffer:<CR><LF>                         //muestro trama recibida: ???(vacio?)

El codigo:
Código: C
  1. fprintf(AUX, "peticion\r\n");
  2. fprintf(AUX, "%c%c%c%c%c%c%c%c",0x01,0x03,0x00,0x0D,0x00,0x02,0x55,0xC8); // Hago la peticion al Powermeter. Envio trama en HEXA
  3. while(buffer_aux[byte_r2] != 0x0A) {
  4.         if (kbhit(AUX)) {buffer_aux[byte_r2++] = fgetc(AUX); timeout = 0;}
  5.             timeout++; delay_ms(1);
  6.         if (timeout >= 100) break;
  7. }
« Última modificación: 04 de Octubre de 2019, 12:39:00 por Andres.mza »


 

anything