viernes, 8 de marzo de 2013

Comunicacion entre 2 Pic's Maestro-Esclavo via SPI

En la siguiente entrada vamos a realizar una comunicación maestro-esclavo, entre 2 Pic's 18F4550 mediante el protocolo SPI.

Ejercicio:
Disponemos de dos Pics 18F4550, los cuales, están conectados a través del protocolo SPI y se enviarán valores pares o impares, actuando como Maestro-Esclavo o Esclavo-Maestro.
En primer lugar el Pic1 funcionará como Maestro, y al ejecutar el programa mediante un pulsador(Boton1) enviaremos un valor par a través del protocolo SPI, ese dato será recibido por el Pic2, y mostrado en un Lcd la recepción del mismo.
A continuación, si pulsamos el Botón2 el Pic2 actuará como maestro y ahora enviará un valor impar, que será recibido por el Pic1 y mostrado en su Lcd.
Según vayamos enviando valores de un Pic a otro,los valores irán incrementando en +1.

Diseño del Esquemático en Isis

El primer paso, será el diseño del esquemático en Isis para poder realizar su simulación.
Partimos realizando el conexionado y esquemático del Pic1, el cual al ejecutar el programa actuará como maestro enviando datos pares al Pic2.
Se puede apreciar en la imagen que el Boton1 le hemos conectado al pin RA0 el cual utilizaremos para ejecutar la orden de envío.
Hemos puenteado los pines RA4 y RA5, ya que el pin RA5 actúa como negado para poder utilizar el Pic como Slave(SS).
Los pines RB0 y RB1 les hemos empleado: para la entrada de datos RB0(SDI) y para la señal de reloj RB1(SCK).
En la salida de datos utilizamos el Pin RC7(SDO).
Por último  el puerto D lo hemos destinado para mostrar los datos en el LCD.



El conexionado en el Pic2 tendrá la misma estructura que el Pic1, en la imagen que mostramos a continuación podemos ver el resultado final.
También hemos añadido un debugger de SPI para poder analizar el tráfico de datos.




Programación del código C

En este ejercicio hemos empleado de una forma pionera el programa MPlabX, el cual es la última versión de Microchip para la programación de Pic.
Obviamente como tenemos dos Pic, tenemos que realizar 2 códigos fuente, uno para cada microcontrolador.

Código Pic1

Este es el código que hemos desarrollado para el Pic1, el cual explicaremos detalladamente:


///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CABECERA /////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include<18f4550.h>
#FUSES INTHS,MCLR,PUT,BROWNOUT
#use delay(INTERNAL=8MHZ)
#include<LCD.c>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// VARIABLES GLOBALES //////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
int dato=0;  // hemos definido la variable dato como global

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PRINCIPAL /////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
SETUP_SPI(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_16); // configuracion del Pic1 como maestro
lcd_init();
printf(lcd_putc,"Pulse Boton 1\nPara Enviar");
while(true)
{
if(input(PIN_A0)==1)
{
while(input(PIN_A0)==1){}
output_bit(PIN_A4,1);  /* activamos el pin RA4 en True, ya que está puenteado con RA5 */
printf(lcd_putc,"\fEnviando");
SPI_WRITE(dato);
delay_ms(50);
SETUP_SPI(SPI_SLAVE|SPI_L_TO_H|SPI_CLK_DIV_16); /* configuramos el Pic1 como esclavo */
delay_ms(50);
lcd_gotoxy(1,2);
printf(lcd_putc,"Dato par: %d",dato); // muestra el dato enviado
output_bit(PIN_A4,0);/* cambiamos el pin RA4 a False, ya que está puenteado con RA5 */
}
if(SPI_DATA_IS_IN()) // si recibe un dato a través de SPI
{
printf(lcd_putc,"\fRecibido");
dato=SPI_READ(); // almacenamos en la variable dato la lectura
delay_ms(50);
SETUP_SPI(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_16);// configuracion del Pic1 como maestro de nuevo
delay_ms(50);
lcd_gotoxy(1,2);
printf(lcd_putc,"Dato impar: %d",dato); // muestra el dato recibido
dato++;
output_bit(PIN_A4,1); /* activamos el pin RA4 de nuevo a True, ya que está puenteado con RA5 */
}
delay_ms(500);
}
}



Código Pic2

El código del segundo pic es muy similar.



//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CABECERA ////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include<18f4550.h>
#FUSES INTHS,MCLR,PUT,BROWNOUT
#use delay(INTERNAL=8MHZ)
#include<LCD.c>

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// VARIABLES GLOBALES //////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
int dato=0; // en el pic2 hemos empleado la misma variable

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PRINCIPAL ////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
SETUP_SPI(SPI_SLAVE|SPI_L_TO_H|SPI_CLK_DIV_16);  // configuramos el pic2 como esclavo cuando ejecutamos el programa
lcd_init();
printf(lcd_putc,"Pulse Boton 2\nPara Enviar");
while(true)
{
if(input(PIN_A0)==1)
{
while(input(PIN_A0)==1){}
output_bit(PIN_A4,1);  // activamos el pin RA4 
delay_ms(50);
printf(lcd_putc,"\fEnviando");
SPI_WRITE(dato);   // escribe el dato SPI
delay_ms(50);
SETUP_SPI(SPI_SLAVE|SPI_L_TO_H|SPI_CLK_DIV_16);  // configuramos el pic2 como esclavo
delay_ms(50);
lcd_gotoxy(1,2);
printf(lcd_putc,"Dato impar: %d",dato);
output_bit(PIN_A4,0);
}
if(SPI_DATA_IS_IN()) // si recibe datos SPI
{
printf(lcd_putc,"\fRecibido");
dato=SPI_READ(); // almacenamos el dato en la variable
delay_ms(50);
SETUP_SPI(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_16); // configuramos el pic2 como maestro
delay_ms(50);
lcd_gotoxy(1,2);
printf(lcd_putc,"Dato par: %d",dato);
dato++;
output_bit(PIN_A4,1);
}
}
delay_ms(500);
}



Funcionamiento

Una vez que tenemos los códigos desarrollados, compilamos y cargamos los ficheros*.cof o *.hex en los pics de Proteus, para poder realizar la simulación.



Este es un pequeño video mostrando su funcionamiento.




1 comentario:

  1. Hola como estas?....interesante programa...pero tengo una pregunta....porqué puenteaste el pin ra5 con ra4....sabemos que ra5 es el pin selector de esclavo en la interfaz spi multiesclavo...ahora en el segundo programa no veo que escogieras en la configuracion la seleccion del chip select...porque así no está haciendo nada en el programa...tampoco veo la directiva de cabecera #use spi(master,pin_sda,pin_sdo,clk=pin_reloj,modo de los cuatro que hay, force_hw)...a menos que la interfaz del pic funcione sin esa directiva

    ResponderEliminar