Autor Tema: mil vueltas... en una sencilla comunicación serie entre pic  (Leído 8587 veces)

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

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
mil vueltas... en una sencilla comunicación serie entre pic
« en: 16 de Mayo de 2011, 20:24:19 »
Hola foreros!!!!

Dispongo de un 16f88 cuyo programa no lo he hecho yo pero del que sé que se comunica a 38400baudios, 8 bits de datos, 1 bit stop y sin paridad.

Este enviará 4 bytes en hexadecimal y YO debo recibirlos (y cuando logre comunicar) almacenarlos y tratarlos adecuadamente. El PIC de recepción será un 16F877 (más adelante y por otras necesidades quizás migre a 18F).

En cuanto al modo de conectar los micros lo hago "a pelo" uniendo el TX1 con RX2 Y RX1 con TX2.

He consultado el foro y la verdad sobre RS232 hay abundante información. Por mi torpeza o desconocimiento no logro hacer andar el siguiente ejemplo. Por favor ayudenme... necesito avanzar... un poco de luz...

Gracias de antemano, os dejo el código:

Código: [Seleccionar]
#include <16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NOWRT

#use delay(clock=20000000)
#use RS232 (baud=38400, bits=8, parity=N, xmit=PIN_C6, rcv=PIN_C7,INVERT,FORCE_SW)

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                   
#use fast_io(D)                   
#use fast_io(E)                   

#byte PORTA = 0X05
#byte PORTB = 0X06
#byte PORTC = 0X07                     
#byte PORTD = 0X08
#byte PORTE = 0X09


int valor;


#int_rda
void RDA_isr()
{
   
   if(kbhit())
      {
         valor=getc();//recibe el INT y guardalo en la variable valor
      }
   
}

void main()
{
   SET_TRIS_D (0x00);
   
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   valor=0;
   PORTD=0X00;
   delay_ms(300);
   
   while(true)
      {
         delay_ms(100);
       
         if (valor!=0)
         {
         PORTD=0XFF;
         }
         else
         {
         PORTD=0X00;
         }
      }
}

Desconectado pablomanieri

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 639
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #1 en: 16 de Mayo de 2011, 20:46:50 »
Hola, tienes como directiva de compilador #use_fast_IO(C), pero en ningún momento configuras las entradas y salidas, RC6 debería ser salida y RC7 entrada  (para poder usar el USART).
Estás forzando al pic a que trabaje con un USART por software siendo que este posee uno por hardware. Sería mejor que aproveches el hardware.
Esto es lo que tienes:
Código: [Seleccionar]
#use RS232 (baud=38400, bits=8, parity=N, xmit=PIN_C6, rcv=PIN_C7,INVERT,FORCE_SW)
le quitaría FORCE_SW, además de que tienes que verificar si el INVERT está correcto.

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #2 en: 16 de Mayo de 2011, 21:05:23 »
Hola, como menciona pablo, no forces a que trabaje por software, ya que si lo haces asi la comunicacion por software no te genera interrupcion. cambia tu encabezado, solo necesitas poner esto:

#use RS232 (baud=38400, xmit=PIN_C6, rcv=PIN_C7)

y tu comunicacion la estas probando directamente en hardware o lo estas simulando.
"Nada es imposible, no si puedes imaginarlo"

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #3 en: 16 de Mayo de 2011, 21:13:37 »
GRACIAS por responder. Estoy en hora local 2 de la mañana y no podré dormir hasta que comunique...

Bien; lo de no configurar C7 como entrada y C6 como salida ya ha sido un error de bulto: en el main: SET_TRIS_C (0X80);

Lo del INVERT, por lo que tengo entendido debo utilizarlo en la comunicación pic a pic si no existe un adaptador de niveles entre dispositivos, pero por otra parte acabo de ver en el manual los siguiente: " may not be used with the internal UART". El FORCE_SW lo puse porque sino da error al compilar con el INVERT (lo vi en un hilo del foro, quizas entendí mal).

En cuanto lo de trabajar con la uart del PIC, tendría que eliminar el:

 if(kbhit())
{
......
}

de la rutina de atención a la interrupción????
L

Gracias compañeros

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #4 en: 16 de Mayo de 2011, 21:22:26 »
rivale!!!!!!!! ha dado resultado.....

Se me enciende todo el puerto D.... pero ahora si que debo repasar lo del INVERT.... bueno en general la directiva #use rs232()....

Gracias.... en cuanto avance aqui lo pstearé!!!!!!!!!!!!!!!!!

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #5 en: 16 de Mayo de 2011, 21:27:03 »
GRACIAS por responder. Estoy en hora local 2 de la mañana y no podré dormir hasta que comunique...

Bien; lo de no configurar C7 como entrada y C6 como salida ya ha sido un error de bulto: en el main: SET_TRIS_C (0X80);

Lo del INVERT, por lo que tengo entendido debo utilizarlo en la comunicación pic a pic si no existe un adaptador de niveles entre dispositivos, pero por otra parte acabo de ver en el manual los siguiente: " may not be used with the internal UART". El FORCE_SW lo puse porque sino da error al compilar con el INVERT (lo vi en un hilo del foro, quizas entendí mal).

En cuanto lo de trabajar con la uart del PIC, tendría que eliminar el:

 if(kbhit())
{
......
}

de la rutina de atención a la interrupción????
L

Gracias compañeros

Orale, pues aca estare otro rato por si puedo ayudarte para que ya te duermas jeje.

lo del kbhit puedes quitarlo no es necesario en este caso, a menos que tuvieras varios puertos rs232 configurados. lo del adaptador de niveles no tiene que ver con el invert, de hecho en el compiladro dice:

"Invert the polarity of the serial pins ", entonces puede que eso te este dando problemas, prueba compilando el encabezado que te mencione anteriormente, debe compilar bien


#use RS232 (baud=38400, xmit=PIN_C6, rcv=PIN_C7)
"Nada es imposible, no si puedes imaginarlo"

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #6 en: 16 de Mayo de 2011, 21:28:52 »
que bien, entonces ya no hagas caso a mi ultimo post, creo que mientras lo escribia tu enviaste tu respuesta, que bueno que te sirvio
"Nada es imposible, no si puedes imaginarlo"

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #7 en: 18 de Mayo de 2011, 15:05:37 »
Hola picGÉNIOS, porque en estos foros abunda la genialidad, el avance.

Sigo con la comunicación serie e intento recoger los 4 bytes que me manda el dispositivo transmisor. Luego en el "main" deseo visualizarlos.

Para ello creo un array de 4 posiciones y mediante un for recorro las posiciones y guardo el dato. El caso es que no visualizo absolutamente nada en el puerto.
Tengo implementado el siquiente código:

Código: [Seleccionar]
#include <16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NOWRT


#use delay(clock=20000000)
//#use RS232 (baud=38400, bits=8, parity=N, xmit=PIN_C6, rcv=PIN_C7,INVERT,FORCE_SW)
//#use RS232 (baud=38400, xmit=PIN_C6, rcv=PIN_C7)
#use RS232 (baud=38400, bits=8, parity=N, xmit=PIN_C6, rcv=PIN_C7)

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                   
#use fast_io(D)                   
#use fast_io(E)                   

#byte PORTA = 0X05
#byte PORTB = 0X06
#byte PORTC = 0X07                     
#byte PORTD = 0X08
#byte PORTE = 0X09

//int recibebyte;

int valor[4];
int i;
int1 flag;

#int_rda
void RDA_isr()
{
   
   if(kbhit())
      {
      for(i=0;i<4;i++)
      {
         valor[i]=getc();//recibe el INT y guardalo en la variable valor
         flag=1;
         //recibebyte=valor[0];
         delay_ms(200);
      };
      }
   
}

void main()
{
   SET_TRIS_A (0xFF);
   SET_TRIS_B (0x0F);
   SET_TRIS_C (0x80);
   SET_TRIS_D (0X00);
   
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   for(i=0;i<4;i++)
      {
         valor[i]=0;   
      }
   flag=0;
   PORTD=0X00;
   
   delay_ms(300);
   
   while(true)
      {
         delay_ms(100);
         if(flag==1)
         {
         PORTD=valor[0];
         delay_ms(2000);
         PORTD=valor[1];
         delay_ms(2000);
         PORTD=valor[2];
         delay_ms(2000);
         PORTD=valor[3];
         delay_ms(2000);
         }
         flag=0;
       
      }
}

Gracias colegas

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #8 en: 18 de Mayo de 2011, 16:37:40 »
Hola de nuevo, creo que el delay que tienes en tu funcion de interrupcion te podria dar problemas, ya que cuando tienes un delay no funcionan las interrupciones, entonces puede que el siguiente dato intente llegar, pero no lo lee ya que la interrupcion se genera con cada byte que recibe, es decir, va a ir recibiendo de uno en uno, no llegan todos en una solo interrpcion

por ejemplo, en tu rutina de interrupcion puede poner algo asi:

« Última modificación: 18 de Mayo de 2011, 16:41:19 por rivale »
"Nada es imposible, no si puedes imaginarlo"

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #9 en: 18 de Mayo de 2011, 16:40:27 »
sorry, el mensaje anterior no estaba completo, tu codigo de la interrupion quedaria asi:
Código: [Seleccionar]
#int_rda
void RDA_isr()
{
  
   if(kbhit())
      {
         valor[i]=getc();//recibe el INT y guardalo en la variable valor
         i++;
         if(i==4)flag=1;
      }
  
}



espero que se entienda, en cada interrupcion solo lles un caracter, e incrementas tu contador(este debes declararlo como variable global e inicializarlo en cero) y cuando tu contador llegue a 4 entonces ya mandas a que lo saque por el puerto D
« Última modificación: 18 de Mayo de 2011, 16:42:40 por rivale »
"Nada es imposible, no si puedes imaginarlo"

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #10 en: 18 de Mayo de 2011, 16:57:21 »
gracias rivale... ahora mismo me llaman a cenar... lo pruebo y lo pongo :-/ :-/ :-/

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #11 en: 18 de Mayo de 2011, 17:47:18 »
Pruebo con algo parecido a lo que tú me dices, compila bien pero luego sólo visualizo en el puerto una posición del array... creo es el último.

Fijaros dónde está la línea: "lectura=getc();" Pues bien ahí compila y recibo ese byte.

Si la coloco más abajo, dentro del bucle for; no visualizo nada en el puerto D.

Gracias compañeros.

El código:

Código: [Seleccionar]
#include <16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NOWRT


#use delay(clock=20000000)
//#use RS232 (baud=38400, bits=8, parity=N, xmit=PIN_C6, rcv=PIN_C7,INVERT,FORCE_SW)
//#use RS232 (baud=38400, xmit=PIN_C6, rcv=PIN_C7)
#use RS232 (baud=38400, bits=8, parity=N, xmit=PIN_C6, rcv=PIN_C7)

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                   
#use fast_io(D)                   
#use fast_io(E)                   

#byte PORTA = 0X05
#byte PORTB = 0X06
#byte PORTC = 0X07                     
#byte PORTD = 0X08
#byte PORTE = 0X09

int lectura=0;
int valor[4];
int i=0;
int1 flag=0;

#int_rda
void RDA_isr()
{
           
      if(kbhit())
      {
      lectura=getc();
   
      for(i=0;i<4;i++)
      {
        //lectura=getc();
        valor[i]=lectura;
      }
      flag=1;
      lectura=0;
}
}

void main()
{
   SET_TRIS_A (0xFF);
   SET_TRIS_B (0x0F);
   SET_TRIS_C (0x80);
   SET_TRIS_D (0X00);
   /*for(i=0;i<4;i++)
      {
         valor[i]=0;   
      }*/
   flag=0;
   lectura=0x00;
   PORTD=0X00;
   int e=0;
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   delay_ms(300);
   
   while(true)
      {
         delay_ms(100);
         
         if(flag==1)
         {
         PORTD=valor[0];
         delay_ms(1500);
         PORTD=valor[1];
         delay_ms(1500);
         PORTD=valor[2];
         delay_ms(1500);
         delay_ms(1500);
         PORTD=valor[3];
         delay_ms(1500);
         flag=0;
         }
         
       
       
      }
}

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #12 en: 18 de Mayo de 2011, 20:15:42 »
tu error esta en el "for" que tienes dentro de tu interrupcion lo que haces es que cada que entra cuando recibe un dato, y luego entra al for, entonces guarda el dato recibido en los 4 lugares de la variable valor, y esto lo hace cada que llega un dato, por eso es que al final solo ves el ultimo dato que recibes

prueba con esto:



Código: [Seleccionar]
#int_rda
void RDA_isr()
{
           
      if(kbhit())
      {
        lectura=getc();
        valor[i]=lectura;
        i++;
         if(i==4)
         {
              flag=1;
             i=0;
         }
      }
}



prueba copiando esto, de esta forma en cuanto recibas 4 interrupciones, es decir, tus 4 datos, entonces dara la instruccion para que los saques por el puerto. y reinicias tu variable de conteo, entonces puedes volver a recibir otros 4 datos nuevos
"Nada es imposible, no si puedes imaginarlo"

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #13 en: 19 de Mayo de 2011, 13:22:26 »
HELLO world!!!!!

He probado lo que me dices , rivale; y te cuento lo que pasa: visualizo 2 bytes en el puerto. Son distintos por lo que quizás pueda valerme.

Os cuento. Como he dicho en el primer mensaje del post recibo 4 bytes en hexadecimal y el "pic emisor" me dicen que comunica a 38400bps, 8bits de datos, 1 bit stop y sin paridad. Se trata de un driver conectado a una touch screen, resistiva 4 hilos... el fabricante me dice que envía esos 4 bytes correspondientes a las coordenadas x e y de la pulsación: en teoría X X Y Y. Tendré algo en el #use rs232(), mal configurado???. Voy a seguir, a ver si logro recibir los 4 bytes.

El código por ahora está asi:

Código: [Seleccionar]
#include <16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NOWRT
#use delay(clock=20000000)
//#use RS232 (baud=38400, bits=8, parity=N, xmit=PIN_C6, rcv=PIN_C7,INVERT,FORCE_SW)
//#use RS232 (baud=38400, xmit=PIN_C6, rcv=PIN_C7)
#use RS232 (baud=38400, bits=8, xmit=PIN_C6, rcv=PIN_C7)

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)                   
#use fast_io(D)                   
#use fast_io(E)                   

#byte PORTA = 0X05
#byte PORTB = 0X06
#byte PORTC = 0X07                     
#byte PORTD = 0X08
#byte PORTE = 0X09

int lectura=0;
int valor[4];
int i=0;
int1 flag=0;

#int_rda
void RDA_isr()
{
           
      if(kbhit())
      {
        lectura=getc();
        valor[i]=lectura;
        i++;
         if(i==4)
         {
              flag=1;
              i=0;
         }
      }
}

void main()
{
   SET_TRIS_A (0xFF);
   SET_TRIS_B (0x0F);
   SET_TRIS_C (0x80);
   SET_TRIS_D (0X00);
   /*for(i=0;i<4;i++)
      {
         valor[i]=0;   
      }*/
   //flag=0;
   //lectura=0x00;
   PORTD=0X00;
   //int e=0;
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   delay_ms(300);
   
   while(true)
      {
         delay_ms(100);
         
         if(flag==1)
         {
         PORTD=valor[0];
         delay_ms(2000);
         PORTD=0;
         delay_ms(2000);
         PORTD=valor[1];
         delay_ms(2000);
         PORTD=0;
         delay_ms(2000);
         PORTD=valor[2];
         delay_ms(2000);
         PORTD=0;
         delay_ms(2000);
         PORTD=valor[3];
         delay_ms(2000);
         PORTD=0;
         delay_ms(2000);
         flag=0;
         }
         PORTD=0;
         
       
       
      }
}

Saludos cordiales;

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: mil vueltas... en una sencilla comunicación serie entre pic
« Respuesta #14 en: 19 de Mayo de 2011, 13:50:05 »
Hola de nuevo, no le encuentro error a tu programa, me parece que asi deberia funcionar bien, lo que tenog duda es del emisor, podria decir que modelo es, talvez los daots los envia separados por algun caracter, o tiene algun otro detalle que no haz contemplado.

otro detalle que te diria es que quites el delay que tienes despues de habilitar las interrupciones y el de 100ms que tienes dentro del while
"Nada es imposible, no si puedes imaginarlo"


 

anything