TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: murphy9 en 17 de Febrero de 2013, 14:59:59
-
Hola a todos. Como dice el titulo necesito comunicar dos pics mediante spi y debido a la disposicion de pines que debo utilizar y a que debo transmitir 16 bits, la comunicacion debe ser por software. He compilado los siguientes firmwares en donde un 16f877 actua como maestro y un 18f4550 actua como esclavo, y en la simulacion que fago en proteus al utilizar la funcion ch[0]=spi_xfer(); rl programa se pierde para siempre a tal punto que no llega a mostrar nunca nada en el lcd. Imagino que hay un problema de sincronizacion, pero no pude solucionarlo hasta ahora. Adjunto los programas por si alguien puede ayudarme. Gracias
////////////////////////////////////////////////////////////////////////////////////////MAESTRO
#INCLUDE <16F877a.H>
#fuses hs,PUT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#define SPI_CL PIN_C1
#define SPI_DO PIN_C2
#define SPI_RDY PIN_C5
#define prender output_high
#define apagar output_low
#use spi(MASTER,CLK=SPI_CL, DO=SPI_DO, BITS=16, MODE=3, FORCE_SW)
int16 valor,ch[8];
int i,funcion,state;
#int_ext
void EXT_isr(void)
{
spi_xfer(ch[0]);
spi_xfer(ch[1]);
spi_xfer(ch[2]);
spi_xfer(ch[3]);
spi_xfer(ch[4]);
spi_xfer(ch[5]);
spi_xfer(ch[6]);
spi_xfer(ch[7]);
output_LOW(SPI_RDY);
}
void main()
{
portb=portd=porta=porte=255;
output_low(spi_rdy);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
set_tris_a(0x00);
set_tris_b(0x01);
set_tris_d(0x00);
set_tris_e(0x00);
while(1)
{
output_LOW(SPI_RDY);
for(i=0;i<8;i++)
{
ch=i+2;
output_a(ch);
}//for(i=0;i<8;i++)
output_HIGH(SPI_RDY);
delay_ms(200);
}//while()
}//main()
////////////////////////////////////////////////////////////////////////////////////////MAESTRO
////////////////////////////////////////////////////////////////////////////////////////ESCLAVO
#INCLUDE <18F4550.H>
#fuses XTPLL,PLL1,PUT,VREGEN,NOWDT,NOPROTECT,NOLVP,NODEBUG
#use delay(clock=48000000)
#INCLUDE <lcdpf.c>
#define EN_XFER PIN_B3
#define SPI_CL PIN_B4
#define SPI_RDY PIN_B5
#define SPI_DI PIN_B6
#use spi(slave,CLK=SPI_CL, DI=SPI_DI, BITS=16, MODE=3, FORCE_SW)
int16 CH[8];
void main()
{
lcd_init();
OUTPUT_low(EN_XFER);
while(1)
{
while((INPUT(SPI_RDY)==1))
{
OUTPUT_HIGH(EN_XFER);
ch[0]=spi_xfer();
ch[1]=spi_xfer();
ch[2]=spi_xfer();
ch[3]=spi_xfer();
ch[4]=spi_xfer();
ch[5]=spi_xfer();
ch[6]=spi_xfer();
ch[7]=spi_xfer();
OUTPUT_LOW(EN_XFER);
}
lcd_gotoxy(1,1);
printf(lcd_putc,"0:%5LuC 4:%5LuC ",ch[1],ch[5]);
lcd_gotoxy(1,2);
printf(lcd_putc,"1:%5LuC 5:%5LuC ",ch[2],ch[6]);
lcd_gotoxy(1,3);
printf(lcd_putc,"2:%5LuC 6:%5LuC ",ch[3],ch[7]);
lcd_gotoxy(1,4);
printf(lcd_putc,"3:%5LuC 7:%5LuC ",ch[4],ch[0]);
}
}
////////////////////////////////////////////////////////////////////////////////////////ESCLAVO
-
Que tal murphy9!
Con respecto a tu problema amigo, te comento que #use spi() solo opera como master no furula como slave :shock:
Aqui (http://www.ucontrol.com.ar/forosmf/programacion-en-c/empezando-a-usar-el-modulo-spi/) describen un ejemplo sencillo que no funciona, en modo slave.
Yo personalmente hice unas pruebas y pude hacer funcionar el master perfectamente pero el slave no hubo forma utilizando #use spi(), por lo que me parece que el problema puede ser un BUG del ccs :?
Asi que para que te funcione te recomiendo que utilices Setup spi() y de seguro te funcionara bien, en el foro hay ejemplos de ello.
Saludos
-
Acá (http://www.todopic.com.ar/foros/index.php?topic=28952.0) hay 2 ejemplos del modulo SPI entre microcontroladores 16F877.
Asi que para que te funcione te recomiendo que utilices Setup spi() y de seguro te funcionara bien, en el foro hay ejemplos de ello.
En efecto hay que utilizar esta función para configurar el modo en que va operar el microcontrolador (maestro, esclavo) así como la velocidad del protocolo.
-
Muchas gracias por sus respuestas RALF2 y Chenao. Tal parece que se trata de un problema de sincronismos, lo que también puede significar que el #use spi funciona mal en modo slave, ya que probé todas las combinaciones posibles con la instrucción spi_xfer() y nunca pude lograr la comunicación entre ambos pics. Así que finalmente tuve que optar por hacer una rutina que reconstruya la comunicación spi, es decir que el maestro genere el pulso de clock y en el flanco descendente enviar el dato por el pin que yo definiera como pin de salida, así mismo en el esclavo tuve que detectar cada flanco de bajada y copiar en el bit correspondiente de lai variable el valor binario que estaba recibiendo en el pin definido como pin de entrada. A partir de esto fue cuestión de afinar tiempos con las instrucciones delay_us y delay_ms para que la comunicación se pudiera efectuar sin inconvenientes. Nuevamente agradezco su ayuda RALF2 y Chenao.
-
Buena tarde Chenao;
Me gustaria saber si tiene un ejemplo de una comunicación entre dos pic por SPI donde muetre los valores tomados por el ADC del maestro en el lcd del esclavo.
-
Buena tarde Chenao;
Me gustaria saber si tiene un ejemplo de una comunicación entre dos pic por SPI donde muetre los valores tomados por el ADC del maestro en el lcd del esclavo.
Creo que el ejemplo #2 (de este (http://www.todopic.com.ar/foros/index.php?topic=28952.0) hilo) hace la operación que preguntas, no tengo la seguridad si el valor de la lectura ADC lo muestre en una LCD, de todas formas, no creo que exista problema alguno en agregar el modulo LCD, sólo haria falta unas cuantas lineas de más (5 lineas si mucho) y adaptar el respectivo hardware.
-
El problema esta en que el PIC esclavo no puede responder a la velocidad máxima que se configura por defecto para el PIC maestro, por ello en el maestro debes indicar el comando BAUD = XXXXXX un número que sea menor y suficientemente lento para que el pic esclavo lo pueda procesar.