RobotyPic son proyectos básicos de electrónica con microcontroladores PIC, de aplicación en el mundo de la robótica didáctica, con archivos fuente creados mediante el compilador CCS PIC C COMPILER en lenguajeC.

Comunicación no estándar entre dos PIC.


Sabemos que existen diversos sistemas de comunicación para transmitir datos entre PICs (comunicación serie, SPI, I2C, etc.). Aquí vamos a desarrollar un sistema de comunicación propio para la transmisión de bytes de datos de un PIC maestro a uno esclavo y viceversa. No se trata de competir con los sistemas estándar de comunicación existentes sino de disponer de un recurso cuando tenemos que transferir datos de un PIC a otro sin demasiadas exigencias. La única condición en el código desarrollado es que ambos PICs, maestro y esclavo, trabajen con la misma frecuencia de reloj.

El proceso se ha pensado para un bus de 4 líneas:
- Mx_pin es unidireccional y transfiere información del PIC Maestro al PIC Esclavo.
- Ex_pin hace la misma función que el anterior pero la transferencia es del PIC Esclavo al Maestro.
- Inicio_pin también es unidireccional y se emplea para avisar al PIC Esclavo desde el Maestro de que se va a producir una transferencia de información.
- Sincro_pin es bidireccional y su misión es sincronizar el envío de información de uno de los PIC con su recepción por el otro PIC.


Para enviar un byte al Esclavo, el PIC maestro comienza el proceso poniendo a '1' Inicio_pin. Este pulso alerta al PIC esclavo para atender la petición del maestro. Previamente, el maestro ha asegurado el Mx_pin a '0'. Cuando el Esclavo atiende a la solicitud, lee el estado del Mx_pin. Un '0' significa que el maestro le va a enviar un byte de datos. Un '1' significa que el maestro le va a solicitar leer un byte de datos.


Cuando el esclavo ya ha accedido a la solicitud del maestro y leído el estado del Mx_pin, da un pulso en el Sincro_pin para avisar al maestro de que puede mandarle el primer bit del byte a transmitir, comenzando por el bit más significativo b7. El PIC esclavo espera unos 5 uS para asegurar que el maestro pase al Mx_pin el siguiente bit. Cuando el esclavo lee el valor vuelve a dar un pulso en Sincro_pin para avisar al maestro. El proceso se repite para los 8 bits del byte transmitido. Después de leer el último bit, el esclavo da un pulso  de unos 10uS en el pin Ex_pin como confirmación de recepción del byte completo.





Para solicitar un byte al Esclavo, el PIC maestro comienza el proceso asegurando el pin Mx_pin a '1'. A continuación da un pulso de comienzo de comunicación en el pin Inicio_pin. Este pulso alerta al esclavo para que atienda el requerimiento del maestro. El esclavo lee el estado del pin Mx_pin. El valor '1' le avisa de que el maestro le solicita un byte para leer. El esclavo confirma su lectura mediante un pulso en Sincro_pin.  En ese momento el control del pin Sincro_pin pasa al maestro (pasa a ser salida en el maestro y entrada en el esclavo).
Ahora es el esclavo quien trasmite el byte de datos bit a bit por Ex_pin y el maestro quien advierte al esclavo de que ya ha leído el bit en curso mediante un pulso en la linea Sincro_pin.
Finalizada la recepción del byte completo por el maestro este lo indica con un pulso de 10uS en Mx_pin.




Tanto en el maestro como en el esclavo, la estrategia empleada, a nivel de código para enviar un byte (8 bits) bit a bit por una única línea, consiste en emplear una variable de valor inicial 0x80 (0b10000000)  con la que haremos una comparación AND con el byte a enviar. Si el byte a enviar tiene ese mismo bit a '1', el resultado de la función AND será 1 y si es 0 será 0. Y ese será el valor que enviaremos del bit. Rotaremos el bit de la variable una posición (0b01000000=> mascara = 0x40) para comparar el siguiente bit del byte (b6) y así sucesivamente para los 8 bits.



   int mascara = 0x80;
  
   /** Envío del byte de datos **/
   for (bit=8; bit>=1; bit--){                     //Para los 8 bits
      if ((dato & mascara)>0) output_high(Mx_pin); //Si bit en curso es 1
      else output_low (Mx_pin);                    //Si bit en curso es 0
      mascara = mascara >> 1;                      //Preparación proximo bit
   }

Al otro lado está el PIC que recibe el byte bit a bit.  Cuando el bit recibido es 0 realiza una función OR entre la variable temporal (que inicialmente tiene valor 0) y la constante mascara0 (con valor 0b00000000). Cuando el bit recibido es 1 realiza la función OR entre la variable temporal y la constante mascara1. Rota una posición los bits de la variable temporal y vuelve a recibir el siguiente bit. Así hasta los 8 bits.



   int mascara0 = 0;
   int mascara1 = 0x01;
   int temporal = 0;
         
   /** Lectura de los 8 bits del byte enviado **/
   for (bit=8; bit>=1; bit--){
      delay_us (5);                  
      if (input_state (Ex_pin)) temporal|=mascara1;      //Si bit recibido es 1
      else temporal|=mascara0;                           //Si bit recibido es 0
      DatoE_RyP_COM=temporal;                            //Guarda recepción
      temporal = temporal << 1 ;        //Preparación para recibir siguiente bit
   }

Todas las funciones necesarias para realizar la comunicacion entre los dos PICs se ha incluido en una librería <RyP_COM.c> que es la que deberemos llamar en el código principal.


#include <RyP_COM.c>

Previamente deberemos definir si el PIC lo vamos a utilizar como Maestro...


#define MASTER    1         //PIC como Maestro 

O como esclavo...


#define SLAVE     1         //PIC como Esclavo

También deberemos definir, antes de cargar la librería, los pines del bus a emplear. Se pueden elegir los que se deseen pero, sino se especifica ninguno, la librería cargará los que tiene por defecto.


#define Mx_pin       PIN_B1
#define Ex_pin       PIN_B2
#define Inicio_pin   PIN_B3
#define Sincro_pin   PIN_B4

En el código del PIC maestro, para enviar un byte al esclavo, llamaremos a la función...


Tx_RyP_COM (Dato_Maestro);       //Envío de un dato al esclavo

Donde "Dato_Maestro" será la variable que contiene el byte a enviar.

Cuando lo que se quiere es leer un byte del esclavo, la función es...


Rx_RyP_COM (Dato_Esclavo);      //Solicitud de dato al esclavo

El byte recibido se almacena en la variable "Dato_Esclavo".Los nombres de las variables se pueden elegir a voluntad.

En el esclavo, la función a invocar es...


Test_RyP_COM (Dato_Esclavo, Dato_Maestro);

Se encarga de testear las posibles solicitudes del PIC maestro. En la variable "Dato_Maestro" se almacena el byte recibido y se envía el byte contenido en "Dato_Esclavo". También para esta función los nombres de las variables se pueden elegir a voluntad, siempre y cuando sean previamente declaradas.

El código de ejemplo aquí mostrado es una muestra de su uso. El PIC Maestro lee el valor de su conversor A/D y lo envía al Esclavo. De la misma forma solicita el valor de la lectura del conversor A/D del Esclavo. Ambas lecturas se muestran en los displays de los respectivos PICs.

En esta animación vemos su funcionamiento y las señales generadas.



[+/-] Ver / Ocultar código PIC Maestro

[+/-] Ver / Ocultar código PIC Esclavo

[+/-] Ver / Ocultar código librería


Los archivos del proyecto se pueden descargar en este enlace:




El proyecto contenido en el artículo ha sido diseñado y probado con éxito utilizando las siguientes versiones de software:
- Windows 10 (64 bits)
- Proteus V7.7 SP2
- CCS PIC C COMPILER v5.015



No hay comentarios:

Related Posts Plugin for WordPress, Blogger...

CONTACTA - (Haz referencia del artículo sobre el que trata la consulta o comentario)