Autor Tema: DSPIC <-> I2C <-> DSPIC  (Leído 9968 veces)

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

Desconectado blackcat

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 600
DSPIC <-> I2C <-> DSPIC
« en: 19 de Noviembre de 2007, 02:28:12 »
Hola a todos

 Espero no aburrirlos con el tema porque ya revise en todo el foro sobre la comunicacion entre dos o mas micros usando el puerto I2C .. pero no vi algo que me ayudara ..... como se imaginaran estuve tratando de poner a funcionar la carajada y no me funciona ...  :x :x :x!!!!  y ya me va a explotar la cabeza  :(... la situacion es la siguiente ... tengo un dspic 33FJ256 en un lado  funcionando como MASTER y todo va  muy bien con las memorias y otros dispositivos I2C,  .... ahora trate de usar otro DSPIC como SLAVE pero no me funciona para nada ... segun a lo que lei ... basta con configurar el I2C y asignar una direccion al I2C1ADD ... el cual solo puede ser entre 0x08 y 0x7F ( creo! ) .. bueno yo le puse 0x08 .... ahora cuando el MASTER envia esa direccion  se da el problema que el master se queda detenido espereando el primer ACK del SLAVE ..  obviamente descarte la posibilidad de que sea el master el que falle pues funciona bien con memorias .... las resistencias son de 3.3k ... tiene que ser el SLAVE

Segun entiendo  este es el algoritmo para recibir datos en el micro que esta como SLAVE ...

1- Configurar el I2C del  micro ... esta a 100kHz, este bit no lo entiendo muy bien Release control bit, lo puse en 0: Hold, la direccion en 0x08, y todo lo demas en 0;

2- Darle Enable al modulo y esperar por medio de la interrupcion a que se detecte la direccion, aqui supuestamente el modulo general los ACK ...  entonces no hay que preocuparse por eso. ..

3- Despues esperar recepcion de datos hasta un stop o un restart....

La bilbioteca de perifericos de microchip puede realizar el paso 3 pero no tengo ningun ejemplo ....

He visto que todo el mundo o casi todo el mundo .... usa CCS y aparentemente se ve muy sencillo .... latimosamente yo no tengo CCS para dspics ... y me gustaria saber si alguien ya pudo hacer funcionar eso en C30 o ASM o no se ....

Me seria de gran ayuda si alguien me hechara una manita ... !!!  GRACIAS!!!  :D :D :D :D :D







 
Control Automático, DSP & Microcontroladores

Desconectado blackcat

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 600
Re: DSPIC <-> I2C <-> DSPIC
« Respuesta #1 en: 19 de Noviembre de 2007, 23:12:07 »
OK .... YA PUDE ... DESPUES DE HORAS Y HORAS Y HORAS ..... AL FIN!!!!    8) 8) 8)


Para cualquiera que tenga los mismos problemas con mucho gusto les ayudare .... no duden en preguntar!!!!!!


 :-/
Control Automático, DSP & Microcontroladores

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: DSPIC <-> I2C <-> DSPIC
« Respuesta #2 en: 20 de Noviembre de 2007, 03:01:18 »
Bueno, no nos dejes con la incógnita, ¿dónde estaba el fallo?

Desconectado blackcat

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 600
Re: DSPIC <-> I2C <-> DSPIC
« Respuesta #3 en: 20 de Noviembre de 2007, 12:03:51 »
JE JE je que pena  :lol: ... pero fue por no leer bien .... mira lo que dice el manual de referencia:

Following the Start condition, the module shifts 8 bits into the I2CxRSR register (see
Figure 19-21). The value of register I2CxRSR<7:1> is evaluated against that of the
I2CxADD<6:0>

Digamos la direccion que estaba enviando el master era la 0xA0 .... y yo de baboso .. estaba poniendo en el slave, en el registro I2CADD = 0xA0 .... claro cuando hacia debugger me salia clarito el 0xA0 en el slave porque se pueden hacer direcciones de 10 bits .... el valor correcto para I2CADD es 0x50 pues el bit 0 de la direccion es de escritura o lectura ... AUN ASI NO ME SEGUIA FUNCIONANDO!!! ..... despues de revisar bien microchip recomienda que las resistencias de 1k sean cuando la velocidad es mayor a 400k, de 2.2k cuando la velocidad es de 100k y 4.7k cuando es menor a 100k ... claro ... estos valores son aproximaciones ... pues esto requiere de un calculo mas complejo considerando las caracteristicas electricas de los dispositivos conectados al bus ... Yo estaba usando resistencias de 3.3k entonces baje la velocidad a 50k y funciono de maravilla !!!!

Tengo que cambiar las resistencias para ver si me funciona a mayor velocidad!

Saludos

PD: Lean bien las hojas de datos!  :lol: :lol: :lol: :lol:

 
Control Automático, DSP & Microcontroladores

Desconectado blackcat

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 600
Re: DSPIC <-> I2C <-> DSPIC
« Respuesta #4 en: 20 de Noviembre de 2007, 22:34:59 »
Hola de nuevo ... bueno ... ya he gastado varias valiosas horas travesiando el I2C como esclavo .... pues resulta que he estado usando un dspic33FJ256MC710 como master ... las rutinas de I2C funcionan bien en ese pic ... ahora he tenido muchos problemas con el PIC24FJ64GA002 ... no me funciona muy bien ... parece que esa serie esta poseida o viene con una maldicion de fabrica .. porque no encuentro el error ....   :D ja  :D ja  :D ja  :D ja ....

Ya he usado dos y los dos me dan los mismos problemas y ya desde hace tiempo no solo con el I2C con el ADC tambien  .... quiesiera saber si alguien ha usado esta serie con exito .. en lo que sea ... 
Control Automático, DSP & Microcontroladores

Desconectado blackcat

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 600
Re: DSPIC <-> I2C <-> DSPIC
« Respuesta #5 en: 12 de Diciembre de 2007, 03:33:13 »
HOLA ... ya he hecho muchos avances con esta cuestion de comunicacion I2C entre micros ... me llamo la atencion  :roll: ( y por ordenes superiores ) realizar una red I2C ...  parece que el protocolo I2C fue diseñado para trabajar en un ambiente multimaster y no solo comunicaciones master <-> slave .... suena bonito  8) ... ya que la red I2C se convierte algo asi como una red ethernet ... porque revisando bien el protocolo tiene direcciones fisicas reservadas y se pueden enviar mensajes tipo BROADCAST ... bueno .. el caso es que ya logre la comunicacion con varios dispositivos con un algoritmo similar al TCP y cree un mecanismo de AUTODESCUBRIMIENTO de la red ... es decir, cada dispositivo conectado al bus identifica a los demas mediante paquetes HELLO en donde cada micro  envia su direccion fisica con una pequeña descripcion y asi cada  pic arma su tabla de direcciones ... EL CASO es que como el bus son solo dos cablesitos y pueden haber muchos dispositivos conectados, la gente que invento el I2C tambien diseño un mecanismo por hardware para detectar colisiones de datos, implemente un metodo similar al que se usa ( o usaba cuando las redes eran con hubs  ) en redes ethernet, todos los dispostivos deben detectar la colision entonces se detiene la actividad en el bus y cada micro espera un tiempo aleatorio antes de reiniciar la actividad.

El problema que tengo ahorita es que ningun micro me detecta las colisiones, suena complicado .. pero eso es un simple bit que se levanta cada vez que le periferico I2C detecta una colision ... pues ese bit esta muerto o le gusta ser 0 ( cero ) porque ni a palos se levanta  :5]... se que hay colisiones en el bus porque algunos datos llegan malos y la unica deteccion es por software mediante checksum ... pareceria que esta es la solucion .. utilizando checksum .. pero esto vuelve el bus lento porque la colision se detecta hasta el final de la trama .....

MI PREGUNTA ES: SI ALGUIEN HA HECHO LO MISMO Y COMO LO SOLUCIONO !!! ... ya no me da la cabeza 



Control Automático, DSP & Microcontroladores

Desconectado blackcat

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 600
Re: DSPIC <-> I2C <-> DSPIC
« Respuesta #6 en: 11 de Abril de 2009, 17:54:13 »
Hola!

Lo prometido es deuda ... a peticion de que muchos me han escrito solicitando una ayudita con la comunicacion entre dsPICs por I2C ... adjunto el código.

Notas importantes:
- Primero tome como base de proyecto un demo de microchip para el Explorer 16. Entonces no se extrañen si hay comentarios en ingles y otros en español. 
- Tambien tomé el codigo de la libreria de perifericos que se instala con el C30.
- A esta libreria le hice algunas modificaciones, como dar TIME_OUT si el I2C se queda congelado.
- Si estudian bien el código, veran que se puede quitar mucha "basura" pues escribi muchas cosas para hacer debug y encontrar pegas.
- Utilicé incialmente un dsPIC33FJ256GP710 (el que viene con el Explorer 16), para probar la comunicacion utilicé una EEPROM, veran que hay codigo para manejar estas memorias, lo deje ahi por si desean utiizarlo. Me di cuenta que el GP710, el I2C no funciona bien, entonces use mejor un dsPIC33FJ256MC710 y ahi se me sirvio.
- Recomiendo revisar el ERRATA (Microchip ERRATA) para ver soluciones a distintos problemas de los micros.
- El codigo es tanto escritura como recepcion, por lo que solo se debe cambiar la direccion del micro ó I2C_ADD, y la direccion del micro donde deben escribir

Este funciona de la siguiente manera:

- Hay dos archivos: MAIN_RTC.C que es el principal y IO_I2C.C que es donde estan todas las funciones del I2C. 

- En MAIN_RTC se configura el I2C, si quieren modificar utilicen la seccion de codigo que esta al inicio:

Código: C
  1. #define I2C2_EN_PERIPH                  1               /* Habilita el modulo I2C2 */
  2. #define I2C2_IPMIEN                     0               /* Intelligent Peripheral Management Ack, 0: Dis, 1: Ena */
  3. #define I2C2_A10M                       0               /* 10 bit Slave Add bit, 0: Dis, 1: Ena */
  4. #define I2C2_DISSLW                     0               /* Slew rate, 0: Dis, 1: En */
  5. #define I2C2_SMEN                       0               /* SMBus input levels bit, 0: Dis, 1: Ena */
  6. #define I2C2_GCEN                       0               /* General Call, 0: Dis, 1: Ena */
  7. #define I2C2_FCLK                       10              /* Serial Clock Rate, in kHz */
  8. #define I2C_ADD                         0x88            /* Numero de direccion i2c slave */


Observen que se configura el I2C2 ... I2C_ADD asigna la dirección de SLAVE del micro.

- La funcion de escritura es:

I2C_Write( 0x80, &dato1, 1);

Los parametros son: Dirección del slave a escribir, puntero del inicio de los datos, cantidad de datos a escribir.

- La recepción es por interrupción, solo se recibe un dato, pero se puede recibir mas de uno. El dato se escribe en i2c_recibido.

Espero que sea de gran ayuda, suerte y saludos!


« Última modificación: 12 de Abril de 2009, 23:16:14 por blackcat »
Control Automático, DSP & Microcontroladores

Desconectado JonyX

  • PIC10
  • *
  • Mensajes: 1
Re: DSPIC <-> I2C <-> DSPIC
« Respuesta #7 en: 12 de Junio de 2009, 19:36:08 »
Hola:

He estado buscando informacion referente a este tema y bueno que te puedo decir...
me parece maravilloso tu aporte, muy util.

Etoy tratando de comunicar 2 dspic30f3014 o 4013 ( solo tienen un modulo I2C, en comparacion con el que tu usas que trae 2 ) que son muy similares, pero he tenido problemas, no entiendo muy bien la comunicacion I2C, me he estado documentando y no logro entender bien:

¿Como configuro un dspic maestro y otro esclavo y como les asigno una direccion a cada uno?

Me podrian echar una mano ?, solo necesito salir de esa duda para poder utilizar todo lo que he estado leyendo, incluyendo tu aporte.

Espero me puedan responder, GRACIAS.

SALUDOS.

Desconectado anibalismo

  • PIC10
  • *
  • Mensajes: 10
Re: DSPIC <-> I2C <-> DSPIC
« Respuesta #8 en: 07 de Abril de 2010, 11:10:02 »
Hola GatoNegro  :) se que el post es medio viejo, y que mi comentario no aporta mucho  :mrgreen: pero acabo de ver que los dos tenemos (tuvimos) problemas parecidos cn el I2C  :( no he revisado tu codigo todavia, pero igualmente, muchas millones de gracias por el aporte!!!

Hey, tengo unas cosas de MiWi corriendo, y estoy haciendo compresion de audio para la tesis de la uni... si algun dia quieres compartir notas, me pongo a la orden!!!

gracias de nuevo por la contribucion  :D si la cosa funciona, tienes un espacio en los agradecimientos de mi tesis jejeje :afro:

Desconectado anibalismo

  • PIC10
  • *
  • Mensajes: 10
Re: DSPIC <-> I2C <-> DSPIC
« Respuesta #9 en: 08 de Abril de 2010, 10:47:39 »
Hola, ayer estuve un rato en esto, y probé unas rutinas sencillas para escribir en una memoria, se que eso está super trillado, pero si lo que quieres es empezar con lo del i2c, quizas esto ayude un poco :D

La rutina esta implementada con un dspic (dspic33fj128gp802) corriendo a 40 mips (es a esa velocidad por otras cosas que esty haciendo en mi aplicacion)

Código: [Seleccionar]
/****************************************************************/
/* */
/* Implementacion de prueba del modulo I2C en un dsPIC 802 */
/* */
/****************************************************************/

#include <p33fj128gp802.h>

//Constantes utiles para la interfaz de usuario
#define PUSH_BUTTON_1 PORTBbits.RB2
#define PUSH_BUTTON_2 PORTBbits.RB3

#define PUSH_BUTTON_1_TRIS TRISBbits.TRISB2
#define PUSH_BUTTON_2_TRIS TRISBbits.TRISB3

#define LED_1 LATAbits.LATA0
#define LED_2 LATAbits.LATA1
#define LED_3 LATBbits.LATB0
#define LED_4 LATBbits.LATB1
   
#define LED_1_TRIS TRISAbits.TRISA0
#define LED_2_TRIS TRISAbits.TRISA1
#define LED_3_TRIS TRISBbits.TRISB0
#define LED_4_TRIS TRISBbits.TRISB1
/////////////////////////////////////////////////

//constantes utiles para el I2C//////////////////
#define I2C_FREC 20000 //frecuencia de I2C deseada
#define I2C_10M 10000000
#define CLOCK_FREC 80000000
#define RBRG (CLOCK_FREC/I2C_FREC) - (CLOCK_FREC/I2C_10M) -1
/////////////////////////////////////////////////

unsigned char data1, data2;

void START( void ); //Genera un Start I2C
void IDLE( void ); //Espera fin trasmision
void PUTC( int dato ); //Pone un dato en el canal
unsigned char GETC( void );
void ACK( void ); //Genera un ACK I2C
void NACK( void ); //Genera un NACK I2C
void WACK( void ); //Espera un ACK I2C
void STOP( void ); //Genera un Stop I2C
void CONF( void ); //Configura el I2C
void HARD( void ); //Configura el Hardware en general
void RST( void );

void ESCRITURA( void );
void LECTURA( void );

_FOSCSEL(FNOSC_FRCPLL);
_FWDT(FWDTEN_OFF); // Disable Watchdog timer
_FPOR(ALTI2C_ON);

/*
Pueba para el DoXy, este es el main
*/
int main( void )
{
unsigned int i;

CONF();
HARD();

while( 13)
{
LED_2 ^= 1;

ESCRITURA();
for( i=0 ; i<6500 ; i++ ) ; //genero un retardo de no se cuanto tiempo

// LECTURA();
// for( i=0 ; i<16500 ; i++ ) ;
}

return 0;
}

void START( void )
{
I2C1CONbits.SEN = 1; //Generar el Start
while (I2C1CONbits.SEN); //Esperar el Start
}

void IDLE( void )
{
while (I2C1STATbits.TRSTAT); //estoy trasmitiendo
}

void PUTC( int dato ) //Pone un dato en el canal
{
I2C1TRN = dato; //cargar byte de trasmision
while (I2C1STATbits.TBF); //Bufer lleno, todavia trasmitiendo
}

unsigned char GETC( void )
{
I2C1CONbits.RCEN = 1; //Habilita la recepcion si soy Master
I2C1STATbits.I2COV = 0;

while( !I2C1STATbits.RBF );

return(I2C1RCV);
}

void ACK( void )//genera un ACK
{
I2C1CONbits.ACKDT = 0; //configura ACk
I2C1CONbits.ACKEN = 1; //genera condicion de ACK
while(I2C1CONbits.ACKEN); //espera a que se termine de enviar
}

void NACK( void )//genera un NACK
{
I2C1CONbits.ACKDT = 1; //configura NACK
I2C1CONbits.ACKEN = 1; //genera condicion de ACK
while(I2C1CONbits.ACKEN); //espera a que el ACK ternime de ocurrir
}

void WACK( void )//(Wait ACK)
{
while( I2C1STATbits.ACKSTAT ); //Espera el ACK
}

void STOP( void )
{
I2C1CONbits.PEN = 1; //Generar STOP
while (I2C1CONbits.PEN); //Y esperar q ocurra
}

void RST( void )
{
I2C1CONbits.RSEN = 1; //Generate Restart
while (I2C1CONbits.RSEN); //Wait for restart
}

void CONF( void )
{
I2C1BRG = RBRG;

I2C1ADD = 0x88 >> 1;

// I2C1CON = 0x0000;
// I2C1RCV = 0x0000;
// I2C1TRN = 0x0000;
// I2C1CON = 0x1200;
// I2C1CONbits.I2CEN = 1;

I2C1CON = 0x0000;
I2C1CONbits.IPMIEN = 0;
I2C1CONbits.A10M = 0 >> 2;
I2C1CONbits.DISSLW = 1;
I2C1CONbits.SMEN = 0;
I2C1CONbits.GCEN = 0;
I2C1CONbits.STREN = 0;

I2C1CONbits.I2CEN = 1;

IFS1bits.SI2C1IF = 0;
IEC1bits.SI2C1IE = 1;
}

void HARD( void )
{
//OSC
CLKDIVbits.PLLPRE = 0; // N1=2: PLL VCO Output Divider Select bits; 0 -> /2 (default)
PLLFBDbits.PLLDIV = 38; // M=40: PLL Feedback Divisor bits; 42 - 2 = 40 -> 40 x multiplier
CLKDIVbits.PLLPOST = 0; // (divisor is 2 more than the value)
// OSCTUN = 16; //por ocio... para ajustar el cristal

//PIN IO
LED_1_TRIS = 0;
LED_2_TRIS = 0;
LED_3_TRIS = 0;
LED_4_TRIS = 0;

LED_1 = 1;
LED_2 = 1;
LED_3 = 1;
LED_4 = 1;

AD1PCFGLbits.PCFG0 = 1;
AD1PCFGLbits.PCFG1 = 1;
AD1PCFGLbits.PCFG2 = 1;
AD1PCFGLbits.PCFG3 = 1;
AD1PCFGLbits.PCFG4 = 1;
AD1PCFGLbits.PCFG5 = 1;

PUSH_BUTTON_1_TRIS = 1;
PUSH_BUTTON_2_TRIS = 1;
}

void ESCRITURA()
{
START();

PUTC( 0b10101010 ); //control 1010 direccion 101 R/W' 0 para Write
IDLE(); //trasmito y espero el ACK
WACK();

PUTC( 0 ); //Direccion Alta
IDLE();
WACK();

PUTC( 0 ); //Direccion Baja
IDLE();
WACK();

PUTC( 0xAA ); //Dato 0
IDLE();
WACK();

PUTC( 0xBB ); //Dato 1
IDLE();
WACK();

PUTC( 0xCC ); //Dato 2
IDLE();
WACK();

STOP();
}

void LECTURA( void )
{
START();

PUTC( 0b10101010 ); //control 1010 direccion 101 R/W' 0 para Write
IDLE(); //trasmito y espero el ACK

PUTC( 0 ); //Direccion Alta
IDLE();

PUTC( 0 ); //Direccion Baja
IDLE();

RST();

PUTC( 0b10101011 ); //control 1010 direccion 101 R/W' 1 para Read

data1 = GETC();

data2 = GETC();

STOP();
}

Ojo, solo funciona la escritura, hoy voy a sentarme con lo de la lectura... y Ojo2, hay formas (como utilizando las interrupciones, o ciclos o que se yo) mucho mejores, esto solo es una humilde aproximacion ;)

Si quieren un par de links con informacion teorica
RobotArgentina
Explicacion microchip I2C

Espero sinceramente que le sea util a alguien  :-/
« Última modificación: 08 de Abril de 2010, 15:33:43 por anibalismo »

Desconectado ablanco93

  • PIC10
  • *
  • Mensajes: 15
Re: DSPIC <-> I2C <-> DSPIC
« Respuesta #10 en: 25 de Agosto de 2010, 13:39:52 »
Hola que tal, gracias por tu aporte BlackCat!, y tengo una super duda que yo se que podras respondermela  :) . Estoy tratando de comunicar dos pic24fj128ga010 con i2c (Ya vi que no viene nada en el Errata de este pic :P ) pero no logro hacerlo :S . Ya pude programar una memoria eeprom 24fc1025, todo funciona muy bien, pero no puedo configurar el pic para que sea maestro :s, segun he leido, se utiliza una interrupcion "SI2CInterrupt" pero no he logrado que el pic entre a la interrupcion, espero y me puedas ayudar, te dejo el codigo fuente del esclavo, en este codigo, lo unico que quiero es que entre a la interrupcion cuando le llegue un dato por el bus de i2c gracias.


#include<p24fj128ga010.h>
#define USE_AND_OR               //USED FOR THE OpenI2C1 INSTRUCTION   
#include<i2c.h>
#define FCY 2000000UL            //THIS IS FOR THE USE OF THE DELAY LIBRARY "libpic30.h"
#include<libpic30.h>

_CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & BKBUG_OFF & COE_OFF & ICS_PGx2 & FWDTEN_OFF & WINDIS_OFF & FWPSA_PR128 & WDTPS_PS32768);
_CONFIG2( FNOSC_PRI & FCKSM_CSDCMD & POSCMOD_XT ); //CONFIGURATION BYTES

unsigned char config1,config2,b1=8;

void main()
{
   TRISD=0;
   PORTD=0;
       /* Turn off I2C modules */
   ConfigIntI2C1(MI2C_INT_ON & SI2C_INT_ON & SI2C_INT_PRI_0 );
    CloseI2C1();                               //Disbale I2C1 mdolue if enabled previously
   config2 =(37);                              //CONFIGURE OF THE I2C1BRG REGISTER: 100KHZ
   config1 =(I2C_ON | I2C_7BIT_ADD| I2C_SLW_DIS|I2C_RCV_EN|I2C_GCALL_EN|I2C_IPMI_DIS|I2C_ACK  );      //CONFIGURE OF THE I2C1CON REGISTER: I2C1 ENABLE, I2CADD IS 7 BIT ADDRESS                                       
   OpenI2C1(I2C1CON | config1,config2);            //CONFIGURATION OF THE MICROCONTROLLER AS MASTER AND WITH VELOCITY OF 100KHZ (SLEW RATE DISABLED)
   I2C1ADD=0x04;                              //ASIGNACION DE DIRECCION DE DISPOSITIVO



   
   while(1)
   {
   
   }
   
}

void __attribute__((__interrupt__, __shadow__)) _SI2CInterrupt(void)
{

   IFS1bits.SI2C1IF = 0;                         //Reset Timer1 interrupt flag and Return from ISR
   PORTD=1;
}