TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: daltonico82 en 16 de Mayo de 2011, 20:24:19

Título: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 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;
         }
      }
}
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: pablomanieri 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.
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale 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.
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 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
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 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é!!!!!!!!!!!!!!!!!
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale 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)
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale 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
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 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
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale 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:

Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale 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
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 18 de Mayo de 2011, 16:57:21
gracias rivale... ahora mismo me llaman a cenar... lo pruebo y lo pongo :-/ :-/ :-/
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 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;
         }
         
       
       
      }
}
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale 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
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 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;
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale 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
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 20 de Mayo de 2011, 13:34:49
Hola, he borrado los delay que me dices y he comprobado que los bytes que visualizo en el puerto son el corrspondiente a valor[0], valor[2]. Creo que con eso será suficiente para poner a trabajar la aplicación.... pero me mosquea pues el fabricante del driver me dice:

                   
    " Tanto los comandos como los datos se transfieren entre el controlador y el host a nivel de bytes en hexadecimal, lo que permite una comunicación serie más ágil y rápida.
Una vez conectado el sistema conviene esperar unos 50ms para que el controlador realice sus ajustes internos. Cada vez que se toca el Touch Screen el controlador transmite 2 bytes para la coordenada X y otros 2 para la coordenada Y. La coordenada X representa en hexadecimal, la posición horizontal y la coordenada Y la posición vertical en pantalla...."


Un saludo :-/ :-/ :-/
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: pablomanieri en 20 de Mayo de 2011, 14:54:59
Hola, prueba de comparar en la interrupción si el flag ya se puso en 0, tal vez estés mostrando los valores en el puerto D y aun no terminas y te vuelve a entrar en la interrupción. Es decir, que te asegures que has procesado todos los datos y recién ahí has caso a lo que recibes del touch. Porque como tienes unos delay de 2000ms, seguro que vuelve a entrar a la interrupción antes de que termines el ciclo de programa.
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 20 de Mayo de 2011, 15:03:25
pues si esta raro que haga eso, pero al parecer si se comunica, para asegurarte de que este recibiendo bien, porque no pruebas conectar tu touch con un cable serial a la computadora, y usas un hiperterminal para ver que esta enviando realmente, asi aseguras saber que recibes y despues checas que el pic reciba lo mismo.
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 20 de Mayo de 2011, 15:32:19
Interesantes consejos... Los pruebo!!!! y cuento :shock: :shock: :shock:
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 21 de Mayo de 2011, 07:29:33
OK AMIGOS!!!! buenos consejos.... he chequeado si el "flag==0" antes de realizar otra lectura y probe la conexión con el hiperterminal y sólo recibo 2bytes. Lo justo!!!! un byte referente a la coordenada X (posición horizontal en pantalla) y otro byte referente a la coordenada Y (posición vertical en pantalla).

Ahora me dispongo a hacer un pequeño programa que testée los datos que llegan a través de la UART para activar y desactivar salidas, a modo interruptor.

Un saludo y muchas gracias. Sus consejos me han ayudado a avanzar y como siempre en este foro a avanzar aprendiendo que es lo mejor!!!
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 25 de Mayo de 2011, 13:43:37
hOLA de nuevo!!!!

Aqui dejo un pequeño programa mediante el cuál activo las salidas asociadas al puerto D durante 1 segundo cuando pulso en una zona determinada del touch screen...

Este es el aperitivo a un programa que activará y desactivará salidas a modo interruptor. La base será la aquí mostrada: conocer los bytes que nos da el controlador al pulsar en cada una de las zonas y activar la salida correspondiente

Saludos picmaniacos!!!!

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)

#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 SX1=0X2B;//coordenadas max y min: X
int SX2=0X61;

int S0Y1=0X26;//coordenadas max y min: y
int S0Y2=0x3C;

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()
{
   delay_ms(50);
   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);
       // valor[0]=(valor[0])&&(0xF0);
         if(flag==1)
         {
     
         
         if (valor[2]<(SX2))//las X
         {
         if (valor[2]>(SX1))
         {
         if (valor[0]<S0Y2)//las Y
         {
         if (valor[0]>S0Y1)
         {
       
         PORTD=0XFF;
         delay_ms(1000);
         PORTD=0X00;
         flag=0;
         }
         }
         }
         }
       
         }
        // PORTD=0;
         
       
       
      }
}
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 26 de Mayo de 2011, 00:36:03
muy bien!, que bueno que ya puedes leer los datos, solo una duda, si dices que ya confirmaste que tu touch te envia solamente 2 datos, porque en tu funcion de la interrupcion por rs232 no cambias para que "flag" se haga 1 cuando recibes 2 datos en lugar de 4
}
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 31 de Mayo de 2011, 15:49:11
Hola!!!

Así tengo el programa. Ya recibo los datos y soy capaz de conseguir un ofecto interrupor al tocar  el panel táctil (3 teclas).

Ahora me dispongo a comunicar en rs232 pero enviando datos e intentar emitir un "beep" cada vez que se realice una pulsación válida.

Estamos en contacto. Iré poniendo los avances.

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)
//#use RS232 (baud=38400, 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

#bit D0=PORTD.0
#bit D1=PORTD.1
#bit D2=PORTD.2

const int SX1=0X2B;//coordenadas max y min: X
const int SX2=0X61;

const int S0Y1=0X26;//coordenadas max y min: Y_TECLA S0
const int S0Y2=0x3C;

const int S1Y1=0X40;//coordenadas max y min: Y_TECLA S1
const int S1Y2=0x59;

const int S2Y1=0X5B;//coordenadas max y min: Y_TECLA S2
const int S2Y2=0x73;

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

#int_rda

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

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


void main()
{
   
   delay_ms(50);//incialización controlador
   SET_TRIS_A (0xFF);
   SET_TRIS_B (0x00);
   SET_TRIS_C (0x80);
   SET_TRIS_D (0X00);
 
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_psp(PSP_DISABLED);
   /*for(i=0;i<4;i++)
      {
         valor[i]=0;   
      }*/
   //flag=0;
   //lectura=0x00;
   PORTD=0X00;
   PORTB=0X00;
   
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   
   
    while(true)
    {
         if(flag==1)
      {   
     
     delay_ms(50);
         flag=0;
         
         if((valor[2]<(SX2))&&(valor[2]>(SX1)))//las X; las 3 teclas en este caso están alineadas verticalmente==>mismas coordenadas X
         {
            Xok=1;
         }
         
         if ((Xok==1)&&(valor[0]<S0Y2)&&(valor[0]>S0Y1))
         {
         Xok=0;
         output_toggle(PIN_D0);
         }
         
         if ((Xok==1)&&(valor[0]<S1Y2)&&(valor[0]>S1Y1))
         {
         Xok=0;
         output_toggle(PIN_D1);
         }
   
         if ((Xok==1)&&(valor[0]<S2Y2)&&(valor[0]>S2Y1))
         {
         Xok=0;
         output_toggle(PIN_D2);
         }

         
   
      }//flag==1
     
   
}//while(1)
}//main()

Saludos :-/ :-/ :-/
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 31 de Mayo de 2011, 15:54:39
muy bien, que bueno que ya quedo, ire siguiendo tus post a ver como va tu proyecto.
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 31 de Mayo de 2011, 17:17:56
Hola; una aclaración que necesito antes de seguir: mi proyecto se divide en un mando, donde estará la "touch screen" y dónde albergaré el controlador y un PIC16F877 (1)que recoge los datos de la pulsación (lo que tengo hasta el momento) comunicando estos por RS232 y una placa remota dónde estará otro PIC16F877 (2) que comunicará bidireccionalmente en RS232 con el primer PIC.

La pregunta es la siguiente: El PIC16F877 (1) comunica tanto con el controlador (lee) y con el otro PIC (transmite y lee) por RS232. ¿Esto me lleva necesariamente a utilizar para una comunicación la UART y para la otra establecer una comunicación serie por soft???. ¿Cuál emplearíais para el controlador y cuál para comunicar con el PIC16F877 (2) que estará más lejos???

Gracias, debo aclarar ciertas cosas para no pisar sobre falso.

Saludos
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 31 de Mayo de 2011, 17:27:12
lo que te recomiendo es usar comunicacion I2c, con esta puedes conectar varios dispositivos con solo 2 pines.

pero si necesitas usar las los con rs232 te recomiendo que uses por hardware en la que vas a leer unicamente, para que en cualquier momento puedas recibir los datos por interrupcion.

Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 02 de Junio de 2011, 13:51:08
Hola!!!!

En principio voy hacer las comunicaciones por RS232.

Entonces; el PIC1 ( el que está escuchando al controlador) recibe los datos de este por la USART y se producirá una interrupción. A su vez transmite y recibe del PIC2 utilizando la rs232 por software.

Voy a elavorar un programa pero es correcto esto para configurar ambas comunicaciones serie:

#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)
#use RS232 (baud=9600, xmit=PIN_C4, rcv=PIN_C5, FORCE_SW)

GraciaS
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: Suky en 02 de Junio de 2011, 13:53:30
Podrías aprovechar la interrupción externa por flanco descendente para detectar cuando se recibe un dato desde el otro microcontralador en la comunicación serial por software  ;-)


Saludos!
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 02 de Junio de 2011, 16:01:12
buena idea la de suky, asi tendiras interrupcion para recibir datos de los 2 dispositivos. puedes configurar asi tus modulos rs232


Código: [Seleccionar]
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,stream=p1)//se configura el puerto rs232 por hardware, el comando "stream" sirve para dar un nombre al puerto
#use rs232(baud=9600,xmit=PIN_b1,rcv=PIN_b0,stream=p2)//se configura el puerto rs232 por software
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 02 de Junio de 2011, 18:45:24
OK rivale...

El controlador envía a 38400 bps y tengo en el PIC que recibe de este un cuarzo de 20MHz. La otra comunicación, la que yo establezco entre "mis PIC"  deseo sea a 9600 bps poniendo en el segundo PIC un cristal de 8MHz.

¿Es posible, verdad?:

#use rs232(baud=38400,xmit=PIN_C6,rcv=PIN_C7,stream=p1)//se configura el puerto rs232 por hardware, el comando "stream" sirve para dar un nombre al puerto
#use rs232(baud=9600,xmit=PIN_b1,rcv=PIN_b0,stream=p2)//se configura el puerto rs232 por software

En la confuguración por soft no debo incluir FORCE_SW???

Saludos amigos :-/ :-/

Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: Suky en 02 de Junio de 2011, 18:46:51
Como los pines seleccionados no corresponden al modulo, se considera que es por software, así que no seria necesario  ;-)


Saludos!
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 02 de Junio de 2011, 18:52:08
Bien, entendido el "FORCE_SW" fuerza a trabajar a la UART, a sus pines asociados, por software y no salta  la rutina de atención a la interrupción sino que en el main pregunaríamos por :

 if(kbhit())
      {
       }...

Lo de las distintas velocidades es factible y funcionará????

Mañana me pongo pilas e intento lograr un program.

Gracias Suky!!!!! Gracias Foro!!!!
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: Suky en 02 de Junio de 2011, 19:15:17
Si, o sea, por hardware (utilizando el módulo) y dependiendo del cristal externo podes obtener grandes velocidades. Ahora cuando se utiliza por software lo mejor es una velocidad no muy alta, pero 9600 es adecuada.

El tema de kbhit() es distinto según se utilice por hardware o por software. Por hardware indica cuando a legado un byte, por software cuando se recibe el bit start.


Saludos!
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 02 de Junio de 2011, 19:23:24
si, puedes poner las velocidades que quieras, solo era un ejemplo lo que te envie, en hardaware puedes ponerle 115200 si quieres.


el kbhit no lo necesitas para la interrupcion por recepcion de datos. para saber si hay datos por el otro modulo(el de soft) ahi si tendrias que checar cuando recibes datos.

tambien puedes usar la interrupcion externa para checar si recibes datos por el puerto de software, en cuanto recibas el dato te genera una interrupcion, puedes apagar la interrupcion despues de recibir el bit de inicio y hasta que acabes de recibir los datos la vuelves a prender para que no te genere una interrupcion cada pulso del dato recibido
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 03 de Junio de 2011, 13:42:01
Hello WORLD!!!

He confeccionado como inicio un programa que recoge los datos del controlador (PIC1), los gestiona y envía al PIC2 un dato (un número en hexadecimal). En el PIC2 se recibe este dato y cambia el estado del puerto D. No lo he probado todabía, sólo dispongo de un PIC y hasta mañana no tengo el otro. Si veis algo raro, espero sugerencias

Saludos!!!

PIC1

Código: [Seleccionar]
#include <16f877.h> //PROGRAM PIC1
#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,STREAM=P1)
#use RS232 (baud=9600, xmit=PIN_B1, rcv=PIN_B0,STREAM=P2 )

#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

#bit D0=PORTD.0
#bit D1=PORTD.1
#bit D2=PORTD.2

#PRIORITY RDA, EXT


const int SX1=0X2B;//coordenadas max y min: X
const int SX2=0X61;

const int S0Y1=0X26;//coordenadas max y min: Y_TECLA S0
const int S0Y2=0x3C;

const int S1Y1=0X40;//coordenadas max y min: Y_TECLA S1
const int S1Y2=0x59;

const int S2Y1=0X5B;//coordenadas max y min: Y_TECLA S2
const int S2Y2=0x73;

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

#int_RDA // recepción datos del controlador

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


#INT_EXT //recepción datos PIC2
ext_isr()
{
//POR HACER
}

void main()
{
   
   delay_ms(50);//incialización controlador
   SET_TRIS_A (0xFF);
   SET_TRIS_B (0x01);//b0->in, b1->out
   SET_TRIS_C (0x80);//c6->out, c7->in
   SET_TRIS_D (0X00);
 
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_psp(PSP_DISABLED);
 
   PORTD=0X00;
   int dato=0x00;

   enable_interrupts(INT_RDA);//INTERRUPCIÓN USART
   enable_interrupts (INT_EXT);//INTERRUPCIÓN EXTERNA (EN RB0)
   ext_int_edge (H_TO_L);
   enable_interrupts(GLOBAL);
   
   
    while(true)
    {
         if(flag==1)
      {   
     
     delay_ms(50);
         flag=0;
         
         if((valor[2]<(SX2))&&(valor[2]>(SX1)))//las X; las 3 teclas en este caso están alineadas verticalmente==>mismas coordenadas X
         {
            Xok=1;
         }
         
         if ((Xok==1)&&(valor[0]<S0Y2)&&(valor[0]>S0Y1))
         {
         Xok=0;
         dato=0x01;
         putc(dato);
         }
         
         if ((Xok==1)&&(valor[0]<S1Y2)&&(valor[0]>S1Y1))
         {
         Xok=0;
         dato=0x02;
         putc(dato);
         }
   
         if ((Xok==1)&&(valor[0]<S2Y2)&&(valor[0]>S2Y1))
         {
         Xok=0;
         dato=0x04;
         putc(dato);
         }

         
   
      }//flag==1
     
   
}//while(1)
}//main()

PIC2:
Código: [Seleccionar]
#include <16f877.h> //PROGRAM PIC2
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NOWRT
#use delay(clock=8000000)
#use RS232 (baud=9600, 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

#bit D0=PORTD.0
#bit D1=PORTD.1
#bit D2=PORTD.2

int lectura=0X00;
int valor=0X00;
int1 flag=0;

#int_RDA // recepción datos del PIC1

void RDA_isr()
{
           
        lectura=getc();
        valor=lectura;
        flag=1;     
}

void main()
{
   
   delay_ms(50);//incialización controlador
   SET_TRIS_A (0xFF);
   SET_TRIS_B (0x00);
   SET_TRIS_C (0x80);//c6->out, c7->in
   SET_TRIS_D (0X00);
 
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_psp(PSP_DISABLED);
 
   PORTD=0X00;
   
   enable_interrupts(INT_RDA);//INTERRUPCIÓN USART
   enable_interrupts(GLOBAL);
   
   
    while(true)
    {
         if(flag==1)
      {   
     
         delay_ms(50);
         flag=0;
         PORTD=lectura;

      }//flag==1
     
   
}//while(1)
}//main()
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: Suky en 03 de Junio de 2011, 13:49:17

tambien puedes usar la interrupcion externa para checar si recibes datos por el puerto de software, en cuanto recibas el dato te genera una interrupcion, puedes apagar la interrupcion despues de recibir el bit de inicio y hasta que acabes de recibir los datos la vuelves a prender para que no te genere una interrupcion cada pulso del dato recibido

En realidad no es necesario apagar la interrupción, ya que dentro de la ISR se trabaja con fgetc() la cual recibirá todo el dato y luego se saldrá de la interrupción borrando la bandera.

@daltonico82, en el microcontrolador que tienes 2 canales de comunicación serial, debes utilizar las funciones fputc y fgetc para indicar mediante el stream sobre cual trabajar.


Saludos!
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 03 de Junio de 2011, 13:58:01
fputc(0x00, p1);  algo asi tienes que poner para escribir, primero pones el dato que vas a enviar, y luego pones por que puerto lo quieres enviar. usando los nombres que le pusiste

#use RS232 (baud=38400, bits=8, parity=N, xmit=PIN_C6, rcv=PIN_C7,STREAM=P1)
#use RS232 (baud=9600, xmit=PIN_B1, rcv=PIN_B0,STREAM=P2)



de igual manera para leer le pones

lectura = fgetc(STREAM)
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 09 de Junio de 2011, 17:54:50
Hola!!!!

Mucho trabajo esta semana :5] :5] :5], por fin hoy pude probar la comunicación. Os cuento:

Correcta la comuncación entre controlador y PIC1 (rececpción de datos  en PIC1 hard-rs232)
Correcta la comunicación entre PIC1 y PIC2 (envío de datos desde PIC1 a PIC2; PIC1 soft-rs232, PIC2 hard-rs232)


 :oops:No funciona comunicación entre PIC2 Y PIC1 (envío de datos desde PIC2 A PIC1).

Dejo código; yo ahora mismo sigo por aca probando!!!
Saludos :-/ :-/ :-/

Código: [Seleccionar]
#include <16f877.h> //PROGRAM PIC1
#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,STREAM=P1)
#use RS232 (baud=9600, xmit=PIN_B1, rcv=PIN_B0,STREAM=P2 )

#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

#bit D0=PORTD.0
#bit D1=PORTD.1
#bit D2=PORTD.2
#bit D6=PORTD.6
#bit D7=PORTD.7

#PRIORITY RDA, EXT


const int SX1=0X2B;//coordenadas max y min: X
const int SX2=0X61;

const int S0Y1=0X26;//coordenadas max y min: Y_TECLA S0
const int S0Y2=0x3C;

const int S1Y1=0X40;//coordenadas max y min: Y_TECLA S1
const int S1Y2=0x59;

const int S2Y1=0X5B;//coordenadas max y min: Y_TECLA S2
const int S2Y2=0x73;

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

#int_RDA // recepción datos del controlador

void RDA_isr()
{
           
        lectura=fgetc(P1);
        valor[i]=lectura;
        i++;
         if(i==4)
         {
              flag=1;
              i=0;
         }
     
}


#int_EXT //recepción datos PIC2
ext_isr()
{
      signal=fgetc(P2);

      if (signal==0)
      {
      output_toggle(pin_D6);
      }

      if (signal==1)
      {
      output_toggle(pin_D7);
      }
}


void main()
{
   
   delay_ms(50);//incialización controlador
   SET_TRIS_A (0xFF);
   SET_TRIS_B (0x01);//b0->in, b1->out
   SET_TRIS_C (0x80);//c6->out, c7->in
   SET_TRIS_D (0X00);
 
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_psp(PSP_DISABLED);
 
   PORTD=0X00;
   int dato=0;

   enable_interrupts(INT_RDA);//INTERRUPCIÓN USART
   enable_interrupts (INT_EXT);//INTERRUPCIÓN EXTERNA (EN RB0)
   ext_int_edge (H_TO_L);
   enable_interrupts(GLOBAL);
   
   
    while(true)
    {
         if(flag==1)
      {   
     
     delay_ms(50);
         flag=0;
         
         if((valor[2]<(SX2))&&(valor[2]>(SX1)))//las X; las 3 teclas en este caso están alineadas verticalmente==>mismas coordenadas X
         {
            Xok=1;
         }
         
         if ((Xok==1)&&(valor[0]<S0Y2)&&(valor[0]>S0Y1))
         {
         Xok=0;
         output_toggle(pin_D0);
         //PORTD=0x01;
         dato=1;
         fputc(dato,P2);
         }
         
         if ((Xok==1)&&(valor[0]<S1Y2)&&(valor[0]>S1Y1))
         {
         Xok=0;
         output_toggle(pin_D1);
         //PORTD=0X02;
         dato=2;
         fputc(dato,P2);
         }
   
         if ((Xok==1)&&(valor[0]<S2Y2)&&(valor[0]>S2Y1))
         {
         Xok=0;
         output_toggle(pin_D2);
         //PORTD=0X04;
         dato=3;
         fputc(dato,P2);
         }

         
   
      }//flag==1
     
   
}//while(1)
}//main()

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

#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

#bit D0=PORTD.0
#bit D1=PORTD.1
#bit D2=PORTD.2
#bit A0=PORTA.0
#bit A1=PORTA.1

int lectura=0X00;
int valor=0X00;
int1 flag=0;

#int_RDA // recepción datos del PIC1

void RDA_isr()
{
           
        lectura=fgetc(P2);
        valor=lectura;
        flag=1;     
}

void main()
{
   
   delay_ms(50);//incialización controlador
   SET_TRIS_A (0xFF);
   SET_TRIS_B (0x00);
   SET_TRIS_C (0x80);//c6->out, c7->in
   SET_TRIS_D (0X00);
 
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_psp(PSP_DISABLED);
   int signal=0;
   PORTD=0X00;
   
   enable_interrupts(INT_RDA);//INTERRUPCIÓN USART
   enable_interrupts(GLOBAL);
   
   
    while(true)
    {
         if(flag==1)
      {   
     
         delay_ms(50);
         flag=0;
         
         switch(lectura)
         {
         case 1:
         
         output_toggle(pin_D0);
         break;
         
         case 2:
         output_toggle(pin_D1);
         break;
         
         case 3:
         output_toggle(pin_D2);
         break;
         }
     
      if(pin_A0==0)
      {
      signal=0;
      fputc(signal,P2);
      }
     
      if(pin_A1==0)
      {
      signal=1;
      fputc(signal,P2);
      }

      }//flag==1
     
   
}//while(1)
}//main()
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 11 de Junio de 2011, 19:26:28
Hola, si en el pic2 solo tienes definido un puerto rs232 no necesitas ponerle el stream
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 13 de Junio de 2011, 11:39:27
Hola rivale!!!
Gracias por seguir el hilo. Suprimo el STREAM en el PIC2, pero siguo sin envíar del PIC2 a PIC1. ¿Detectas algo raro en el envío o en la recepción por parte del PIC1??? las prioridades en las interrupciones creo están bien...

Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 13 de Junio de 2011, 18:05:47
Hola, en tu recepcion del pic1 estas intentando leer un dato cuando tienes una interrupcion externa, pero vas a entrar a esa interrupcion cada que tengas un cambio de flanco, no necesariamente cuando tengas un dato. primero checa si tienes un dato usando "kbit" y luego lees
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 14 de Junio de 2011, 13:13:58
hola!

Ocurre lo siguiente: Si en la rutina de atención a la interrupción por flanco de bajada en RB0 coloco el if(kbhit()) entonces no ejecuta lo que tengo dentro de dicha rutina. Si no lo coloco, es decir, si no pregunto si ha llegado bit start entonces sí ejecuta el código  pero deja de funcionarme la interrupción de la USART (y no hace caso a lo que llega desde el controlador) que lo tengo como prioritario:
#PRIORITY RDA, EXT

Continuaré hasta lograrlo, estamos cerca pero ó una cosa o la otra.... :5]
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 14 de Junio de 2011, 13:31:58
Hola de nuevo, si estas usando el kbhit() puede que te de un true cuando tenga un dato por cualquiera de tus puertos, si quieres especificarle en que puerto quieres checar si hay dato usa:

kbhit(stream);   donde stream es el nombre de tu puerto a checar


tambien puedes hacer la prueba poniendo el kbhit dentro de tu main, solo para ver si esta recibiendo bien los datos del otro pic, si no, tal vez sea que el otro no envia bien los datos
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 17 de Junio de 2011, 15:06:22
Hola PICamigos!!!!

Conseguí enviar y recibir tal y como queria con mis dos 16F877. Adjunto los programas tal y cómo los tengo funcionando; sólo una duda: fijaros en el programa del PIC2. Tal y cómo está anda; sin embargo si coloco el envío correspondiente al estado de los pines A0 y A1 dentro del switch, envía pero deja de comunicar correctamente el controlador con el PIC1. Si pongo dicho envío de los dos pines A0 y A1 fuera del switch lo mismo....Tal y cómo está, uno dentro y otro fuera funciona. Raro, raro, raro...

Saludos

Código: [Seleccionar]
#include <16f877.h> //PROGRAM PIC1
#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,STREAM=P1)
#use RS232 (baud=9600, xmit=PIN_B1, rcv=PIN_B0,STREAM=P2 )

#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

#bit D0=PORTD.0
#bit D1=PORTD.1
#bit D2=PORTD.2
#bit D6=PORTD.6
#bit D7=PORTD.7

#PRIORITY RDA, EXT


const int SX1=0X2B;//coordenadas max y min: X
const int SX2=0X61;

const int S0Y1=0X26;//coordenadas max y min: Y_TECLA S0
const int S0Y2=0x3C;

const int S1Y1=0X40;//coordenadas max y min: Y_TECLA S1
const int S1Y2=0x59;

const int S2Y1=0X5B;//coordenadas max y min: Y_TECLA S2
const int S2Y2=0x73;

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

#int_RDA // recepción datos del controlador

void RDA_isr()
{
         
        lectura=fgetc(P1);
        valor[i]=lectura;
        i++;
         if(i==4)
         {
              flag=1;
              i=0;
         }
     
}


#int_EXT //recepción datos PIC2
ext_isr()
{
if (kbhit(P2))
{
      signal=fgetc(P2);
 
     switch (signal)
     {
     case 1:
     output_high(pin_D6);
     break;
     
     case 2:
     output_low(pin_D6);
     break;
     
     case 3:
     output_high(pin_D7);
     break;
     
     case 4:
     output_low(pin_D7);
     break;
     }   
}
}

void main()
{
   
   delay_ms(50);//incialización controlador
   SET_TRIS_A (0xFF);
   SET_TRIS_B (0x01);//b0->in, b1->out
   SET_TRIS_C (0x80);//c6->out, c7->in
   SET_TRIS_D (0X00);
 
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_psp(PSP_DISABLED);
 
   PORTD=0X00;
   int dato=0;

   enable_interrupts(INT_RDA);//INTERRUPCIÓN USART
   enable_interrupts (INT_EXT);//INTERRUPCIÓN EXTERNA (EN RB0)
   ext_int_edge (H_TO_L);
   enable_interrupts(GLOBAL);
   
   
    while(true)
    {
         if(flag==1)
      {   
     
     delay_ms(50);
         flag=0;
         
         if((valor[2]<(SX2))&&(valor[2]>(SX1)))//las X; las 3 teclas en este caso están alineadas verticalmente==>mismas coordenadas X
         {
            Xok=1;
         }
         
         if ((Xok==1)&&(valor[0]<S0Y2)&&(valor[0]>S0Y1))
         {
         Xok=0;
         output_toggle(pin_D0);
         dato=1;
         fputc(dato,P2);
         }
         
         if ((Xok==1)&&(valor[0]<S1Y2)&&(valor[0]>S1Y1))
         {
         Xok=0;
         output_toggle(pin_D1);
         dato=2;
         fputc(dato,P2);
         }
   
         if ((Xok==1)&&(valor[0]<S2Y2)&&(valor[0]>S2Y1))
         {
         Xok=0;
         output_toggle(pin_D2);
         dato=3;
         fputc(dato,P2);
         }
         
       }//flag==1
       
 
}//while(1)
}//main()

Código: [Seleccionar]
#include <16f877.h> //PROGRAM PIC2
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NOWRT
#use delay(clock=8000000)
#use RS232 (baud=9600, 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

#bit D0=PORTD.0
#bit D1=PORTD.1
#bit D2=PORTD.2
#bit A0=PORTA.0
#bit A1=PORTA.1


int lectura=0X00;
int valor=0;
int1 flag=0;

#int_RDA // recepción datos del PIC1

void RDA_isr()
{
           
        lectura=getc();
        valor=lectura;
        flag=1;     
}


void main()
{
   
   delay_ms(50);//incialización controlador
   SET_TRIS_A (0xFF);
   SET_TRIS_B (0xff);
   SET_TRIS_C (0x80);//c6->out, c7->in
   SET_TRIS_D (0X00);
 
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_psp(PSP_DISABLED);
   int signal1=0;
   PORTD=0X00;
   
   enable_interrupts(INT_RDA);//INTERRUPCIÓN USART
   enable_interrupts(GLOBAL);
   
   
    while(true)
    {
   
      if(input(pin_A0)==0)
      {
      //signal1=1;
      //putc(signal1);
      valor=4;
      flag=1;
      }
      else
      {
      //signal1=2;
      //putc(signal1);
      valor=5;
      flag=1;
      }
     
      if(input(pin_A1)==0)
      {
      signal1=3;
      putc(signal1);
      //valor=6;
      //flag=1;
      }
      else
      {
      signal1=4;
      putc(signal1);
      //valor=7;
      //flag=1;
      }
   
    ///////////////////////////////////
      if(flag==1)
      {   
         delay_ms(50);
         flag=0;
         
         switch(valor)
         {
         case 1:
         output_toggle(pin_D0);
         break;
         
         case 2:
         output_toggle(pin_D1);
         break;
         
         case 3:
         output_toggle(pin_D2);
         break;
         
         case 4://d6 pic1 on
         signal1=1;
         putc(signal1);
         break;
         
         case 5:// d6 pic1 off
         signal1=2;
         putc(signal1);
         break;
         }
         /*
         
         case 6://d7 pic1 on
         signal1=3;
         putc(signal1);
         break;
         
         case 7://d7 pic1 off
         signal1=4;
         putc(signal1);
         break;
         }*/
       
       }//flag==1
   
       
}//while(1)
}//main()
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 17 de Junio de 2011, 18:07:56
que bueno que funciona :-/, aunque no tendria porque darte errores si pones los 2 dentro de un switch.

a que te refieres con que se deja de comunicar correctamente con el pic1, el pic2 se pierde, o se resetea o deja de enviar cualquier dato?
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 18 de Junio de 2011, 07:17:55
Hola!!!

pues deja de comunicar el PIC1 con el controlador, con los cambios el programa PIC2... Seguiré ajustando... Ya sabes, lo que en principio no tiene explicación, seguro la tiene.

Saludos cordiales :P
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 18 de Junio de 2011, 11:04:50
Ya sabes, lo que en principio no tiene explicación, seguro la tiene.



si, eso siempre pasa, solo no te desesperes, oye, lo haz debuggeado o simulado en proteus paso a paso?, quizas ahi puedas ver que pasa exactamente cuando pones los 2 dentro del switch.
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: daltonico82 en 20 de Junio de 2011, 06:35:32
Hola!!!! No dispongo del proteus.... y lo del debug... nunca lo he probado... creo es hora de trabajar con el entorno MPLAB.

Dispongo de unas entrenadoras de MIKROELECTRONICA y siempre pruebo directamente en hardware.

Si conoces algún hilo dónde hablen sobre el debug... dejamelo, lo agradezco.

Saludos y gracias por todas la aportaciones e ideas
Título: Re: mil vueltas... en una sencilla comunicación serie entre pic
Publicado por: rivale en 20 de Junio de 2011, 09:31:28
el debug se puede hacer con tu programador directamente, depende de cual tengas.
te recomendaria usar el proteus, lo puedes integrar al mplab para ver el codigo linea a linea y usar las herramientas tanto del mplab como del proteus