Autor Tema: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]  (Leído 5542 veces)

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

Desconectado manex_1987

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1127
Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« en: 27 de Febrero de 2007, 08:55:40 »
Hola gente

Estoy tratando de implementar una comunicacion I2C completa entre un 18f452 a 20mhz como master y un 18f2550 a 48mhz (20mhz PLL5 :2) como esclavo. Las resistencias pullup son 2K2 con 10K en paralelo, resultando en 1K8. Pensaba que el circuito 18f452 no llevaba pullups, y en el circuito slave los implementé. Aun asi esa resistencia segun he leido, esta aun en baremos aceptables.

El codigo del slave, resumido:
Código: [Seleccionar]
#include <18f2550.h>
#fuses HSPLL,PLL5,CPUDIV1,NOWDT
#use delay(clock=48000000)
#use I2C(slave,sda=PIN_B0,scl=PIN_B1,address=0xa0,force_hw)

...

#INT_SSP

                       //
void isr4()
{
   state = i2c_isr_state();
   output_a(0xFF); //Para tener constancia de que ha ocurrido. A esta configurado como digital total.


     if(state>=0x80) // Solicitud de envio
     {
     i2c_write(I2C_BUFFER[i2c_addr+(state-0x80)]);  //Envio dato desde direccion, esta
     }                                              //se incrementa por cada solicitud antes del STOP.

     if (state>=2) // Recibe datos II
     {
      I2C_BUFFER[i2c_addr+state-2]=i2c_read(); //Segundo y consecutivos datos, la direccion
                                                                      //se incrementa por cada envio antes del STOP.
      if(i2c_addr==9) I2C_READ_RDY=1;            //Si se escribe el comando, se sube flag de datos recibidos.
     }

     if(state==1) //Recibe PRIMER dato
     {
      i2c_addr=i2c_read();      //Primer dato direccion
     }

}


Mencionar, que se sobreentiende que he puesto "enable_interrupts(INT_SSP);" en el programa.

Y el master:

Código: [Seleccionar]

#include <18f452.h>
#fuses HS,NOWDT
#use delay(clock=20000000)
#use i2c(master, sda=PIN_C4,scl=PIN_C3,force_hw)

int i2c_data[10];
int tmp;


void main()
{
output_float(PIN_C4);
output_float(PIN_C3);

setup_timer_0 (RTCC_INTERNAL|RTCC_DIV_4);
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);
lcd_init();
printf(LCD_PUTC,"INICIO!!");
delay_ms(1000);
lcd_putc('\f');

while(1)
{

printf(LCD_PUTC,"Start");
delay_ms(1000);
lcd_putc('\f');

i2c_start();
i2c_write(0xa0);
i2c_write(0x00);
i2c_write(0x80);
printf(LCD_PUTC,"Datos");
lcd_putc('\f');
i2c_stop();

printf(LCD_PUTC,"Dato enviado");

delay_ms(1000);
lcd_putc('\f');

i2c_start();
i2c_write(0xa0);
i2c_write(0x00);
i2c_start();
i2c_write(0xa1);
tmp=i2c_read();
printf(LCD_PUTC,"%u",tmp);
i2c_stop();

}


}


Bueno, pues en fin. Alimento los dos, enciendo el tinglado... y el 18f452 funciona como si enviara y leyera bien. Pero el dato que recibo siempre es 0xFF. Quito el 18f2550 de su zocalo, enciendo y... hale! igual igual, se comporta igual. Y el 18f2550 no da constancia de haber entrado en interrupcion (recordemos que cuando entra, se encienden todos los pines del puerto A).
La conexion I2C fisica es correcta, lo he comprobado 1000 veces con el polimetro. Y los pines de SDA y SCL no estan intercambiados ni nada por el estilo. No se que es lo que funciona mal, de veras.

Espero vuestra ayuda!

PD: El slave, simple y llanamente, no entra en la interrupcion...

PD2: El slave, tampoco hace ACK al recibo de un dato.
« Última modificación: 27 de Febrero de 2007, 13:08:10 por manex_1987 »

Desconectado manex_1987

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1127
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #1 en: 27 de Febrero de 2007, 14:16:50 »
Llevo 3 dias con el asunto y nada... argh... estoy completamente jodido, de veras. Que impotencia... la conexion fisica esta bien, he eliminado la resistencia de 10K para que el pullup sea 2K2 exactos... pero ni asi. Y he probado con tres 18f2550 diferentes.

Que frustrante. Argh.
« Última modificación: 27 de Febrero de 2007, 14:20:54 por manex_1987 »

Desconectado pikman

  • Moderador Local
  • PIC24F
  • *****
  • Mensajes: 679
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #2 en: 28 de Febrero de 2007, 00:17:32 »
Hola, MANEX, mira creo que deberias revisar el fe de erratas del micro con que tienes problemas creo saber que habia algun inconveniente con el 18f4550 con el I2C, y estas usando el 18f2550, puede que ese sea el error, voy a buscarlo, de cualquier manera creo haber visto un post en este subforo.

saludos
PikMan

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #3 en: 02 de Marzo de 2007, 13:11:50 »
Manex ¿y porque no pruebas haciendo la programación del I2C en ensamblador? ya he tenido noticias de que los comandos I2C en CCS pueden fallar, a mi me pasó una vez que el SPI en C no funcionaba correctamente (los tiempos se corrian) cuando lo intenté (usando v 3.249)

si puedes buscate un osciloscopio y mira los tiempos a ver si son correctos.

Salu2
Pedro
La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #4 en: 02 de Marzo de 2007, 13:19:09 »
Puedes decirnos que version de CCS usas??
Has probado ambos PIC con un dispositivo I2C a ver si andan??
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado JJcorps

  • PIC12
  • **
  • Mensajes: 51
    • Proyectos de JJcorps
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #5 en: 03 de Marzo de 2007, 06:29:33 »
Hola manex_1987
Llevo ya un tiempo trabajando con esto del i2c, El codigo lo veo bien, y a mi me paso algo parecido asi que aki llevas unos consejillos :P

1) Tiene que haber 2 resistencias de pullup en todo circuito i2c y NO un par de resistencias en el maestro y otro par de resistencias en el esclavo. Estas resistencias las he probao con 2k2, 4k7 y 10k y han funcionao asi q lo de la resistencias no te calientes mucho la cabeza.

2) La rutina de interrupcion que esta en los ejemplos que trae ccs esta mal. Me explico, funciona de perlas para mandar datos pero para recibir datos empieza en el state=0 (primer dato, no direccion del dispositivo) Al menos con el pic16f88 que es con el q trabajo

3) Te recomiendo que hagas un ejemplo basico para detectar que el esclavo entra realmente en la interrupcion algo asi q cuando se pulse un boton mande algo al esclavo y cuando el esclavo reciba  señal que encienda un led. y lo pruebes en el proteus. Un fallo que tuve fue que con los cristales que tenia puesto el i2c no rulaba. Asi que estuve probando con el proteus cristales hasta que funciono (tb cambiandolo en el codigo) y esos fueron los q me pille.

Espero que te sea de ayuda y suerte

« Última modificación: 03 de Marzo de 2007, 06:32:29 por JJcorps »

Desconectado omix

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 244
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #6 en: 04 de Marzo de 2007, 17:02:02 »
Hola manex_1987, como bien comenta el compañero pikman, deberias de revisar el documento de erratas del 18F2550, pues hay algunas revisiones de estos micros que tienen un problema con el I2C. De hecho, yo uso ese mismo micro en un proyecto y tuve problemas con el I2C, ya que no funcionaba con las librerias del CCS, probablemente porque no llevan implementado el workarround que se comenta en el documento de errata del micro. Asi que me implemente la libreria (modo maestro solamente), corrigiendo dicho error y funciona perfectamente.

Con esto te quiero decir que es mejor que te implementes tu propia libreria, porque lo mas probable es que ese sea el problema. Por supuesto si decides hacerlo y deseas que te pase mi libreria o te eche una mano con la tuya no dudes en decirmelo.

Un saludo y animo.

Desconectado manex_1987

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1127
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #7 en: 04 de Marzo de 2007, 18:23:31 »
Buenas, muchas gracias por vuestras respuestas!

PalitroqueZ:Ya he intentado implementarlos por assembler pero no me funcionaron. El osciloscopio pinta bien, los datos de SDA no puedo verlos bien aunque siguen un patron definido (no es un osc digital), pero SCL es regular. Segun mis calculos, a unos 200khz va el SCL.

MGLSOFT: Uso ccs 4.023

JJCORPS: He suprimido las dos resistencias del slave (las puse porque pensaba que el master no llevaba de por si), ahora la R es 2K2 en ambas lineas. Lo de la interrupcion no lo comprendo, me explico con la ayuda del i2c_isr_state:
Cita de: Ayuda CCS
0 - Address match received with R/W bit clear

1-0x7F - Master has written data; i2c_read() will immediately return the data

0x80 - Address match received with R/W bit set; respond with i2c_write()

0x81-0xFF - Transmission completed and acknowledged; respond with i2c_write()
Lo del ejemplo basico ya lo hago, y te aseguro que nada-de-nada. Y no un led, sino que hago output_a(0xFF);. Nadie da señales de vida.

OMIX: Ya he visto las erratas y lo mas importante me parece una en especial, donde advierte de malfunciones en ciertos entornos. Ya intente crear mi libreria:

LIBRERIA  I2C_18F2550.C  ,  PARA MODO SLAVE SOLO
Código: [Seleccionar]
#byte TRISB = 0xF93

#define  SDA   PIN_B0
#define  SCL   PIN_B1

#byte MCU_SSPBUF = 0xFC9
#byte MCU_SSPADD = 0xFC8
#byte MCU_SSPSTAT = 0xFC7
#byte MCU_SSPCON1 = 0xFC6
#byte MCU_SSPCON2 = 0xFC5

#bit DA_BIT = MCU_SSPSTAT.5
#bit RW_BIT = MCU_SSPBUF.0

#define ADRESS 0xA0;


void init_i2c()
{
   setup_adc_ports(NO_ANALOGS);
   bit_clear(TRISB,0);
   bit_clear(TRISB,1);
   output_low(SDA);
   output_low(SCL);
   bit_set(TRISB,0);
   bit_set(TRISB,1);
   MCU_SSPADD=ADRESS;
   MCU_SSPCON1=0x36;   
}

int8 i2c_read()
{
    return MCU_SSPBUF;
}

int1 i2c_write(int8 data)
{
   MCU_SSPBUF=data; 
}



//int8 my_i2c_isr_state(void)
//0= Adress, to write in slave
//1= Data, to write in slave
//0x80=Adress,to send from slave
//0x81=Data, to send from slave



int8 my_i2c_isr_state(void)
{
int8 i2c_state=0;   
int8 retval;
   
if(!DA_BIT)  // If address byte was received
  {
   i2c_state = 0;  // Suppose it is a write adress

   if(RW_BIT)      // If it is a Read address
      bit_set(i2c_state, 7);  // Then set bit 7 of state.
  } 
else        // If data was received
  {
   i2c_state++; //Suppose it is data to be read, increment each data.
   
   if(RW_BIT) //If it is data sent
     bit_set(i2c_state,7);
  }


return(i2c_state); 
}


Aun asi, OMIX, seria interesante que me mandaras tu libreria maestro, por si acaso. Si no te importa claro.



Porcierto se me olvida mencionar, probé en una protoboard un 18f2550 frente a frente con un 18f2550, y la transferencia i2c entre ambos es satisfactoria. Lo triste es que no puedo implementar un 18f2550 en mi montaje, debe ser de 40 pines. 18f4550? en ello estoy, pero no me funciona por ahora.
Un saludo a todos!!!
« Última modificación: 04 de Marzo de 2007, 18:27:09 por manex_1987 »

Desconectado manex_1987

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1127
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #8 en: 04 de Marzo de 2007, 20:48:04 »
Código: [Seleccionar]
#include <18f4550.h>
#fuses HS,PLL5,CPUDIV1,NOWDT,PUT
#use delay(clock=48000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#build (reset=0x04,interrupt=0x08)

int encoder_value=0,encoder_target=0;
int1 encoder_bit=0,encoder_bit2=0,encoder_task=0;

int motortask;

#include <def.c>
#include <lcdbot.c>
#use i2c(master, sda=PIN_C4,scl=PIN_C5)

int i2c_data[10];
int tmp;
int q;


void main()
{
setup_psp(PSP_DISABLED);


output_float(PIN_C4);
output_float(PIN_C3);

//setup_timer_0 (RTCC_INTERNAL|RTCC_DIV_4);
//enable_interrupts(GLOBAL);
//enable_interrupts(INT_TIMER0);
lcd_init();
printf(LCD_PUTC,"INICIO!!");
delay_ms(1000);
lcd_putc('\f');

while(1)
{

printf(LCD_PUTC,"Start");
delay_ms(1000);
lcd_putc('\f');

i2c_start();
printf(LCD_PUTC,"1");
i2c_write(0xa0);
printf(LCD_PUTC,"2");
i2c_write(0x00);
printf(LCD_PUTC,"3");
i2c_write(0x80);
printf(LCD_PUTC,"Datos");
lcd_putc('\f');
i2c_stop();

printf(LCD_PUTC,"Dato enviado");

delay_ms(1000);
lcd_putc('\f');

i2c_start();
i2c_write(0xa0);
i2c_write(0x00);
i2c_start();
i2c_write(0xa1);
tmp=i2c_read();
printf(LCD_PUTC,"%u",tmp);
i2c_stop();

}









}




#INT_TIMER0
isr1()
{
if (encoder_bit^input(Sen_encoder))
{
   if(encoder_task)
   {
      if(encoder_target--==0)
      {
         encoder_task=0;
         Stop();
      }
   }

   encoder_bit=!encoder_bit;
   if(encoder_value++==17)
   {
      encoder_value=0;
   }
}

}

He cambiado de terreno, ahora el master es un 18f4550. Como podeis ver, he puesto marcadores despues de cada orden I2C. Pues el cacharro empieza a funcionar (intentando comunicarse con un 2550 en slave), y llega a "1" y ya nada mas. Vamos, como que se cuelga el programa.

Cabe destacar, que el I2C es por software. Por hard no me es posible pues no me coinciden los pines.

Desconectado omix

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 244
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #9 en: 05 de Marzo de 2007, 16:13:10 »
Hola manex_1987, siento no haber podido responder antes. Aqui te adjunto el código para el manejo del I2C en el 18F2550.

Saludos y espero que te sirva de ayuda.
« Última modificación: 05 de Marzo de 2007, 16:15:43 por omix »

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #10 en: 28 de Julio de 2007, 23:59:33 »
manex, como te fue con la comunicación, te funciono, si fuera posible podrias colgarnos el codigo por aca para qeu se pueda servirnos de ayuda? si puedes claro.

omix, esas librerias qeu adjuntaste como funcionan, ya no debo hacer el #use i2c(...) o se debe hacer? y como las incluyo primero cual? necesitan algo extra mas?? funcionarian con otro PIC, un 16 por ejemplo??

weno intentare decifrarlas, un saludo y muchas gracais, adios.
.

Desconectado omix

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 244
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #11 en: 29 de Julio de 2007, 07:37:48 »
Hola Cryn, para usar la libreria que yo puse no necesitas poner el #use i2c..., simplemente añade mi liberia a tu proyecto e inicializa el i2c con la función I2c_Init, hecho esto ya puedes usar el I2c_Start(), para enviar la condicion de inicio, I2c_Stop, envia la condicion de fin, I2c_Restart(), vuelve a enviar la condicion de inicio, con I2c_Write() envias un byte y con I2c_Read lees un byte y por ultimo I2c_Off() deshabilita el modulo I2C (si necesitas hacerlo).

Ejemplo de uso, para leer la temperatura de un sensor TCN75:

Código: [Seleccionar]

void main(){
  unsigned char tempHight, tempLow;

  ..... //más codigo

  I2c_Init(I2C_FAST); //Inicializa el modulo I2C a 400KHz

  ..... //más código

  for(;;){

         I2c_Start();
I2c_Write(0x90); //Selecciona dispositivo a escribir (TCN75 addr = 0x00)
I2c_Write(0x00); //Selecciona registro de temperatura del TCN75
I2c_Restart();
I2c_Write(0x91); //Selecciona TCN75 para leer
tempHight = I2c_Read(1);
tempLow = I2c_Read(0);
Stop_i2c();

if((tempLow & 0x80) == 0x80){       //comprobamos si el bit 7 es 1 => 0.5ºC
      printf("TEMP: %d.5 ºC\r\n",tempHight);
    }else{
      printf("TEMP: %d.0 ºC\r\n",tempHight);
    }

       ....... //Código adicional

   }
 
}


Con respecto a si sirve para otros micros, pues en teoria deberia de servir, lo unico que tendras que cambiar posiblemente son los pines de SDA y SCL y quizá algun registro que pueda cambiar. De todas formas yo solo lo he probado con micros de la serie 18F, pero deberia de servir tambien para micros de la serie 16F.

Un saludo.

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #12 en: 29 de Julio de 2007, 11:56:14 »
en PICs que no tengan i2c por hardware, funcionaria? digamos en un 16f84A o un 16f648A?

para enviar creo qeu no hay mucho problema, se coloca el start, direccion, datos, y stop. En cambio para recepción como lo hago??, qeu hay de la direcion del slave, donde la defino, porque podria usar varios micros slaves, verdad?

la recepcion la hago por interrupcion?? pero si fuera asi no iria con cualqueir micro

gracias por la ayuda.
.

Desconectado omix

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 244
Re: Problema con I2C [ 18f452 (Ma) <---> 18f2550 (Sl) ]
« Respuesta #13 en: 29 de Julio de 2007, 12:50:51 »
Hola de nuevo Cryn, la libreria solo sirve para micros que posean el módulo MSSP o lo que es lo mismo no sirve para manejar I2C por software. En cuando a lo recepcion en esclavo, como ya comenté en un post anterior, la libreria solo implementa el modo Maestro, pero si necesitas el modo esclavo solo tendrias que modificar la funcion que inicializa el módulo I2C para que funcione en modo esclavo.

Un saludo.