TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: juanelete en 07 de Marzo de 2005, 16:31:00
-
Hola a tod@s:
LLevo varia semanas intentando comunicar dos PIC mediante I2C, y por fin lo he conseguido.
He descubierto que hay un par de "trucos" para que funcione correctamente.
Os pongo unos ejemplos simplificados al maximo:
El master:
///////////////////////////////////////////////////////////////////////////////////////////////////////
// INT_SSP_MASTER //
// //
// Comunicacion I2C entre dos PIC 16F876 //
// //
// Este es el que va a actuar como master. Enviara secuencialmente una serie //
// de numeros que iran incrementandose de uno en uno. //
// //
//////////////////////////////////////////////////////////////////////////////////////////////////////
#INCLUDE <16F876.H>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#ORG 0x1F00,0x1FFF {} //Necesario para bootloader
#use delay(clock=20000000)
#use I2C(master,sda=PIN_C4,scl=PIN_C3)
//Leds que se iluminaran
#DEFINE LED1 PIN_A1 //PIN 3
#DEFINE PIC2 0x02 //Direccion dispositivo PIC 2 (esclavo)
void main()
{
int8 dato=0;
delay_ms(1000); //Hay que dejar tiempo que se inicialize el esclavo
while(1)
{
output_high(PIN_A1);
delay_ms(1000);
i2c_start(); // Condicion Inicio
i2c_write(PIC2);// Direccion dispositivo
delay_ms(3); // *** Necesario ***
i2c_write(dato);// dato
delay_ms(3); // *** Necesario ***
i2c_write(++dato);// dato
i2c_stop(); // Stop
output_low(PIN_A1);
delay_ms(1000);
}
}
Y el Esclavo:
///////////////////////////////////////////////////////////////////////////////////////////////////////
// INT_SSP_SLAVE //
// //
// Comunicacion I2C entre dos PIC 16F876 //
// //
// Este es el que va a actuar como ESCLAVO. Recibira secuencialmente una serie//
// de numeros que iran incrementandose de uno en uno y los mostrara en //
// pantalla //
//////////////////////////////////////////////////////////////////////////////////////////////////////
#INCLUDE <16F876.H>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#ORG 0x1F00,0x1FFF {} // Necesario para bootloader
#use delay(clock=20000000)
#DEFINE PIC2 0x02
#use I2C(slave,sda=PIN_C4,scl=PIN_C3,address=PIC2)
#define use_portb_lcd TRUE //Necesario si usamos el portB para el LCD, y que sea compatible con LCD.C
#include <LCD.C>
//VARIABLES GLOBALES
int8 buffer[2];
int1 recibido=0;
#int_ssp //Rutina Interrupción I2C
void int_sspi2c()
{
disable_interrupts(int_ssp); // *** Necesario ***
buffer[0]=i2c_read();
buffer[1]=i2c_read();
recibido=1;
}
void main()
{
delay_ms(50);
lcd_init();
lcd_putc("fPreparado...
");
delay_ms(300);
enable_interrupts(int_ssp);
enable_interrupts(global);
while(1)
{
if(recibido==1)
{
printf(lcd_putc,"fb[0]=%U b[2]=%u",buffer[0],buffer[1]);
recibido=0;
enable_interrupts(int_ssp); // *** Necesario ***
}
}
}
Los "trucos" a los que me referia antes son los siguientes:
Es fundamental poner un pequeño retardo despues de enviar la direccion del dispositivo:
i2c_write(PIC2); // Direccion dispositivo
delay_ms(3); // *** Necesario ***
Y luego tambien poner un retardo despues de enviar cada dato:
i2c_write(dato);// dato
delay_ms(3); // *** Necesario ***
El otro "truco" es que, en el esclavo, justo cuando se entra en la interrupcion SSP hay que desactivarla antes de hacer nada:
disable_interrupts(int_ssp); // *** Necesario ***
y luego cuando ya se ha terminado de procesar todos los datos volver a activarla:
enable_interrupts(int_ssp); // *** Necesario ***
Os puedo asegurar que estos ejemplos, asi, funcionan perfectamente, si se quitan los retardos o no se desactiva la int, no funcionan. Palabrita de "Niño Jesus".
Saludos
-
Jeje no es la mala... aver si tengo tiempo para testearlo en proteus.
Aun asi, lo que me mosquea son esos delays... 6ms por dato? Eso reduce el bitrate a 160 bps... y eso en ciertas aplicaciones pueSsSsSs...
No se puede reducir ese delay?
salu2!
-
En teoría deberia funcionar sin los delays, aunque no pongo en duda lo que dice juanelete. Yo hice hace tiempo un ejemplo muy sencillo con simulación en proteus, pero sin usar la interrupción. Lo tengo en esa cosa que llamo web, que es tan cutre y nunca acabo, pero por si sirve de ayuda os lo pego aquí.
http://www.telecable.es/personales/trelles2
Es muy sencillo, pero si necesitais otro con más detalle, recuerdo que en el foro había varios ejemplos, incluso uno comunicando 3 pics, pero no recuerdo donde está posteado.
Un saludo.
-
En la carpeta de ejemplos C hay un par de ejemplos
http://personal.auna.com/asencio5/Ejemplos%20C/I2C/
-
Habeis hecho alguna comunicación I2C entre una PIC y una memoria? la que tengo es la 24LC512 .
Es que lo estoy intentando y no hay manera.