Autor Tema: DUDA COMUNICACIÓN I2C!!!!!!  (Leído 6127 veces)

0 Usuarios y 3 Visitantes están viendo este tema.

Desconectado Darukur

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 464
    • Informacion, recursos y ejemplos para desarrollos con microcontroladores
Re: DUDA COMUNICACIÓN I2C!!!!!!
« Respuesta #15 en: 10 de Noviembre de 2006, 10:37:25 »
Aca un manejador de I2C MASTER por interrupciones:

Código: [Seleccionar]
//Valores para I2C
#define SSPMode(val) SSPCON1 &=0xF0; SSPCON1|=(val & 0xf)
#define MASTER_FIRM 0B1011
#define MASTER_CLK 0B1000
//Definiciones de tareas
#define T_IDLE 0
#define T_WRITE 1
#define T_READ 2
#define T_WRITE_R 3
#define T_READ_R 4
//Definiciones de pasos
#define S_IDLE 0
#define S_START 1
#define S_RESTART 2
#define S_STOP 3
#define S_WRITE_ADRESS_W 4
#define S_WRITE_ADRESS_R 5
#define S_WRITE_DEV_ADRE 6
#define S_WRITE_DATA 7
#define S_READ_DATA 8
#define S_ACK_MS 9
#define S_NACK_MS 10
#define S_DONE 11
#define S_ERROR 12
//Definiciones de errores
#define E_NO_ERROR 0
#define E_W_ADRESS_NACK 1
#define E_R_ADRESS_NACK 2
#define E_DATA_NACK 3
#define E_DEV_ADRESS_NACK 4
#define E_DEV_TIMEOUT 5
//Definicion de la I2C
#define SCL RC3
#define SDA RC4
#define SCL_TRIS TRISC3
#define SDA_TRIS TRISC4
//Variables de I2C
char I2C_TASK_TIMEOUT;
char I2C_TASK,I2C_TASK_STEP,I2C_TASK_ERROR;
char I2C_TASK_ADRESS,I2C_TASK_DEV_ADRESS,*I2C_TASK_DATA,I2C_TASK_NUM;
#define I2C_TASK_TIMEOUT_MAX 30 //tiempo de espera para que conteste
/******************************************************************************************/
// Rutinas I2C MASTER para dispositivos con HW I2C manejado por interrupciones
/******************************************************************************************/
void I2C_init (void);
void I2C_Interrupt (void);
void I2C_WRITE (char I2C_ADRESS,char *I2C_DATA,char I2C_NUM);
void I2C_READ (char I2C_ADRESS,char *I2C_DATA,char I2C_NUM);
void I2C_WRITE_ROM (char I2C_ADRESS,char I2C_DEV_ADRESS,char *I2C_DATA,char I2C_NUM);
void I2C_READ_ROM (char I2C_ADRESS,char I2C_DEV_ADRESS,char *I2C_DATA,char I2C_NUM);
/******************************************************************************************/
void I2C_WRITE (char I2C_ADRESS,char *I2C_DATA,char I2C_NUM)
{I2C_TASK_STEP=S_START; /*Posiciono en paso START*/;
I2C_TASK_TIMEOUT=I2C_TASK_TIMEOUT_MAX; /*Inicializo el TIMEOUT*/
I2C_TASK=T_WRITE;I2C_TASK_ADRESS=I2C_ADRESS;I2C_TASK_DATA=I2C_DATA;
I2C_TASK_NUM=I2C_NUM;SEN=1;/*Genero un Start*/;}
/******************************************************************************************/
void I2C_READ (char I2C_ADRESS,char *I2C_DATA,char I2C_NUM)
{I2C_TASK_STEP=S_START;/*Posiciono en paso START*/;
I2C_TASK_TIMEOUT=I2C_TASK_TIMEOUT_MAX; /*Inicializo el TIMEOUT*/
I2C_TASK=T_READ;I2C_TASK_ADRESS=I2C_ADRESS;I2C_TASK_DATA=I2C_DATA;
I2C_TASK_NUM=I2C_NUM;SEN=1;/*Genero un Start*/;}
/******************************************************************************************/
void I2C_WRITE_ROM (char I2C_ADRESS,char I2C_DEV_ADRESS,char *I2C_DATA,char I2C_NUM)
{I2C_TASK_STEP=S_START;/*Posiciono en paso START*/;
I2C_TASK_TIMEOUT=I2C_TASK_TIMEOUT_MAX; /*Inicializo el TIMEOUT*/
I2C_TASK=T_WRITE_R;I2C_TASK_ADRESS=I2C_ADRESS;I2C_TASK_DEV_ADRESS=I2C_DEV_ADRESS;
I2C_TASK_DATA=I2C_DATA;I2C_TASK_NUM=I2C_NUM;SEN=1;/*Genero un Start*/;}
/******************************************************************************************/
void I2C_READ_ROM (char I2C_ADRESS,char I2C_DEV_ADRESS,char *I2C_DATA,char I2C_NUM)
{I2C_TASK_STEP=S_START;/*Posiciono en paso START*/;
I2C_TASK_TIMEOUT=I2C_TASK_TIMEOUT_MAX; /*Inicializo el TIMEOUT*/
I2C_TASK=T_READ_R;I2C_TASK_ADRESS=I2C_ADRESS;I2C_TASK_DEV_ADRESS=I2C_DEV_ADRESS;
I2C_TASK_DATA=I2C_DATA;I2C_TASK_NUM=I2C_NUM;SEN=1;/*Genero un Start*/;}
/******************************************************************************************/
void I2C_Interrupt (void)
{I2C_TASK_TIMEOUT=I2C_TASK_TIMEOUT_MAX; /*Inicializo el TIMEOUT*/
 switch(I2C_TASK_STEP)
{case S_START :I2C_TASK_ERROR=E_NO_ERROR;
if (I2C_TASK==T_READ)
{I2C_TASK_STEP=S_WRITE_ADRESS_R;SSPBUF=(I2C_TASK_ADRESS | 0x01);}
else{I2C_TASK_STEP=S_WRITE_ADRESS_W;SSPBUF=(I2C_TASK_ADRESS & 0xFE);};break;
case S_RESTART :I2C_TASK_STEP=S_WRITE_ADRESS_R;SSPBUF=(I2C_TASK_ADRESS | 0x01);break;
case S_WRITE_ADRESS_W:if (ACKSTAT) {I2C_TASK_ERROR=E_W_ADRESS_NACK;I2C_TASK_STEP=S_STOP;PEN=1;}
else {switch(I2C_TASK){case T_WRITE :I2C_TASK_STEP=S_WRITE_DATA;SSPBUF=*I2C_TASK_DATA;break;
case T_WRITE_R :I2C_TASK_STEP=S_WRITE_DEV_ADRE;SSPBUF=I2C_TASK_DEV_ADRESS;break;
case T_READ_R :I2C_TASK_STEP=S_WRITE_DEV_ADRE;SSPBUF=I2C_TASK_DEV_ADRESS;break;
  };};break;

case S_WRITE_ADRESS_R:if (ACKSTAT) {I2C_TASK_ERROR=E_R_ADRESS_NACK;I2C_TASK_STEP=S_STOP;PEN=1;}
else{I2C_TASK_STEP=S_READ_DATA;RCEN=1;};break;
case S_WRITE_DEV_ADRE:if (ACKSTAT) {I2C_TASK_ERROR=E_DEV_ADRESS_NACK;I2C_TASK_STEP=S_STOP;PEN=1;}
else{switch(I2C_TASK){case T_WRITE_R:I2C_TASK_STEP=S_WRITE_DATA;SSPBUF=*I2C_TASK_DATA;break;
   case T_READ_R :I2C_TASK_STEP=S_RESTART;RSEN=1;break;};}
break;
case S_WRITE_DATA :if (ACKSTAT) {I2C_TASK_ERROR=E_DATA_NACK;I2C_TASK_STEP=S_STOP;PEN=1;}
else if (I2C_TASK_NUM)
{I2C_TASK_NUM--;I2C_TASK_DATA++;I2C_TASK_STEP=S_WRITE_DATA;SSPBUF=*I2C_TASK_DATA;}
  else {I2C_TASK_STEP=S_STOP;PEN=1;};
break;
case S_READ_DATA :*I2C_TASK_DATA=SSPBUF;
if (I2C_TASK_NUM) {ACKDT=0;I2C_TASK_NUM--;I2C_TASK_DATA++;I2C_TASK_STEP=S_ACK_MS;}
else {ACKDT=1;I2C_TASK_STEP=S_NACK_MS;};
ACKEN=1;break;
case S_ACK_MS :I2C_TASK_STEP=S_READ_DATA;RCEN=1;break;

case S_NACK_MS :I2C_TASK_STEP=S_STOP;PEN=1;break;
case S_STOP :if (I2C_TASK_ERROR==E_NO_ERROR)
{I2C_TASK_STEP=S_DONE;}else{I2C_TASK_STEP=S_ERROR;};break;
default :I2C_TASK_STEP=S_ERROR;break;
}
}

/******************************************************************************************/
void I2C_init (void)
{SCL_TRIS=SDA_TRIS=1; //Seteo SCL y SDA como entradas
 SSPMode(MASTER_CLK); //SSP modo maestro con seteo de frec de I2C
 SSPCON2=0;
 #if XTAL_CON_PLL==1 //Velocidad de transferencia=fosc/(4*(SSPADD+1))=100K
SSPADD = 99;
 #else
SSPADD = 24;
 #endif
 SSPEN = 1; //Habilito modulo I2C
 CKP=SMP=1; //Control de Slew rate
 I2C_TASK=T_IDLE;I2C_TASK_STEP=S_IDLE; //Inicializo flags
 I2C_TASK_ERROR=E_NO_ERROR;
 SSPIF=0;SSPIE=1; //Limpio flags de interrupcion y la inicio
}

Este manejador permite trabajar tanto con un dispositivo I2C clasico como con memorias 24LCXX de manera directa.

Falta un pequeño DAEMON de Timeout de I2C que va en la parte de relojeria pero es facil darse cuenta que va.

« Última modificación: 10 de Noviembre de 2006, 14:23:14 por Darukur »
El que no sabe lo que busca no entiende lo que encuentra.
Mi Pagina Web:  http://www.sistemasembebidos.com.ar
Mi foro:             http://www.sistemasembebidos.com.ar/foro/

Desconectado Zaphyrus

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 323
    • Mi blog: Es cuestión de actitud
Re: DUDA COMUNICACIÓN I2C!!!!!!
« Respuesta #16 en: 10 de Noviembre de 2006, 11:35:31 »
Que grande Darukur!!! :)

¿Habrá alguién que no entienda si no conoce el Salvo RTOS que estas utilizando? Por suerte encontré solo una señalización de semáforo:

OSSignalSem()

¿No sería mejor explicarlo?

Saludos.

Martín

PD: Cuando ingresas el código al post tenes un lista donde podes señalizar si queres que te lo coloree o resalte (la lista que dice GeSHi)
« Última modificación: 10 de Noviembre de 2006, 13:18:30 por Zaphyrus »
"¿Lo quiere rápido, barato, o bien hecho? Puede elegir dos de las tres cosas." Arthur C. Clarke.
Mi Proyecto Final de Carrera-Microprocesador RISC de 16 bits en HDL: http://martin.calveira.googlepages.com/home
Mi página web o blog: http://es-cuestion-de-actitud.blogspot.com/
Martín Calveira - Zárate - Argentina

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: DUDA COMUNICACIÓN I2C!!!!!!
« Respuesta #17 en: 10 de Noviembre de 2006, 12:50:22 »
Darukur, he visto que para agregar algo a tus posts, haces un post nuevo.

Esto no es necesario, lo más práctico suele ser "modificar" el post , esto lo puedes hacer clickeando sobre tu post, en modificar y le agregas/quitas lo que te parezca.

 :)
- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado Darukur

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 464
    • Informacion, recursos y ejemplos para desarrollos con microcontroladores
Re: DUDA COMUNICACIÓN I2C!!!!!!
« Respuesta #18 en: 10 de Noviembre de 2006, 14:21:25 »
Err, tenes Razon Maunix.... Sorry.
Lo hice de vago nomas, lo sabia  :mrgreen:
El que no sabe lo que busca no entiende lo que encuentra.
Mi Pagina Web:  http://www.sistemasembebidos.com.ar
Mi foro:             http://www.sistemasembebidos.com.ar/foro/

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: DUDA COMUNICACIÓN I2C!!!!!!
« Respuesta #19 en: 10 de Noviembre de 2006, 15:52:01 »
Err, tenes Razon Maunix.... Sorry.
Lo hice de vago nomas, lo sabia  :mrgreen:

No problem, :)

Una pregunta, esa máquina de estados que haces en la rutina de i2c en el vector de interrupción, ¿no es algo lenta?

Es una pregunta, tengo dudas de cómo pueda funcionar semejante código en un vector de interrupción, mezclado con otras tareas que también requieran atención.

Si detallas para qué micro y frecuencia lo has usado, tal vez la duda quede disipada, ya que cuando hay velocidad... estas cosas pasan a un segundo plano ;)

- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado Darukur

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 464
    • Informacion, recursos y ejemplos para desarrollos con microcontroladores
Re: DUDA COMUNICACIÓN I2C!!!!!!
« Respuesta #20 en: 11 de Noviembre de 2006, 10:04:08 »
Tanto para la rutina de interrupcion de I2C MASTER como la de SLAVE son Macros asi que esta optimizado el tiempo de entrada a la rutina.
El codigo puede parecer largo pero tene en cuenta que es un switch-case en donde se ejecuta una sola opcion.
Yo lo probe a 470Khz y 10Mhz de clock y anda eficientemente.
Entiendo perfectamente la necesidad de que las interrupciones sean lo mas breves posibles, pero realmente esto requiere hacerse en interrupciones.
Tengo casos muucho mas complicados, por ejemplo el manejo de un canal RS-485 half duplex con un protocolo tipo TCP-IP propietario y realmente ahi el codigo en interrupcion es grande.
Es que tiene que transmitir y escucharse (para detectar colision) y no hay otra manera de hacerlo tan rapido fuera de interrupciones.
Asi y todo ese micro gestiona el 485, el I2C master, relojes, contadores de pulsos y un monton de servicios juntos y anda perfecto.
El que no sabe lo que busca no entiende lo que encuentra.
Mi Pagina Web:  http://www.sistemasembebidos.com.ar
Mi foro:             http://www.sistemasembebidos.com.ar/foro/


 

anything