# Comunicacion  I2C



## DARFER (Mar 1, 2006)

hola necesito saber en donde puedo encontrar como se configuran todos lo registros de funcion especifica que van asociados con la comunicacion I2C del pic 16f8xx en donde puedo encontrar información para realizar un proyecto y que ojala sea en español gracias de antemano


----------



## elmasvital (Mar 3, 2006)

bueno no especificas que lenguajes utilizas para la programación... tampoco qué pretendes conectar mediante i2c si una memoria si otro pic etc.

primero si no va a ser una memoria mira en el datasheet si tiene modulo spi, que es la interrupción de llegada de algun byte por el i2c.

En ccs (compilador c) es facil

defines dirección i2c, y patillas, luego si es master, usamos read y write y a correr



```
//VITAL '06
//Ejemplo que demuestra como conectar
//un pic a una memoria i2c y muestra resultados por lcd


#INCLUDE <16F628.H>
#fuses INTrc_io,NOWDT,NOBROWNOUT,NOPROTECT,NOPUT,NOLVP,NOMCLR //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz

#define EEPROM_SDA PIN_A0
#define EEPROM_SCL PIN_A1
//#define EEPROM_SIZE 1024
#define use_portb_lcd

#INCLUDE <2408.C>
#INCLUDE <lcd.c>

void main() {

char caracter[16];
char i,j=0;

   //iniciamos lcd
   lcd_init();
   lcd_putc("\fIniciando...");
   delay_ms(2000);
   lcd_putc("\fIniciando...\n EEPROM");
   init_ext_eeprom();

   while(ext_eeprom_ready())
   {
      for (i=0;i<EEPROM_SIZE;i++)
      {
            if (i>15){
               //desplazamos los caracteres a la izquierda
               for (j=0;j<15;j++)
               {
                  caracter[j]=caracter[j+1];
               }
               caracter[15]= read_ext_eeprom(i);
               printf(lcd_putc, "\fLeido \n%s", caracter);
               delay_ms(500);
            }
            else
               caracter[i]= read_ext_eeprom(i);
      }
   }

}
```


----------



## DARFER (Mar 3, 2006)

elmasvital dijo:
			
		

> bueno no especificas que lenguajes utilizas para la programación... tampoco qué pretendes conectar mediante i2c si una memoria si otro pic etc.



gracias pelao lo que necesito conectar es un micro (16fxx) con una memoria y el programa lo hago en ensamblador  (mplap)  gracias de antemano por la ayuda


----------



## maunix (Mar 3, 2006)

DARFER dijo:
			
		

> elmasvital dijo:
> 
> 
> 
> ...



Te has dignado a leer un poco de los application notes de microchip? Yo tuve que hacer algo asi hace un tiempo y estaba todo en las application notes.


----------



## lalosoft (Mar 4, 2006)

> Te has dignado a leer un poco de los application notes de microchip? Yo tuve que hacer algo asi hace un tiempo y estaba todo en las application notes.



Varios hacen lo mismo no leen manuales ni notas de aplicacion estando alli la solucion a sus dudas.


----------



## galindo_353 (Abr 29, 2008)

hola yo tambien necesito utilizar la comunicacion i2c para pretendo conectar un pic con otro pic y me ayudaria si me das algun ejemplo en mikro c


----------



## richard_qr (Ene 7, 2009)

utilizen un lenguaje como el PICBASIC o el PICC compiler es mas facil hacer una comunicacion I2C, yo tengo uno hecho entre el PIC16F628A y una memoria 24C256 funciona bien solo que el simulador (Proteus) es muy lento y aveces ocurre una falla, talvez alguien me ayude con eso, ha! y variando las resistencias de Pull Up mejora un poco.


----------



## adrianjpc (May 23, 2009)

como utlizar el I2C para realizar la comunicacion entre dos pic 
ayuda!

saludos


----------



## Gregory (Jun 24, 2009)

hola que tal alguien tiene el codigo en ccs de la comunicacion entre 2pics bien sea por i2c o spi
agradezco cualquier ayuda...gracias


----------



## elchelo123 (Ago 3, 2009)

Bueno, estoy probando las comunicación entre dos PIC's, ya me funciono la comunicación SPI.

En un PIC (el maestro) tengo conectado un teclado Hexagesimal, en el otro PIC (esclavo) tengo conectado un LCD 16x2, la idea es que al oprimir una tecla del teclado se vea en el LCD.

Primero el código del Maestro


```
#include<16F877A.h>
#use delay(clock=4000000)


#Byte PORTB = 0x006

#fuses XT,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP


//******Declaración de Funciones****************
char Teclado();



void main()
{
   char Tecla;

   setup_spi(spi_master |spi_h_to_l |spi_clk_div_16 );
   set_tris_a(0x17);
   set_tris_b(0x0F);
   set_tris_c(0b11010111);

   do
   {
      output_low(PIN_A4);
      Tecla = 'F';
      while(Tecla == 'F')
      {
         Tecla = Teclado();
      }
      while('F' != Teclado())
      {  
           output_high(PIN_A4);
      }
      spi_write(Tecla);      
   }while(true);

}


char Teclado()//Función para leer el Teclado Hexa
{
   PORTB = 0xFF;
   delay_ms(10);
   if((PORTB & 0xF0) > 0)
   {
      PORTB = 0x8F;
      delay_ms(10);
      switch(PORTB & 0x0F)
      {
         case 1:{return('*');}break;
         case 2:{return('7');}break;
         case 4:{return('4');}break;
         case 8:{return('1');}break;
         default:{}
      }
      PORTB = 0x4F;
      delay_ms(10);
      switch(PORTB & 0x0F)
      {
         case 1:{return('0');}break;
         case 2:{return('8');}break;
         case 4:{return('5');}break;
         case 8:{return('2');}break;
         default:{}
      }
      PORTB = 0x2F;
      delay_ms(10);
      switch(PORTB & 0x0F)
      {
         case 1:{return('#');}break;
         case 2:{return('9');}break;
         case 4:{return('6');}break;
         case 8:{return('3');}break;
         default:{}
      }
      PORTB = 0x1F;
      delay_ms(10);
      switch(PORTB & 0x0F)
      {
         case 1:{return('D');}break;
         case 2:{return('C');}break;
         case 4:{return('B');}break;
         case 8:{return('A');}break;
         default:{}
      }
   }
   return('F');
}
```

Codigo del Esclavo


```
#include<16F877A.h>
#use delay(clock=4000000)


#define use_portb_lcd = TRUE
#Byte PORTB = 0x006
#include<lcd.c>
#fuses XT,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP




void main()
{
   int Tecla;

   setup_spi(spi_slave | spi_h_to_l | spi_clk_div_16 | spi_ss_disabled );
   set_tris_c(0b11011111);
   
   lcd_init();
   do
   {
      while(spi_data_is_in())
      Tecla = spi_read();
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Recibe: %c",Tecla);
   }while(true);

}
```

Recuerden la conexión se los pines,  C3<->C3  C4<->C5  C5<->C4


Luego les paso el protocolo I2C, cuando lo pruebe.


----------



## Gregory (Ago 5, 2009)

hey men bastante bueno  eso que tienes, pero si el esclavo decidiera responder algo al maestro ¿como haces?...
que instrucion se utilizaria,..., otra cosa, serias tan amable de darme una breve explicacion de lo que hacen la instruccion case, switch, break...algo breve pero didactico  te lo agradezco de antemano ..soy novato


----------



## elchelo123 (Ago 5, 2009)

Bueno, realmente no probe el caso en que el esclavo respondiera, pero para hacerlo se puede hacer lo siguiente:

en el maestro:


```
spi_write(dato);
dato_devuelto = spi_read();
```

y en el esclavo:


```
dato_recibido = spi_read(dato_a_mandar);
```


no estoy seguro, es cuestión de probar, de aca se destaca que el maestro es el que debe empezar la comunicación mandando algo, y el esclavo apenas reciba ese algo podrá responder por medio de la función read (a la vez recibe y envía).


Sobre el switch, hay ocasiones en que respecto a una variable se pueden hacer muchas preguntas como por ejemplo si es 1 ó si es 2 ó si es 3 etc... esto nos llenaría de if dentro de otro if y otro y otro, para este caso lo mejor es usar switch.

en el switch ponemos la variable a analizar, y dentro de este ponemos los diferentes casos


```
switch(variable_a_analizar)
{
       case 0:{//esto se hace si variable_a_analizar vale cero}break;//el break siempre debe ir al final de cada caso.
       case 2:{//esto se hace si variable_a_analizar vale uno}brak;
           .
           .
           .
       case n:{//n es el límite que Ud necesite}break;
       default:{//esto se hace si no se dió ningún caso}//aca no se pone break
}
```

variable_a_analizar puede ser tambien de tipo char y en los casos pregunar case 'A' por ejemplo.

En resumen el switch es la mejor opción para los casos donde a partir del valor de una variable se puedan tomar mas de dos caminos, si son solo dos caminos pues bastará un if.

Espero haber sido de ayuda.

Gracias


----------



## elchelo123 (Ago 5, 2009)

Tuve un pequeño error en lo que coloque anteriormente, puse case 2:{//si la variable_a_analizar vale uno}, corrijo 
case 2:{//si la variable_a_analizar vale dos} ó case 1:{//si la variable_a_analizar vale uno}.


Gracias


----------



## Gregory (Ago 10, 2009)

muchas gracias chelo por tu explicacion  , disculpa porq respondi tarde tengo la computadora en reparacion ... gracias de antemano muy agradecido


----------



## Gregory (Ago 12, 2009)

que tal el chelo, oye ya probe enviar datos del esclavo al maestro  como sugeristes pero nada de nada, el maestro envia pero el esclavo no quiere responder


----------



## elchelo123 (Ago 12, 2009)

Bueno, ya probe el envío esclavo maestro, no estaba tan lejos 



En el Maestro debe poner

Valor_a_leer = spi_read(0); //Se espera el dato y a la vez se activa la señal de reloj (mandando 0) 


En el esclavo

No_importa = spi_read(Dato_a_enviar); //En No_importa quedaría el 0, y a la vez envía el dato del esclavo hacia el maestro.


Espero que ahora si le funcione.


----------



## Gregory (Ago 12, 2009)

ok gracias lo pruebo en unos instantes,.., hey men tu crees que sea posible emular redes ip con pic, un maestro y varios esclavos conectados


----------



## elchelo123 (Ago 12, 2009)

Con la comunicación SPI se pueden crear redes de un PIC maestro y varios PIC esclavos, solo será necesario que del maestro salga una linea de enable a cada esclavo, todos los pics comparten las lineas de clk RDO RDI, entonces cuando se necesite enviar un dato al PIC esclavo numero 1, abra que activar el enable de ese PIC, desactivar el enable de los otros y enviar el dato.


Otro tipo de comunicacion que funciona para hacer una red sería I2C que es muy similar a SPI, en esta se fija una direccion para cada PIC esclavo, asi antes de enviar un dato primero se envía la direccion al esclavo que se quiere comunicar y luego si envía los datos.

también esta la comunicación rs485, en la cual igualmente sirve para crear una red de PICs.


Creo que a eso se refería tu pregunta.


----------



## Gregory (Ago 12, 2009)

ok en lo que respecta a la teoria de estas comunicaciones estoy mas o menos claro he leido bastante el problema es a la hora de programarlas  en ccs..las he programado en assembler pero en c me ha costado ..mi pregunta es si es posible el diseño de redes con el protocolo tcp/ip en los pic, que me dices de eso habras leido algo


----------



## elchelo123 (Ago 13, 2009)

Ya comprendo tu pregunta, si es posible, primero se podría desarrollar el protocolo tcp/ip en el PIC vía software, yo personalmente a nivel de voltajes y tiempos no conozco como funciona el tcp/ip, pero sea como sea creo que esto no sería nada fácil de desarrollar, segundo se podría emplear el siguiente integrado Enc28j60, este integrado se convertiría en el puerto ethernet del PIC, la comunicación entre el integrado y el PIC es vía SPI de está manera si se hace mucho mas posible crear la red tcp/ip que quieres.


----------



## Gregory (Ago 14, 2009)

men y que opinas del pic18f97j60 que tiene un modulo ethernet , lo malo es que estuve leyendo y el ccs no tiene librerias para trabajar con el modulo ethernet


----------



## Gregory (Ago 14, 2009)

Que tal el_chelo, oye men probe la transmision del esclavo al maestro como dijistes y nada , no me da..puedes colgar el programa completo a ver y disculpa la molestia


----------



## elchelo123 (Ago 14, 2009)

Personalmente no conozco el pic18f97j60, pero si ya trae el puerto Ethernet integrado mucho mejor, será cuestion de buscar un buen rato en la red alguna librería ó leer detalladamente el datasheet y desarrollar las funciones necesarias.

Respecto al programa de comunicación SPI no lo pondré todo porque ya lo llevo un poco extenso, pero voy a poner las funciones que nos interesan.


Función de leer en el maestro


```
void Leer_SPI(char *Valor, int n, int f)
{
   int i;   
   for(i = 0;i < n;i++)
   {
      spi_write(f);//Envío un numero que el esclavo interpreta como una instrucción donde le digo que arreglo quiero leer
      delay_ms(5);//Sin estos retardos no me funciona el programa
      spi_write(i);//Envío un numero que el esclavo interpreta como la posición del arreglo que quiero leer
      delay_ms(5);
      Valor[i] = spi_read(0);//Leo
      delay_ms(5);
   }     
}
```


Fucion en el esclavo


```
void Leer()
{
   short int Condicion;
   Condicion = true;
   do
   {
      while(spi_data_is_in())
      {        
         Rx = spi_read();//Leo lo enviado por el maestro
         if(Rx == 25)//el maestro envia 25 cuando quiero terminar la comunicacion
         {
            Cont = 20;
            Condicion = false;
         }
         Switch(Cont)//En el contador llevo la secuencia de lectura, primero leo Instruccion, segundo leo posicion en el vector
         {                  //Si el maestro manda un dato para meter al arreglo entonces abria un tercer paso que es recibir el dato.
            case 0:{//Si Cont es 0 es porque se leyó la instruccion
                     Instr = Rx;
                     Cont++;
                   }break;
            case 1:{//Si Cont es 1 es porque se leyó la posición del arreglo
                     Address = Rx;
                     if(Instr == 10)//Si la instruccion es 10 es porque el maestro quiere leer el arreglo ValT
                     {
                        Rx = spi_read(ValT[Address]);
                        Cont = 0;
                     }
                     else
                     {
                        if(Instr == 11)//Si la instruccion es 11 es porque el maestro quiere leer el arreglo ValL
                        {
                           Rx = spi_read(ValL[Address]);
                           Cont = 0;
                        }
                        if(Instr == 12)//Si la instrucción es 12 es porque el maestro quiere enviar un dato
                        {
                           Cont++;
                        }
                     }
                   }break;
             case 2:{    //Si el maestro envía dato, se recibe y se guarda
                        Dato = Rx;                          
                        Val2[Address] = Dato;         
                        Cont = 0;
                    }break;
         } 
        }         
   }while(Condicion);
}
```


Trate de comentar un poco el código para darme a entender que quería hacer ya que la función en el esclavo puede ser un poco confusa.


----------



## Gregory (Ago 14, 2009)

Men , con respecto al puerto ethernet, estuve leyendo un buen rato y parece que ccs no tiene librerias para el manejo de este puerto , de todas maneras si consigues alguna por alli de antemano te agradezco,..., por los momentos voy a seguir estudiando l que me dejastes de spi
..nos vemos suerte y gracias


----------



## Gregory (Ago 14, 2009)

men, mejor para no molestarte mas con esto de las comunicaciones seriales, te pido el favor que me envie tus apuntes o la base que te permitio programar estas comunicaciones en ccs,.., lo que tengas de spi e i2c.,.,no te pido codigos solo apuntes donde expliquen el funcionamientos de las instrucciones por ejemplo....este es mi correo eldegreg@hotmail ..te lo agradezco estas comunicaciones me tienen loco.., las entiendo pero no las he podido programar en c


----------



## Ritos (Ago 17, 2009)

que tal. he corrido el jemplo de chelo para pic masestro y pic esclavo, pero no veo que aparezca el pin cs, y al simular en proteus aparece un error logico, quiza debido a las resistencias pull up de los pines sdo sdi clk. he usado un key phone de proteus en el puerto b. y el lcd en el puerto b.

muchas gracias


----------



## elchelo123 (Ago 17, 2009)

Supongo que cuando dice el pin cs se refiere al de selección de esclavo, no hay selección de esclavo porque solo se está haciendo entre dos pics y como puede ver en el codigo del esclavo está este párametro "spi_ss_disabled" que quiere decir que no se va a usar la selección de esclavo, efectivamente el teclado se usa en el puerto b del maestro y el LCD en el puerto b del esclavo, resistencias de pull up no entiendo a que se refiere, las resistencias de pull up se usan en I2C, de todas maneras con seguridad funciona porque yo lo monté.


----------



## Ritos (Ago 17, 2009)

gracias por responder chelo

te adjunto una imagen de la conexion en proteus, en el codigo solo se utilizan 4 pines, los ultimos del puerto b, com esta en tu codigo para el manejo del teclado, pero no creo que ese sea el problema, en el codgio veo que has configurado los pines de entrada y de salida para sdo, sdi, etc. me gustaria si pudieras postear una imagen en proteus.

ritos


----------



## Gregory (Ago 19, 2009)

que tal el chelo gracias a dios y a tu ayuda , hice algo parecido a lo tuyo pero conecte el teclado en el esclavo y la lcd esta en el maestro,..,pero resulta  que debo presionar la tecla varias veces para que esta pueda mostrarse en la lcd ....tienes alguna idea de que pueda ser..¿tal vez te ocurrio lo mismo?


----------



## elchelo123 (Ago 19, 2009)

Bueno, andaba un poco perdido, primero para Ritos, no tengo diagrama en proteus pero tratare de describir la conexion del teclado en el maestro (yo use teclado 4x4) en los 4 primeros pines RB0 RB1 RB2 RB3 poner resistencias 10k a tierra igualmente conectar las filas del teclado, en los 4 pines restantes conectar resistencias de 1k en serie con las columnas del teclado.


Para Gregory, si, si me ha pasado, eso es cuestion de jugar con los retardos aumentelos un poco.


----------



## Gregory (Ago 21, 2009)

el_chelo sera que me puedes abrir la mente con los retardos, que me sugeristes con respecto al problema que te comente de que la tecla debe ser pulsada varias veces he intentado de varias maneras pero nada que ver...gracias


----------



## elchelo123 (Ago 23, 2009)

Si quiere pegue el codigo para mirarlo, y asi mas facil le digo.


----------



## sebitronic (Ene 7, 2010)

galindo_353 dijo:


> hola yo tambien necesito utilizar la comunicacion i2c para pretendo conectar un pic con otro pic y me ayudaria si me das algun ejemplo en mikro c



yo lo he echo en asm no es muy dificil  y la ventaja que presenta con respecto a acerlo en basic es que consumem menos memoria y tiempo de ejecucion. en los microcontroladores PIC16F87x es muy simple, solo seteas uno como master y otro como slave (creo que son los ultimos bits del registro sspcon) y despues manejandolo por las interrupciones podes hacer otras cosas con el micro mientras recive o transmite informacion. Otra ventaja que implementan estos micros es que soportan direcciones de 10 bit's pudiendo conectar en teoria hasta 1024 micros en el mismo bus.
 Si necesitas ayuda avisame que yo en este protocolo tengo algo de experiencia, es mas, estoy armando un microbot de sumo e internamente controla todo por el bus I2C con los maravillosos integrados de PHILIPS PCF8574 y PCF8591.


----------



## nahumof (May 2, 2010)

una dudilla compañeros
estaba empezando a hacer comunicacion spi con ccs y me ha parecido interezante lo que aqui se postea ya que no he logrado una comunicacion aceptable entre master y slave, mi problema es este, el master no puede leer si no envia antes algo???

y que diferencia de lo que aqui se postea tiene utilizar las funciones de la siguiente manera:
MASTER:
recive=spi_read(send);   
SLAVE:
from_send = spi_read(to_recive);

segun la teoria al utilizar esta funcion en el master envia el valor send y lee 1 dato que guarda en recive. el problema es que si envia send al slave pero lee 2 valores send y recive... 

el esclavo no tiene problemas si recive y si envia la info y es correcta.

cualquier alluda sirve, saludos y gracias desde ya.


----------



## nahumof (May 3, 2010)

bueno pues... hasta que alguien me contradiga

"If this device is the master then either do a SPI_WRITE(data)  followed by a SPI_READ() or do a SPI_READ(data).  These both do the same thing  and will generate a clock.  If there is no data to send just do a SPI_READ(0) to  get the clock"
al parecer ahun que ccs diga que se puede usar ambiguamente las instrucciones resultase que no!!!

si se utiliza un read y un write en el master en el slave se tiene que usilizar un read y un write, no se pueden pasar datos correctos si se envia en el read un argumento de regreso al master o al slave.

y si se utiliza un read con argumento de retorno en el master se debe tener un read con argumento de retorno en el slave.

todo esto es referente a la comunicacion BIDIRECCIONAL y no aplica si se maneja comunicacion solo en un sentido en donde si se pueden convinar instrucciones.

a si y no ocupa delay!!! ni para leer ni para escribir.

opcion 1:
master  & slave:
         data_to_recive = spi_read(data_to_send);

opcion 2:
 master:
          spi_write(data_to_slave);       
          data_from_slave=spi_read(0);

slave:
          data_from_master=spi_read(0); 
          spi_write(data_to_master); 

estoy en lo cierto?


----------



## JPTZ (Ene 2, 2012)

Hola a todos!. Quería ver si alguien me podía ayudar, estoy tratando de establecer una comunicación por I2C entre un PIC 18F4520 y un oscilador LTC6904. Estoy programando en CCS, el problema que tengo es que se me clava el oscilador en 1KHz, o sea no estan llegando bien los datos, o no esta bien establecida la comunicación. Si alguien puede ayudarme se lo agradezco, luego voy a subir el código de lo que hice hasta ahora. Gracias y saludos a todos!


----------



## Gudino Roberto duberlin (Ene 2, 2012)

Hola amigo, revisa en el datasheet del oscilador la velocidad de transferencia de datos y el tamaño de palabra.


----------



## JPTZ (Ene 9, 2012)

Lo revise, le agregué un retardo luego de la transferencia, que no lo había contemplado, pero sigue si andar...  Gracias Roberto


----------



## Gudino Roberto duberlin (Ene 9, 2012)

Amigo, otro detalle a comtemplar, los datos son reconocidos como VERDADERO, o como INVERTIDO?, es decir un dato digital "1" es reconocido como nivel alto o nivel bajo?.


----------



## JPTZ (Ene 16, 2012)

La verdad es que cuando programo en C me olvido de esas cosas que por ahi contemplaba en asm, puede ser que haya algún FUSE que no tuve en cuenta o alguna definición que no puse q haga q no se establezca bien la comunicación?. Gracias!.


----------



## JPTZ (Ene 17, 2012)

el problema es q el PIC no me genera la señal de clock, nose porque... alguien sabe porqeu puede ser?


----------

