Autor Tema: Sobre Ejemplo EX_SISR.C  (Leído 2746 veces)

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

Desconectado Nexting

  • PIC10
  • *
  • Mensajes: 8
Sobre Ejemplo EX_SISR.C
« en: 10 de Febrero de 2018, 02:11:49 »
Cordial Saludo


Solicito comedidamente su colaboración para entender debidamente sobre la manera de capturar una cadena de caracteres con el ejemplo de ccs ex_sisr.c, trato de desarrollar una protocolo propio para una pantalla mini de touchscreen la cual debe cumplir con las siguiente condición:

-El envio y la recepción debe ser en hexadecimal
-

mientras envió el sincronismo por ejemplo 0x45,0x63,0x72 debo recibir este mismo valor como respuesta. En el momento que hago contacto en la pantalla por ejemplo envió 0x26,0x47,0x45 la respuesta debe ser 0x56,0x68,0x74 el pic para esto es un 16f876. No logro interpretar la forma apropiada de recibir estos valores al menos en esta parte del código.
Código: [Seleccionar]
  do {
      delay_ms(10000);  \\ Retardo se ajustara según la necesidad
      printf("\r\nBuffered data => ");\r\n  \\ necesitare estos caracteres como parte de mi programa
      while(bkbhit)\\ necesito prescindir de cualquier intervención de teclado
        putc( bgetc() );\\ obtener la cadena pero en hexadecimal
   } while (TRUE);
}

He visto varias aplicaciones del código y en el tema de captura no logro entender la recepción del buffer en hexadecimal y procesarlo. Se habla también de que el ejemplo se aplica un buffer circular, esto significa que los datos nunca están en la misma posición?. agradezco cualquier guía sobre la forma en que deben tratarse las cadenas hexadecimales. No publique el código completo pues estoy aprendiendo a interpretarlo y no he hecho modificaciones hasta el momento.


Gracias

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Sobre Ejemplo EX_SISR.C
« Respuesta #1 en: 10 de Febrero de 2018, 10:41:32 »
El programa tiene varias partes.

Empecemos por la idea original del programa.
Es realizar un buffer de lectura de la UART, es decir mientras llegue dato que se guarden en el buffer, esto lo hace por 10 segundos, por eso ese delay que tenes en el main.
De alli luego envia todos los datos.

Mientras esta en el delay no puede hacer otra cosa, la unica cosa que puede hacer es alguna interrupcion que lo saque de alli, por eso tenemos la recepcion:

Código: C
  1. #int_rda
  2. void serial_isr() {
  3.    int t;
  4.  
  5.    buffer[next_in]=getc();
  6.    t=next_in;
  7.    next_in=(next_in+1) % BUFFER_SIZE;
  8.    if(next_in==next_out)
  9.      next_in=t;           // Buffer full !!
  10. }

Pensa que "next_in" es el indice donde tiene que ir el dato en el buffer, esto te interesa unicamente para no sobreescribir algo que ya paso.
"next_out" por su parte, es para cuando sacas datos del buffer, te indica desde donde debes empezar, ya que puede ocurrir que no sea desde 0.

Luego revisa si el proximo valor a donde deberia ir el nuevo dato que recibio es el mismo que el que debe sacar, si son iguales no avanza el "next_in"

Ejemplo, tenes 10 valores maximos. next_out es 8, y next_in es 7 apenas comenzas, es decir esta LLENO, ya que si queres sacas tus datos debes sacarlos 8..9..0..1..2..3..4..5..6..7
Si tenemos esos valores, cuando entra a la interrupcion, se da cuenta que:

Código: C
  1. next_in=(next_in+1) % BUFFER_SIZE;

Le da 8, por lo tanto next_in lo vuelve a 7.
Aca esta un posible "problema", ya que si llegan mas datos siempre van a sobreescribir la ultima posicion, en ves de indicarte o tratar de solucionarlo de otra forma. Asi que el tamaño debe ser lo suficientemente grande como para que esto no ocurra.

............

Hasta aca ya recibimos todos los datos.. ahora solo queda enviarlos. Y eso lo hace luego del delay:
Código: C
  1. while(bkbhit)\\ necesito prescindir de cualquier intervención de teclado
  2.         putc( bgetc() );\\ obtener la cadena pero en hexadecimal

bkbhit en realidad no es mas que (next_in!=next_out)
Por lo tanto dice que mientras el buffer tenga algo ejecute lo de adentro, cuando no tenga nada el buffer ( es decir next_in y next_out sean iguales) procedera a no ejecutar mas el putc.

bgetc, es una funcion que define mas arriba. Esta funcion es simple,

Código: C
  1. BYTE bgetc() {
  2.    BYTE c;
  3.  
  4.    while(!bkbhit) ;
  5.    c=buffer[next_out];
  6.    next_out=(next_out+1) % BUFFER_SIZE;
  7.    return(c);
  8. }

La funcion devuelve el valor del buffer a la que apunta next_out, y de paso actualiza next_out para la proxima ves que entre.

Vamos a un ejemplo mas practico

Recepcion:

Empezamos con next_in = next_out = 0
Se recibe 'H','o','l','a'

Nuestro buffer y variables quedarian asi:
buffer[] = {'H','o','l','a',0x00,.....,0x00}    Supongo que se pusieron a 0 todos los valores antes
Next_in = 4                                             Indice 4 es el proximo a actualizar cuando se reciba algo, es decir el 5to elemento.
Next_out = 0

Si no llega nada mas y se procede a enviar quedaria asi:
buffer[] = {'H','o','l','a',0x00,.....,0x00}    Supongo que se pusieron a 0 todos los valores antes
Next_in = 4                                             Indice 4 es el proximo a actualizar cuando se reciba algo, es decir el 5to elemento.
Next_out = 4                                           Sen envio desde 0 hasta 3, al llegar al 4 sale el while y entra nuevamente en el delay

Si llega 'P','e' ahora:

buffer[] = {'H','o','l','a','P','e',0x00,.....,0x00}
Next_in = 6                                             
Next_out = 4

Observaras que no se borra lo anterior, pero al momento de "sacar" del buffer nuestro next_out nos dice que hay que sacar desde el indice 4, hasta que next_out == next_in.
Por eso si se va a enviar o leer, solo se envia 'P','e'.
Ahora si quedando Next_out en 6 tambien.

En resumen es CASI un buffer circular, si no fuera por la parte que sobreescribe cuando esta lleno.
« Última modificación: 10 de Febrero de 2018, 10:45:17 por KILLERJC »

Desconectado Nexting

  • PIC10
  • *
  • Mensajes: 8
Re:Sobre Ejemplo EX_SISR.C
« Respuesta #2 en: 10 de Febrero de 2018, 11:32:32 »
Saludos


KILLERJC... como puedes dormir? ((:-)) ((:-))


Muchas gracias por tu respuesta, demasiado claro ahora si podre tratar de construir algo con base en tu orientaciòn, ademas veo que en el proceso liberas el buffer lo que simplifica el proceso, a ensamblar se ha dicho.

Desconectado Nexting

  • PIC10
  • *
  • Mensajes: 8
Re:Sobre Ejemplo EX_SISR.C
« Respuesta #3 en: 15 de Febrero de 2018, 16:44:37 »
Saludos Cordiales

Sigo en el proceso de adquirir los datos por el puerto serie pero no logro atrapar ni una mosca, se seguro estoy implementando mal la teoría, el código sigue intacto, hice una prueba en Realterm y en proteus con una implementacion no muy valida, y funciona pero obviamente no como se debe.
Código: [Seleccionar]
do {
      delay_ms(1000);  \\ Intervalo a un segundo
      putc(0x45)putc(0x63)&putc(0x72); \\señal de sincronismo presente todo el tiempo
      while(bkbhit) \\ sigue esta linea segun lo que me explico KILLERJC
        if(( bgetc()==(0x26,0x47,0x45))){   \\ esquina superior pantalla táctil
        putc(0x56)&(0x68)&(0x74); respuesta
}

} while (TRUE);
}



aun no he implementado la pantalla táctil física los comandos los envió desde el teraterm y puedo ver el sincronismo trabajando debidamente, en la parte del código del if se cumple y tengo la respuesta requerida sin embargo es como adivinar. No logro hacer la extracción carácter por carácter y son varios los comandos de respuesta que requiero al tocar la pantalla y solo se cumple 1 es la única parte del código que he modificado con excepción de la configuración del rs232 a 9600 baudios y 8 bits. De nuevo mil gracias por cualquier comentario sobre este tema.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Sobre Ejemplo EX_SISR.C
« Respuesta #4 en: 15 de Febrero de 2018, 19:04:27 »
Código: C
  1. putc(0x45)putc(0x63)&putc(0x72); \\

Eso deberia darte error, pero supongamos que estas enviando esos 3 valores es decir 0x45 0x63 y 0x72

El problema es que cada vez que llamas a bgetc() te devuelve siempre 1 valor, no todos.

Es tu deber pedirlo uno por uno y de alli ver si es el correcto. Existen varias formas de hacerlo, tal ves la mas simple es esta:

Código: C
  1. if (bgetc() == 0x26 )
  2. {
  3.      if (bgetc() == 0x47 )
  4.      {
  5.             if (bgetc() == 0x45 )
  6.             {
  7.                       // Aca si hubo la secuencia de 0x26 / 0x47 / 0x45
  8.                       putc(0x56);
  9.                       putc(0x68);
  10.                       putc(0x74);
  11.             }
  12.       }
  13. }

Si usas el codigo anterior, va a ocurrir que si falla el primer if, culpa del while vas a enviar nuevamente todo.

Desconectado Nexting

  • PIC10
  • *
  • Mensajes: 8
Re:Sobre Ejemplo EX_SISR.C
« Respuesta #5 en: 15 de Febrero de 2018, 21:38:33 »
Gracias KILLERJC


He probado el cogido y funciona perfectamente siempre y cuando elimine la linea de sincronismo, ya que se detiene la comunicación al igual si le asigno otra esquina de contacto al táctil, pero debe ser cuestión de jugar con los tiempos de captura. Con tu instrucción se cumple sin ningún problema.De nuevo mil gracias

Desconectado Nexting

  • PIC10
  • *
  • Mensajes: 8
Re:Sobre Ejemplo EX_SISR.C
« Respuesta #6 en: 19 de Febrero de 2018, 03:56:52 »
Hice los cambios propuestos y el codigo ha quedado de la siguiente manera:
Código: [Seleccionar]
#include <16f628A.h>
#fuses XT,nowdt,nolvp,noprotect,nomclr
#use delay(clock=4000000)
#include <string.h>
#use rs232(baud=9600,parity=E,xmit=pin_B2,rcv=pin_B1,bits=8,ERRORS)
#define OUT1  PIN_A2
#define OUT2  PIN_A3
#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
#int_rda
void serial_isr() {
   int t;
   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
}
#define bkbhit (next_in!=next_out)
BYTE bgetc() {
   BYTE c;

     while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}
void main() {

 enable_interrupts(int_rda);
   #if defined(__PCM__)
   enable_interrupts(global);
   #endif
 
do{
 
delay_ms(800);
putc(0x48);    //sincronismo
putc(0x63);    //sincronismo
putc(0X72);    //sincronismo
while(bkbhit)
if (bgetc() == 0x26)    //Trama Inicial
{
if (bgetc() == 0x47)     //Punto de contacto Esquina Superior izquierda debe cambiar segun contacto
{                     
if (bgetc() == 0x45)    //Trama Final
{

putc(0x56);            //Respuesta a trama Inicial
putc(0x68);            //Respuesta a punto de contacto
putc(0x74);            //Respuesta a Trama Final

}
}
}

while(true);
}

   
   
 
   
 
 
 
cambie el pic temporalmente por un accidente con el 876 y esta algo duro de conseguir. para hacer la prueba física ademas se hace necesario agregar mas comandos de contacto, la trama inicial y final de la trama siempre sera la misma en la recepción. solo estoy usando un comando el 0x47 porque al estar dentro del do no me permite cambiarlo. Nuevamente mil gracias por la colaboración.
« Última modificación: 19 de Febrero de 2018, 11:36:05 por Nexting »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Sobre Ejemplo EX_SISR.C
« Respuesta #7 en: 19 de Febrero de 2018, 08:14:21 »
Ahora que lo veo habria que cambiar una cosa mas..

Y es esto:

while(bkbhit)

Primero ponerle las llaves que veo que se las sacaste. Y segundo hay que cambiarlo, ya que vos esperas una respuesta con 3 valores, y ahi entra apenas tiene 1 solo.

Y por favor, identa el codigo, es decir ponele espacios, como en el codigo que te pase, es mas facil de leer que si estuviera todo junto como en tu main.

Desconectado Nexting

  • PIC10
  • *
  • Mensajes: 8
Re:Sobre Ejemplo EX_SISR.C
« Respuesta #8 en: 19 de Febrero de 2018, 11:35:18 »
Gracias KILLERJC

mea culpa, por publicar el código de esa manera ya es un habito, con respecto a las llaves no las he sacado de hecho funciona perfecto
Código: [Seleccionar]
do{
 
delay_ms(800);

putc(0x48);    //sincronismo

putc(0x63);    //sincronismo

putc(0X72);    //sincronismo


while(bkbhit)



if (bgetc() == 0x26)    //Trama Inicial
{


if (bgetc() == 0x47)     //Punto de contacto Esquina Superior izquierda debe cambiar segun contacto
{                     


if (bgetc() == 0x45)    //Trama Final
{


putc(0x56);            //Respuesta a trama Inicial

putc(0x68);            //Respuesta a punto de contacto

putc(0x74);            //Respuesta a Trama Final





                     } 
               }
          }
  }

while(true);

}
talvez es confuso por lo que hay entre el do y el bkbhit los tres sincronismos para verificar la actividad. En la prueba al enviarlos como esta en el codigo la respuesta que tengo es la requerida, si hago el envio por aparte 0x26 o 0x27 o 0X45 no tengo respuesta en el terminal. Hice la prueba fisica y en proteus y en ambos casos se cumple. De nuevo mil gracias.
« Última modificación: 19 de Febrero de 2018, 12:18:39 por Nexting »


 

anything