TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: thegame en 10 de Octubre de 2010, 15:56:28

Título: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: thegame en 10 de Octubre de 2010, 15:56:28
Que tal a todos, de nuevo dando lata, pues veran mi pregunta tiene que ver con la comunicacion SPI entre dos PIC's 18F4550, uno como maestro y el otro como esclavo (obvio jeje), se que hay mucha informacion y temas sobre esto en el foro, pero de verdad que lo he leido casi todo, y no logro hacer que el esclavo me envie datos, si me recibe datos, pero no me responde, entonces, concretando la pregunta:

¿Cual debe ser la secuencia correcta para que el esclavo envie un dato, por ejemplo un 0x02?

hasta ahora esto es lo que tengo:

Para el maestro:

Código: [Seleccionar]
#include<18f4550.h>
#fuses HS,PLL1,CPUDIV1,PUT,NOBROWNOUT,NOVREGEN,NOWDT,NOPBADEN,MCLR,NOLVP,NODEBUG,NOPROTECT
#use delay(clock=20000000)
//#use spi(MASTER,DI=PIN_B0,DO=PIN_C7,CLK=PIN_B1,MODE=1,BITS=8,FORCE_HW)

#BYTE TRISB=0xF93
#BYTE PORTB=0xF81

void main(void)
{
bit_clear(TRISB,7);
bit_set(PORTB,7);
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4|SPI_XMIT_L_TO_H);
bit_clear(PORTB,7);

while(1)
{
spi_write(0x01);
                delay_ms(1000);
}

}

Y para el esclavo:

Código: [Seleccionar]
#include<18f4550.h>
#fuses HS,PLL1,CPUDIV1,PUT,NOBROWNOUT,NOVREGEN,NOWDT,NOPBADEN,MCLR,NOLVP,NODEBUG,NOPROTECT
#use delay(clock=20000000)
//#use spi(SLAVE,DI=PIN_B0,DO=PIN_C7,CLK=PIN_B1,ENABLE=PIN_A5,MODE=1,BITS=8,FORCE_HW)

#BYTE TRISB=0xF93
#BYTE PORTB=0xF81

int dato;

void main(void)
{
bit_clear(TRISB,7);
bit_clear(PORTB,7);
setup_spi(SPI_SLAVE|SPI_L_TO_H|SPI_CLK_DIV_4|SPI_XMIT_L_TO_H);

while(1)
{
if(spi_data_is_in())
{
dato=spi_read();
if(dato==0x01)
{
bit_set(PORTB,7);
delay_ms(400);
bit_clear(PORTB,7);
delay_ms(400);
}
}
}
}

Con esto solo le envio cada segundo un 0x01 desde el maestro hacia el esclavo, lo he simulado en proteus y funciona, he puesto un led en el RB7 del esclavo que parpadea cada ves que lee el dato.

Utilizo el RB7 del maestro para el chip select.

No soy experto en esto, de echo es la primera vez que lo uso, espero me puedan ayudar y claro corregir, que seguro la estoy regando en algo.

Gracias
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: Suky en 10 de Octubre de 2010, 18:34:48
Fíjate que en modo esclavo en SPI se utiliza el PIN CS que habilita la comunicación.


Saludos!
Título: Re: Pregunta
Publicado por: QIQE en 10 de Octubre de 2010, 18:36:34
Quiza deberías emplear una interrupción cuando
Recibas datos por spi
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: thegame en 10 de Octubre de 2010, 19:55:11
es CS o SS activo en bajo??? porque si es asi si lo estoy usando, y lo de la interrupcion ya lo probe tambien pero no me queda, seguire intentando
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: BrunoF en 10 de Octubre de 2010, 21:15:56
El Slave Select es Activo en Bajo en el protocolo SPI.

Saludos.
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: thegame en 10 de Octubre de 2010, 21:52:26
correcto BrunoF, asi lo estoy usando, pero no logro que me envie un dato simple, como 0x02, por ejemplo, uso la funcion spi_write(0x02), claro en el codigo que coloque no esta esa parte, porque he estado haciendo pruebas, pero coloque lo que llevo para que mas o menos me puedan ayudar y decirme donde se podria poner la parte para que el esclavo me mande el valor y la parte en la que el maestro recibiria.

gracias por la ayuda
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: Suky en 10 de Octubre de 2010, 22:04:54
Realizaste algún debug? Cruzaste las lineas SDI y SDO?
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: BrunoF en 10 de Octubre de 2010, 23:36:21
correcto BrunoF, asi lo estoy usando, pero no logro que me envie un dato simple, como 0x02, por ejemplo, uso la funcion spi_write(0x02), claro en el codigo que coloque no esta esa parte, porque he estado haciendo pruebas, pero coloque lo que llevo para que mas o menos me puedan ayudar y decirme donde se podria poner la parte para que el esclavo me mande el valor y la parte en la que el maestro recibiria.

gracias por la ayuda

Hola. Nunca trabajé con dos microcontroladores comunicandose por SPI(en modo maestro-esclavo), pero hasta donde sé del protocolo el maestro es quien siempre inicia todas las peticiones. Nunca el esclavo. Algo similar sucede entre un Host y un Device en el protocolo USB(<=v2.0).
El esclavo puede recibir información del maestro, o bien enviarla, pero es siempre el maestro quien determina si quiere o no seleccionarlo y/o comunicarse con el. El maestro siempre es el que genera los pulsos de clock. Me parece que primero deberías intentar un byte desde el maestro hacia el esclavo, y luego sí, meterte ya a enviar desde el esclavo al maestro. Pero tené en cuenta que para eso, es el maestro el que debe iniciar la conversación siempre.

Puede que esté equivocado, pero es lo que recuerdo y lo que me parece lógico debido a las limitaciones de la capa física del protocolo SPI.

P.D. Es muy buena la observación que te hace Suky de que los cables SDI y SDO van cruzados entre los dispositivos...

Saludos.
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: thegame en 11 de Octubre de 2010, 01:16:13
Asi es compañero suky, he cruzado los cables, es decir, la salida del maestro a la entrada del sclavo y viceversa, realice un debug muy sencillo en Proteus, con el spi debug, pero solo veo como le llega el dato al esclavo y nunca devuelve nada, repito, el codigo que he puesto es lo que ya funciona, es decir solo del maestro al esclavo, y no en ambas direcciones.

mmm, y si es asi como lo comentas amigo BrunoF, el maestro es quien inicia la comunicacion y quien genera los pulsos de reloj, talves alguna configuracion se me ha ido, o algun delay, o alguna instruccion faltante o mal usada, ya no se, creo que necesito ver con mas calma otra ves las hojas de datos del micro.

gracias por la ayuda.
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: thegame en 11 de Octubre de 2010, 01:34:30
aqui pongo la imagen del diseño inicial en proteus, es decir en un solo sentido (maestro---->esclavo) y funciona, o por lo menos veo la respuesta en el led,a este diseño he probado agregarle al maestro (PIC de la IZQUIERDA) en el pin RB6 otro led para comprobar que el esclavo(PIC de la DERECHA) envia un dato, no se talves he simulado mal, no soy experto en proteus, pero hasta ahora nada que puedo.

Se aceptan sugerencias por supuesto
(http://www.todopic.com.ar/foros/imgtiny/20ro7ye.jpg)
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: BrunoF en 11 de Octubre de 2010, 06:09:12
Hola. Bueno, estuve mirando con un poquito mas de tiempo tu post y código.... Creo que el error resulta bastante evidente.

Como dijimos entonces, el master genera los clocks. Lo que significa que la unica manera de que el esclavo envie algo, es mientras el master genera clocks(y en consecuencia a ello, quiera o no, también estará enviando algún valor por su linea SDO).

Entonces, creo que el problema de que tu esclavo no envie nada, es que sencillamente no le has pedido en ningun momento a tu esclavo que envie y a tu master que escuche, para lograr lo que quieres...

Podria ser algo correcto en tus programas hacer algo así:

Para el maestro:

Código: [Seleccionar]
#include<18f4550.h>
#fuses HS,PLL1,CPUDIV1,PUT,NOBROWNOUT,NOVREGEN,NOWDT,NOPBADEN,MCLR,NOLVP,NODEBUG,NOPROTECT
#use delay(clock=20000000)
//#use spi(MASTER,DI=PIN_B0,DO=PIN_C7,CLK=PIN_B1,MODE=1,BITS=8,FORCE_HW)

#BYTE TRISB=0xF93
#BYTE PORTB=0xF81

#Define CMD_SET_VALUE 0x01
#Define CMD_GET_VALUE 0x02

void main(void)
{
        char ReadedValue;        

bit_clear(TRISB,7);
bit_set(PORTB,7);
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4|SPI_XMIT_L_TO_H);
bit_clear(PORTB,7);

while(1)
{
spi_write(CMD_GET_VALUE);        //indicar que queremos que el esclavo nos envie el valor
ReadedValue = spi_read();          //leer envío del esclavo.
                output_d(ReadedValue);              //mostrar el valor obtenido en el puerto D

                delay_ms(500);
        
                spi_write(CMD_SET_VALUE);        //indicar que queremos enviar un valor al esclavo
                spi_write(++ReadedValue);         //enviarle el valor leido previamente, pero incrementado para que el esclavo lo guarde actualizado al nuevo valor  

                delay_ms(500);
}

}

Y para el esclavo:

Código: [Seleccionar]
#include<18f4550.h>
#fuses HS,PLL1,CPUDIV1,PUT,NOBROWNOUT,NOVREGEN,NOWDT,NOPBADEN,MCLR,NOLVP,NODEBUG,NOPROTECT
#use delay(clock=20000000)
//#use spi(SLAVE,DI=PIN_B0,DO=PIN_C7,CLK=PIN_B1,ENABLE=PIN_A5,MODE=1,BITS=8,FORCE_HW)

#BYTE TRISB=0xF93
#BYTE PORTB=0xF81

#Define CMD_SET_VALUE 0x01
#Define CMD_GET_VALUE 0x02

int dato;

void main(void)
{
        char myValue;


bit_clear(TRISB,7);
bit_clear(PORTB,7);
setup_spi(SPI_SLAVE|SPI_L_TO_H|SPI_CLK_DIV_4|SPI_XMIT_L_TO_H);

        myValue = 0;

while(1)
{
if(spi_data_is_in())
{
dato=spi_read();                       //leer comando a ejecutar
                        switch(dato){                            //seleccionar segun comando recibido
    case CMD_SET_VALUE:        //se ha recibido una peticion de setear el valor.
       myValue = spi_read();      //entonces leer el valor y almacenarlo
    break;

    case CMD_GET_VALUE:       //se ha recibido una peticion de enviar el valor.
bit_toggle(PORTB,7);       //indicarlo cambiando el estado del pin b7
spi_write(MyValue);        //y enviar el valor al master...
    break;
}
}
}
}


Obviamente ese mini protocolo lo arme para mostrarte el ejemplo y vos podés armarlo vos según tu necesidad y a medida.

P.D. Escribí el código "on the fly" por lo que no está excento a errores de sintáxis, compilación y menos aún, funcionamieto.

Saludos.
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: Suky en 11 de Octubre de 2010, 09:15:05
mmm, y si es asi como lo comentas amigo BrunoF, el maestro es quien inicia la comunicacion y quien genera los pulsos de reloj, talves alguna configuracion se me ha ido, o algun delay, o alguna instruccion faltante o mal usada, ya no se, creo que necesito ver con mas calma otra ves las hojas de datos del micro.

Ups! Claro, falta un read_spi en el master para que genere el clock  :mrgreen: En SPI puede mandar y recibir datos al mismo tiempo  ;-)


Saludos!
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: thegame en 11 de Octubre de 2010, 14:30:32
okidoki BrunoF, dejame probar lo me mencionas, y te pongo tambien el avance en el codigo que yo tengo, te agradesco mucho tu ayuda, Suky tambien muchas gracias hago pruebas y les digo si lo logre.
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: thegame en 11 de Octubre de 2010, 15:07:06
Asi es amigo BrunoF, hice algo similar a lo que me mencionaste y funciona, ahora si entendi bien, lo que se hace es porner como un dato de control que le dice al esclavo si queremos leer de el, o escribirle, que son los que tu defines en el codigo, yo solo los puse asi directamente y funciona, ahora voy a depurar y hacer un programa mas complej. Gracias.
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: thegame en 11 de Octubre de 2010, 20:24:09
me adelnte a pensar que ya funcionaba, porque ahora hay algo que no me cuadra, y me lleva a pensar que no funciona,  ahora que hago la simulacion en proteus y utilizo el SPI debug me sale esto:

(http://www.todopic.com.ar/foros/imgtiny/242euc2.jpg)

ahora, no soy experto, como ya lo dije, pero por lo poco que entiendo, los datos subrayados de azul, son los que se envian, no??,y los de verde son los que se reciben, no???, bueno eso supongo yo.

entonces, lo que esta encerrado en el circulo rojo, corresponde al dato de comando que le envio al esclavo, para que este me envie un 0x44, pero no veo por ningun lado el 0x44. Entonces que paso ahi???????

esta es la configuracion que uso para el SPI debuger:

(http://www.todopic.com.ar/foros/imgtiny/f0qmtu.jpg)

y estos son los codigos para el maestro:

Código: [Seleccionar]
#include<18f4550.h>
#fuses HS,PLL1,CPUDIV1,PUT,NOBROWNOUT,NOVREGEN,NOWDT,NOPBADEN,MCLR,NOLVP,NODEBUG,NOPROTECT
#use delay(clock=20000000)
//#use spi(MASTER,DI=PIN_B0,DO=PIN_C7,CLK=PIN_B1,MODE=1,BITS=8,FORCE_HW)

#BYTE TRISB=0xF93
#BYTE PORTB=0xF81

int dato;

void main(void)
{
bit_clear(TRISB,7);
bit_clear(TRISB,6);
bit_set(PORTB,7);
bit_clear(PORTB,6);
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4|SPI_XMIT_L_TO_H);
bit_clear(PORTB,7);

while(1)
{
spi_write(0x01); //enviar
spi_write(0x33);

delay_ms(500);

spi_write(0x02); //recibir
if(spi_data_is_in()==1)
{
dato=spi_read();
if(dato==0x44)
{
output_toggle(PIN_B6);
delay_ms(400);
}
}
delay_ms(500);
}

}

y para el esclavo:

Código: [Seleccionar]
#include<18f4550.h>
#fuses HS,PLL1,CPUDIV1,PUT,NOBROWNOUT,NOVREGEN,NOWDT,NOPBADEN,MCLR,NOLVP,NODEBUG,NOPROTECT
#use delay(clock=20000000)
//#use spi(SLAVE,DI=PIN_B0,DO=PIN_C7,CLK=PIN_B1,ENABLE=PIN_A5,MODE=1,BITS=8,FORCE_HW)

#BYTE TRISB=0xF93
#BYTE PORTB=0xF81

int dato,dato_leido;

void main(void)
{
bit_clear(TRISB,7);
bit_clear(PORTB,7);
setup_spi(SPI_SLAVE|SPI_L_TO_H|SPI_CLK_DIV_4|SPI_XMIT_L_TO_H);

while(1)
{
if(spi_data_is_in())
{
dato=spi_read();
if(dato==0x01) //recibe
{
dato_leido=spi_read();
bit_set(PORTB,7);
delay_ms(400);
bit_clear(PORTB,7);
delay_ms(400);
}
if(dato==0x02)//envia
{
spi_write(0x44);
}
}
}
}

creo que voy a salir traumado de esto jeje, pero bueno, gracias y espero alguien me ayude



Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: thegame en 13 de Octubre de 2010, 19:36:11
Ya lo solucione  :-/  :-/, resulta que mi error era mas sencillo de lo que parecia, mas bien fue un error de observacion, despues de intentar como mil intentos, me di cuenta que mi configuracion en el esclavo estaba mal, concretamente el bit SMP, del registro SSPSTAT, que en el esclavo debe ser 0, y yo lo ponia a 1, error, jajaja bueno gracias por la ayuda
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: Lobo_Azul en 30 de Octubre de 2010, 18:22:39
   Que bien que hayas solucionado tu problema thegame, pero podrías subir los códigos que hiciste para nosotros los principiantes, si no es mucha molestia, yo quiero empezar a trabajar con este protocolo tambien, de todas formas gracias... :P
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: Lobo_Azul en 10 de Noviembre de 2010, 22:40:01
   Hi thegame, pues ando revisando este foro de nuevo pero no veo respuesta........ :(
O al menos podrías decirme a cual 1 y cual 0 es al que te refieres que resolvio tu problema y donde esta en el codigo??
Y otra preguntita  :P : Las lineas

#BYTE TRISB=0xF93
#BYTE PORTB=0xF81

que pones en tu código son forzosamente necesarias para el SPI con el 18F4550, es decir que si pongo al maestro y esclavo con un 18f4550 deben ser necesarias esa lineas, pero si pongo como maestro un 18f4550 y esclavo un 16f877 esas lineas cambian o sólo las usas para configurar la salida del led???

Gracias de todas formas.
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: Lobo_Azul en 20 de Noviembre de 2010, 19:56:06
    :huh:  Hola de nuevo, sigo esperando respuesta a mis dudas, pero no la veo, o al menos podría alguien ayudarme, ya que yo he puesto como maestro un PIC18F4550 y como esclavo un PIC16F877A, pero no logro hacer que el esclavo me envíe datos (he puesto vartias lineas como comentarios a modo de prueba, pero ninguna funciona), quisiera ver si alguien me puede ayudar, pongo los códigos para ver si alguien puede decirme donde esta mi error o como puedo hacer para que el esclavo me envíe los datos del convertidor AN0 que pongo en este caso, agrdecería su ayuda, gracias.   :?:

Soy algo nuevo en esto de responder, pero tambien adjunto el proyecto entero que he realizado en Proteus y una imagen del mismo; espero ayuda gracias...   :?


Para maestro:
Código: [Seleccionar]
#include<18f4550.h>
#fuses HS,PLL1,CPUDIV1,PUT,NOBROWNOUT,NOVREGEN,NOWDT,NOPBADEN,MCLR,NOLVP,NODEBUG,NOPROTECT
#use delay(clock=20000000)
//#use spi(MASTER,DI=PIN_B0,DO=PIN_C7,CLK=PIN_B1,MODE=1,BITS=8,FORCE_HW)

#BYTE TRISB=0xF93
#BYTE PORTB=0xF81

int8 leidoesc;

void main(void)
{
   bit_clear(TRISB,7);
   bit_set(PORTB,7);
   setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4|SPI_XMIT_L_TO_H);
   bit_clear(PORTB,7);
  
   while(1)
   {
      spi_write(0xFF);
                delay_ms(1000);
                
       spi_write(0x16); //recibir
       if(spi_data_is_in())
       {
         leidoesc = spi_read();
         output_d (leidoesc);
         delay_ms(250);
       }
   }
  
}




Para esclavo:

Código: [Seleccionar]
#include <16f877a.h>
#DEVICE ADC=8
#use delay(clock=20000000)
//#byte puerto_b=06

void canal_0(void);

int conversion=0, valor_spi, dummy;

void main()
{
  setup_adc_ports(RA0_ANALOG);
  setup_adc(ADC_CLOCK_DIV_2);
  set_tris_a(255);
  set_tris_c(223);
  set_tris_b(0);
  //puerto_b = 0;
  setup_spi(spi_slave | spi_l_to_h | spi_clk_div_16| SPI_XMIT_L_TO_H);
  do
   {
     if(spi_data_is_in())
       {
         //canal_0();
         valor_spi = spi_read();
         output_d(valor_spi);
         delay_ms(250);
         //canal_0();
         //spi_write(conversion);
         output_b(conversion);
         //dummy = spi_read();
         //spi_write(conversion);
         delay_ms(250);
         //spi_write(conversion);
         //output_b (0);
       }

          /* canal_0();
           spi_write(conversion);
           delay_ms(250);*/
           //output_b (0);

      
   }
  while(true);
}

void canal_0(void)
{
   setup_adc(adc_clock_div_32);           // Encendemos el conversor
   set_adc_channel(0);
   delay_us(20);
   conversion = read_adc();
   conversion = conversion << 1;
    
}

Pongo también la simulación que he hecho en proteus:

(http://Simulación.jpg)

Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: Lobo_Azul en 20 de Noviembre de 2010, 19:58:14
Mmmmmm, o estaba pensando, debo poner esto como un nuevo tema???  :?

Gracias de todas formas.
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: thegame en 11 de Septiembre de 2011, 23:26:45
ijole, una disculpa lobo azul, me desconecte bastante tiempo por mi trabajo, y apenas volvi a entrar, no se si ya allas resuelto tu problema amigo, pero si puedo ayudarte adelante, avisame y subire el codigo que utilice, que por cierto debo buscar jeje, pero no problema si no lo volvemos a hacer.

en cuanto a lo de las lineas que preguntas se ponen para mapear el registro tris y port del micro y de esta manera utilizar algunas funciones que trae el CCS, almenos asi lo he utilizado varias veces sin problema, claro hay otras funciones que realizan la misma accion pero depende de como programemos.

de nuevo una disculpa y yo estare al pendiente, por lo pronto buscare el codigo y lo subire en caso de que a alguien mas le sirva ok.
Título: Re: Pregunta, comunicación SPI entre dos PIC's 18F4550 ....
Publicado por: borodelostoldos en 07 de Noviembre de 2012, 11:39:31
Hola chicas, para mandar un dato desde el esclavo al master, primero tienen que escribir un dato con el maestro: spi_write("cualquier cagada")
Cuando leen en el esclavo, si ademas quieren mandar un dato aprovechando el clock qeu genera el master, usan la función spi_read("dato que quiero mandar")
Asi mientras lee el dato que manda el master, que puede ser importante o no, el esclavo va mandando por la otra línea (SDO)el dato que quiere comunicar.
CCS Reference Manual 2012.pdf