Autor Tema: Ayuda sobre I2C  (Leído 2257 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Petrihp

  • PIC10
  • *
  • Mensajes: 8
Ayuda sobre I2C
« en: 11 de Julio de 2004, 17:02:00 »
Estoy desarrollando un proyecto en el cual implemento control de un motor, interfaz de usuario, y el codigo ya esta muy grande. Estoy utilizando un PIC 16F877 y se me quedo corto por lo cual necesito de otro y comunicarlos mediante I2C, para en el ejecutar algunas funciones. Nunca he manejado este sistema de comunicación y por lo que he investigado hice el siguiente programa para probar la comunicación entre los 2 PIC, pretendo enviar un dato al esclavo y que el luego me retorne el mismo dato enviado yel maestro lo muestra en el LCD.


Para el PIC Maestro

#include <16f877.h>
#include <lcd.c>

#fuses HS,NOLVP,NOWDT,PUT
#use delay(clock=20000000)
#use i2c(Master, SDA=PIN_C4, SCL=PIN_C3)

main() {

int Aux;
byte Entra,Sale;
SET_TRIS_C(0x18); // configura pines PIN_C4 y PIN_C3 como salida

lcd_init();                //Inicializa el LCD
lcd_putc("f");          // Borra el LCD
printf(LCD_PUTC, "Inicio";
Delay_ms(3000);

Sale =0;

while (TRUE) {
Sale += 1;
i2c_start(); //Condicion de inicio
i2c_write(0x02); //Esta es la direccion del esclavo
i2c_write(Sale); //Envia algun dato a el esclavo
i2c_stop(); //Condicon de parada

aux = Sale;
printf(LCD_PUTC, "Dato enviado = %d", Aux);
delay_ms(2000);

i2c_start(); //Condicion de inicio
i2c_write(0x02); //Esta es la direccion del esclavo
Entra = i2c_read(); //Espera a que el esclavo responda
i2c_stop(); //Condicon de parada

Aux = Entra;
lcd_gotoxy(1,1);
printf(LCD_PUTC, "Dato Recivido= %d",Aux);
delay_ms(2000);

if (Sale==11)
Sale=0;
      }
}

Para el PIC esclavo

#include <16f877.h>

#fuses HS,NOLVP,NOWDT,PUT
#use delay(clock=20000000) //,RESTART_WDT)

#use i2c(slave, SDA=PIN_C4, SCL=PIN_C3, address=0x02)


#define Led_1 PIN_B5
#define Led_2 PIN_B6
main() {

byte Entra, Sale;
int Aux;

SET_TRIS_C(0x18);


while (TRUE) {

i2c_start(); //Condicion de inicio
Entra = i2c_read(); //Espera a que el esclavo responda
i2c_stop(); //Condicon de parada

Sale = 22;
i2c_start(); //Condicion de inicio
i2c_write(Sale);
i2c_stop(); //Condicon de parada

if (Entra == 5) {  // Si el dato recivido es 5 enciendo unos LED

      output_low(Led_1);
      output_high(Led_2);
      delay_ms(2000);
      output_high(Led_1);
      output_low(Led_2);
      delay_ms(2000);
}

}


}

Para las conexiones coloque una resistencia pull-up de 10K a VCC y un condensador de 40 pF a tierra, (lo vi en el datasheet del PIC)

Lo pruebo y no me manda ni recive ningun dato, no se que mas consideraciones halla que tener en cuenta.

Les agradesco las sugerencias.


Desconectado pikman

  • Moderador Local
  • PIC24F
  • *****
  • Mensajes: 679
RE: Ayuda sobre I2C
« Respuesta #1 en: 11 de Julio de 2004, 20:57:00 »
Petrihp, bueno en principio te aconsejo, no postear mas de una vez el mismo tema, te conteste ya en el anterior donde estabas pidiendo ayuda, en pincipio te recomiendo ver el manual de CCS, si no lo tienes puedes bajarlo desde www.ccsinfo.com, ademas puedes mirar el archivo ex_slave.c que es un ejemplo de esclavo simulando una memoria 24C01 con un PIC16F877 o similar, debes si no quieres complicarte e independizar los tiempos  de comunicacion de tu proceso, utilizar la interrupcion de MSSP, aqui te pego el codigo del ejemplo que funciona, entonces, para porbarlo puedes hacer lo que recomienda el ejemplo, cargas el codigo en el que va a ser esclavo, y en el master incluyes el controlador para memoria 24c01 y escribes y lees, creo que en base a este ejemplo  puedes tomar referencia y utilizar este mecanismo para tu proyecto, yo lo utilize comunicando 4 micros y funciona muy bien, espero que te sirva................

saludos

Ariel



#if defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)  

#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0)

typedef enum {NOTHING, CONTROL_READ,
              ADDRESS_READ, READ_COMMAND_READ} I2C_STATE;

I2C_STATE fState;
byte address, buffer[0x10];


#INT_SSP
void ssp_interupt ()
{
   byte incoming;

   if (i2c_poll() == FALSE) {
      if (fState == ADDRESS_READ) {  //i2c_poll() returns false on the
         i2c_write (buffer[address]);//interupt receiving the second
         fState = NOTHING;           //command byte for random read operation
      }
   }
   else {
      incoming = i2c_read();

      if (fState == NOTHING){
         fState = CONTROL_READ;
      }
      else if (fState == CONTROL_READ) {
         address = incoming;
         fState = ADDRESS_READ;
      }
      else if (fState == ADDRESS_READ) {
         buffer[address] = incoming;
         fState = NOTHING;
      }
   }
}


void main ()
{
   int i;

   fState = NOTHING;
   address = 0x00;
   for (i=0;i<0x10;i++)
      buffer = 0x00;

   enable_interrupts(GLOBAL);
   enable_interrupts(INT_SSP);

   while (TRUE) {}
}


saludos
PikMan

Desconectado Petrihp

  • PIC10
  • *
  • Mensajes: 8
RE: Ayuda sobre I2C
« Respuesta #2 en: 12 de Julio de 2004, 22:09:00 »
Escrito originalmente por Petrihp


Gracias pikman por tu comentarios, la verdad es que ya habia visto este programa en las ayudas del CCS pero la verdad no lo habia entendido muy bien y al respecto tengo las siguientes dudas:

1. Se debe implemetar la interrupción tanto en el maestro como en el esclavo

2. El dato que me llega a donde queda almacenado en incoming o en buffer[] y para que utilizo este array de 10 posiciones. o en que posición queda almacenado el dato

3. Si deseo escribir un dato solo escribo en cualquier parte del main o de una funcion.

i2c_write (Dato_a_enviar);

Y por que en la interrupción me aparace la instrucción de escritura
 i2c_write (buffer[address]);

En general te pido el favor que me des alguna orientación sobre el programa ejemplo.

Te agradezco por tu gran ayuda y constante colaboración





Desconectado pikman

  • Moderador Local
  • PIC24F
  • *****
  • Mensajes: 679
RE: Ayuda sobre I2C
« Respuesta #3 en: 12 de Julio de 2004, 22:54:00 »
Escrito originalmente por Petrihp
Escrito originalmente por Petrihp


Gracias pikman por tu comentarios, la verdad es que ya habia visto este programa en las ayudas del CCS pero la verdad no lo habia entendido muy bien y al respecto tengo las siguientes dudas:

1. Se debe implemetar la interrupción tanto en el maestro como en el esclavo

[color=0000FF][/color]

NO, EL MAESTRO PREGUNTA EN FORMA SINCRONA DENTRO DE TU PROGRAMA CUANDO ES NECESARIO, PERO EL ESCLAVO DEBE ATENDER SIEMPRE AL MAESTRO POR ESO ES LA RECOMENDACION DE USAR LA INTERRUPCION EN EL SLAVE, PERO TAMBIEN SE PUEDE HACER POLLING SOLO QUE SE COMPLICA MAS TU PROGRAMA.


2. El dato que me llega a donde queda almacenado en incoming o en buffer[] y para que utilizo este array de 10 posiciones. o en que posición queda almacenado el dato

EXACTAMENTE LE DATO LO TENDRAS EN EL STRING BUFFER QUE
SI TE FIJAS AL PRINCIPIO SE DEFINEN 16 POSICIONES, ESTO ES
POR QUE EL EJEMPLO PRETENDE SIMULAR A UNA MEMORIA
24C01 QUE ES DE 16 BYTES, PERO PODES HACER MAS GRANDE ESTE
BUFFER SIN PROBLEMAS.

3. Si deseo escribir un dato solo escribo en cualquier parte del main o de una funcion.

BUENO, LA FUNCION LA PODES LLAMAR DESDE EL MAIN, O DESDE CUALQUIER LADO,  EN VEZ DE COMPLICARTE CON EL MANEJO DE LAS INSTRUCCIONES DEL I2C, INCLUI EN EL PROGRAMA DEL MASTER EL DRIVER DE LA MEMORIA 24C01, ENTONCES LAS FUNCIOENS SERAN

////   init_ext_eeprom();    Call before the other functions are used  ////
////                                                                   ////
////   write_ext_eeprom(a, d);  Write the byte d to the address a      ////
////                                                                   ////
////   d = read_ext_eeprom(a);  Read the byte d from the address a     ////
////                                                                   ////
////   b = ext_eeprom_ready();  Returns TRUE if the eeprom is ready    ////
////                            to receive opcodes                     ////


Y LISTO, ENTONCES CON ESTO, PODES ENVIAR Y LEER EL BUFFER
DE TU SLAVE, SENCILLAMENTE LEYENDO O ESCRIBIENDO LA POSICION 0x00 A 0x10, NO SE SI ENTENDES AHORA, BUENO
CON RESPECTO AL EJEMPLO POSTEA LAS LINEAS QUE NO ENTEDES,
CUIDADO CON EL ANSI C, EN CCS HAY MUCHAS FUNCIONES Y LIBRERIAS QUE HACEN LAS COSAS MAS SENCILLAS.

i2c_write (Dato_a_enviar);


Y por que en la interrupción me aparace la instrucción de escritura
 i2c_write (buffer[address]);

BUENO ES QUE EN REALIDAD TODA LA RUTINA DE INTERRUPCION ES LA FUNCION DE ESCRITURA/LECTURA, Y CADA VEZ QUE LLEGA UN DATO AL MSSP, ENTRA A LA FUNCION Y VERIFICA QUE OPERACION DEBE REALIZAR.

En general te pido el favor que me des alguna orientación sobre el programa ejemplo.

TE RECOMIENDO PROBAR EL MASTER INCLUYENDO 24C01.C Y EX_SLAVE.C EN EL ESCLAVO, PODES SIMULARLO EN PROTEUS
PERFECTAMENTE.

Te agradezco por tu gran ayuda y constante colaboración

NO HAY PORQUE, ESTE FORO ES UNA MARAVILLA, ES UN GRAN HONOR PODER DEVOLVER ALGO DE TODO LO QUE HE APRENDIDO.

SALUDOS

ARIEL






saludos
PikMan