PIC16f873A como esclavo I2C

Hola a todos:

estoy intentando comunicar 2 pic por i2c, pero tengo algún problema con el esclavo. El esclavo debe leer una señal analogica que la convierto a 8bits, y ese valor tiene que leerlo el maestro por i2c.
Lo estoy intentando en CCS, y las rutinas para el maestro si que las se, pero lo que no se es como le digo al esclavo donde tiene que meter ese valor para que lo pueda coger el maestro.
¿Alguien me puede echar una mano? gracias!!
 
El maestro tiene que enviar un comando que el esclavo interpreta como "enviar resultado", posteriormente el esclavo toma ese valor de su memoria RAM y lo envia por el puerto I2C
 
Hola rachelies podrias compartir como lo solucionaste es q me sucede exactamente lo miso; le envio un dato desde el pic master al esclavo y este simpre envia un dato igual a 6 (binario). Gracias
 
Hola. Pues mira, al final no es tan complicado.
En el pic que quieras tener como esclavo, lo configuras logicamente como esclavo. Yo tengo esto en el esclavo, donde le digo que es esclavo, los pines sda y scl, velocidad lenta (aun no he probado la rapida), forzar el i2c por hardware y la direccion que he queridopara este pic, 0x0A o 10 en decimal:

Código:
#use i2c(SLAVE,SCL=PIN_C3,SDA=PIN_C4,SLOW,FORCE_HW,ADDRESS=0x0A)

Este programa para el esclavo lo que hace es leer una entrada analogica y tenerla disponible para cuando el maestro se la solicite:

Código:
#include <16F873A.h>
#device ADC=8
#fuses HS,NOWDT,PUT
#use delay(clock=20000000)
#use i2c(SLAVE,SCL=PIN_C3,SDA=PIN_C4,SLOW,FORCE_HW,ADDRESS=0x0A)
 
int pichB,state,buffer[0x01],adress;
#INT_SSP
void ssp_interrupt()
{ output_high(PIN_A2);
 state=i2c_isr_state();
 if(state==0x80){
  i2c_write(buffer[0x00]);
  output_high(PIN_A1);
 }
}
void main(){
 set_tris_A(0b00000001);
 setup_adc_ports(AN0);
 setup_adc(ADC_CLOCK_INTERNAL);
 set_adc_channel(0);
 delay_us(20);
 pichB=read_adc();
 enable_interrupts(GLOBAL);
    enable_interrupts(INT_SSP);
 
 adress=0x00;
 
 while(TRUE){
 
 set_adc_channel(0);
 delay_us(20);
 pichB=read_adc();
 buffer[0x00]=pichB;
 delay_ms(1);
 output_high(PIN_A3);
 }
}

Hasta aqui el esclavo. El maestro se configura como maestro:

Código:
#use i2c(MASTER,SCL=PIN_B1,SDA=PIN_B0,SLOW,FORCE_HW)

y cuando quiero leer el dato que está en el esclavo utilizo esto en el programa:

Código:
i2c_start();
  i2c_write(0x0A+1);
  pichB=i2c_read(0);
  i2c_stop();

Y ya está. Si hace falta alguna aclaración más no dudeis en preguntar.
Saludos
 
Hola rachelies, gracias por exponer tu codigo, hice algunas modificaciones en mi codigo pero aun persiste el error; el esclavo envia el dato pero el master sigue interpretando el mismo valor=0110 en el puerto D (d0-d7), esto sucede en el montaje fisico.
Lo que sucede es muy extraño simulando en proteus7.6 sp4 el codigo funciona como lo tengo especificado en el codigo, pero el montaje real no anda tan solo se accionan los leds indicando en binario 6, adjuntare el codigo y el proteus para ver si pueden ayudarme a decifrar lo q sucede.


En el montaje fisico utilizo pic 18F4550, resistencias pullup de 4.7Kohm tambien prove con resistencias de 1.8Kohm que lei q era en critico pero sigue sin andar no puedo realizar comunicacion I2c master esclavo-esclavo master.
En el montaje fisico ocurre lo siguiente:

-El pin d0 del pic esclavo se pone en alto al recibir el dato de entrada que viene del maestro. y se pone en alto en el esclavo el pin correspondiente al terminal de entrada (en este caso A0).
-un tiempo despues el pin d1 del pic esclavo se pone en alto al recibir el dato de salida que viene del maestro, seguidamente se muestra en el puerto d del maestro la dirrecion del pic en el cual se debe leer el retorno de la señal(02 en este caso, pinD1 en alto).
-un tiempo despeus el Master realiza la lectura al slave(se indica con ra0 en alto), en el puerto c del esclavo mostramos el valor de la lectura(para este caso lee el pin A1) el cual sin importar la posicion del sw siempre vale 1, y en el puerto d del maestro mostramos dicho valor, el cual no coincide y siempre obtenemos un 6=0110.


Agradezco alguna ayuda
 

Adjuntos

  • i2cexp.rar
    64.6 KB · Visitas: 277
Última edición:
Hola, estoy realizando un proyecto con comunicación I2C entre dos PIC 18F4550, en CCS, la programación aparentemente está bien, funciona bien en simulación Proteus, pero al implementarlo en protoboard no funciona, no realiza la comunicación I2C. También he estado probrando entre PIC18F4550 y PIC16F877A, la simulación sale OK, al implementarlo no funciona. Por favor, alguien me puede ayudar pasándome un ejemplo con I2C entre dos PICs 18F4550. Se lo agradecería mucho.

Zarbio Rómulo Ordóñez Dávila.
 
Hola. Pues mira, al final no es tan complicado.
En el pic que quieras tener como esclavo, lo configuras logicamente como esclavo. Yo tengo esto en el esclavo, donde le digo que es esclavo, los pines sda y scl, velocidad lenta (aun no he probado la rapida), forzar el i2c por hardware y la direccion que he queridopara este pic, 0x0A o 10 en decimal:

Código:
#use i2c(SLAVE,SCL=PIN_C3,SDA=PIN_C4,SLOW,FORCE_HW,ADDRESS=0x0A)

Este programa para el esclavo lo que hace es leer una entrada analogica y tenerla disponible para cuando el maestro se la solicite:

Código:
#include <16F873A.h>
#device ADC=8
#fuses HS,NOWDT,PUT
#use delay(clock=20000000)
#use i2c(SLAVE,SCL=PIN_C3,SDA=PIN_C4,SLOW,FORCE_HW,ADDRESS=0x0A)
 
int pichB,state,buffer[0x01],adress;
#INT_SSP
void ssp_interrupt()
{ output_high(PIN_A2);
 state=i2c_isr_state();
 if(state==0x80){
  i2c_write(buffer[0x00]);
  output_high(PIN_A1);
 }
}
void main(){
 set_tris_A(0b00000001);
 setup_adc_ports(AN0);
 setup_adc(ADC_CLOCK_INTERNAL);
 set_adc_channel(0);
 delay_us(20);
 pichB=read_adc();
 enable_interrupts(GLOBAL);
    enable_interrupts(INT_SSP);
 
 adress=0x00;
 
 while(TRUE){
 
 set_adc_channel(0);
 delay_us(20);
 pichB=read_adc();
 buffer[0x00]=pichB;
 delay_ms(1);
 output_high(PIN_A3);
 }
}

Hasta aqui el esclavo. El maestro se configura como maestro:

Código:
#use i2c(MASTER,SCL=PIN_B1,SDA=PIN_B0,SLOW,FORCE_HW)

y cuando quiero leer el dato que está en el esclavo utilizo esto en el programa:

Código:
i2c_start();
  i2c_write(0x0A+1);
  pichB=i2c_read(0);
  i2c_stop();

Y ya está. Si hace falta alguna aclaración más no dudeis en preguntar.
Saludos



Amigo llevo cuatro horas intentando hacer la comunicación... y resulto que tenia un error tonto me faltaba dat=i2c_read(0); o lo tenía pichB=i2c_read(); ... se bloqueaba en el momento en el que el esclavo enviava el dato.

gracias.
 
Amigo llevo cuatro horas intentando hacer la comunicación... y resulto que tenia un error tonto me faltaba dat=i2c_read(0); o lo tenía pichB=i2c_read(); ... se bloqueaba en el momento en el que el esclavo enviava el dato.

gracias.

Denada!!!
Yo he probado también la opción de forzar la comunicación por software y utilizando otros pines del pic, y funciona todo perfectamente.
Un saludo a todos
 
Muchachos muchas gracias por todo, me han dado la mano y me han ayudado muchisimo en un proyecto que estoy realizando con el i2c, Muchas gracias por sus comentarios, y gracias por compartir sus codigos y experiencias. Estos son los principios de GNU.... el codigo Libre... Ademas los invito a que se den una pasadita por Linux ubuntu, es muy bueno...
 
hola he estado modificando el codigo y adaptarlo a mi proyecto,el proyecto q estoy realizando consiste en que el master escribe un comando en el esclavo ,el esclavo valida este comando mediante un if y si lo valida lee una entrada analoga AN0 y lo envia hacia el master ,en ese momento el master cambia a lectura ,el codigo que he realizado lee el dato del sensor pero no valida el comando que envia el master,si me podrian ayudar se los agradeceria,aqui les pongo el codigo:

Código:
#include <16F873A.h>
#device ADC=10
#fuses HS,NOWDT,PUT
#use delay(clock=40000000)
#use i2c(SLAVE,SCL=PIN_C3,SDA=PIN_C4,SLOW,FORCE_HW,ADDRESS=0XA0)
#define PORTB 0X06
//int dato; 
int p;
int q;
byte state,buffer[0x01],adress,incoming;
#INT_SSP
void ssp_interrupt()
{ 
 state=i2c_isr_state();
 
 
 if(state < 0x80) //Master is sending data
  {
    if(state == 0)
    {
    
    }
    if(state == 1)  //First received byte is address
    {
      incoming = i2c_read();
      adress = incoming;
    }
    if(state == 2)  //Second received byte is data
    {
      incoming = i2c_read();
      buffer[adress] = incoming;
    
         }
    }
  
 
 
   if(state==0x80){
    i2c_write(buffer[0x00]);
                }
}
void main(){
 set_tris_A(0b00000111);
 set_tris_B(0x00);
 setup_adc_ports(AN0);
 setup_vref(FALSE); 
 setup_adc(ADC_CLOCK_INTERNAL);
 set_adc_channel(0);
 delay_us(20);
 enable_interrupts(GLOBAL);
 enable_interrupts(INT_SSP);
 adress=0x00;
  #asm
      clrf PORTB;
   #endasm
      

 while(TRUE){
 
        if (incoming==5) 
         
            set_adc_channel(0); 
            delay_us(20);
            q = read_adc();                  //Lectura canal0
            p = (q*(0.48875));               //Conversión a tens;
            buffer[0x00]=p;
         
         }
    }

#include <16f877.h>
       #device adc=10
       #include <math.h>
       #Fuses XT,NOWDT, NOPROTECT, NOCPD, NOBROWNOUT, NOLVP, NODEBUG, NOWRT
       #use delay(clock=4000000)
       #use i2c(MASTER, SDA=PIN_C4, FAST, SCL=PIN_C3, FORCE_HW)//NOFORCE_SW)
       #use standard_io(C)
       #use fast_io(a)
       #use fast_io(d)
       #include <lcd.c>
       

      int a;
     
     

void main()
      {
      lcd_init();
      while(TRUE)
      {
         i2c_start();
         i2c_write(0xA0);       
         delay_ms(10);
         i2c_write(5);
         i2c_stop();         
         i2c_start(); 
         i2c_write(0xA1);
         delay_ms(100);
         a = i2c_read(0); 
         i2c_stop();
          }
         delay_ms(20);
          lcd_gotoxy(1,1);
          printf(lcd_putc,"UAPSAT");
          lcd_gotoxy(1,2);
         printf(lcd_putc,"\ntemp2=%01.2u",a);
         delay_ms(1500);
         lcd_putc("\f");
         delay_ms(1000);
         
         }
 
Última edición por un moderador:
christian, mira mi correo es










si es posible explicame mas detalladamente que es lo que quieres hacer exactamente, ya mire el codigo, en este momento el Master pide los datos del Slave, pero no entiendo para que quieres validar los datos, no se si es que quieres introducir mas Esclavos o que, si es posible Explicame mas detalladamente lo que quieres hacer con este proyecto y con gusto te ayudare hasta donde mis conocimientos me den....
 
Última edición por un moderador:
Hola djr3000 el proyecto consiste: en el esclavo van ha ir conectados 4 sensores de temperatura (LM35) el cual el esclavo digitaliza los datos analogos del sensor ,entonces el Master envia el start ,direccion del esclavo y el octavo bit 0 de escritura,escribe un dato por ejemplo 5 luego el esclavo recibe estos datos ,si es 5 envia el dato digitalizado del canal 0 para eso el Master cambia a lectura envia start,direccion del esclavo y el octabo bit 1 , leo y stop, luego lo muestra en una pantalla.Para los siguientes sensores escribiria 6,7 u 8 por ejemplo en la escritura del comando en el codigo del Master.Si hubiera otra forma o metodo de obtener estos datos digitalizados de los sensores conectados al esclavo por favor hazme sabe,de antemano muchas gracias drj3000.
 
Hola Diego pues tu apreciación es correcta y valida lo que pasa es que me piden que lo desarrolle de esa manera(utilizar 2 pic-i2c) osea el master envia el star,write(direc0),comado,stop y cambiar a lectura star,write(direc1),read,stop.El esclavo validar el comando y de acuerdo a eso selecciona el canal analogo y lo envia al master.
Estos dias estado profundizando y persistiendo acerca i2c y ya consegui soluccionar el proyecto ya logro validar y funciona a la perfeccion.te adjunto el codigo y el esquema en proteus.
Tambien estado desarrollando otros codigos I2C .El cual los visualizo todos los sensores por la pantalla.
Actualmente toy trabajando en la implementacion del puerto virtual serial el cual los datos de temperatura los envia al programa matlab para visualizar su grafica y estudiar su comportamiento,posiblemente el master lo cambie al por el pic18f4550 para utilizar puerto usb en fisico con el hardware,bueno si hay alguna apreciacion o sugerencia te lo agradesco ,saludos.
 

Adjuntos

  • Nueva carpeta.rar
    82.4 KB · Visitas: 241
  • TES21.rar
    79.9 KB · Visitas: 146
Atrás
Arriba