TODOPIC
Microcontroladores PIC => dsPIC => Mensaje iniciado por: microcarsil en 06 de Enero de 2007, 21:21:59
-
Hola amigos estuve probando la comunicacion I2C con los dspic y funciona bien siempre y cuando ponga osciladores externos sin PLL, por ejemplo con 8 mhz y 20 mhz funciona bien, pero resulta que si pongo un cristal de 7.3728 mhz y activo el PLL a 16 para obtener MIPS = (7.3728 Mhz * 16/4)= 29.49 no funciona, para ilustrar un poco lo que hice voy a poner el codigo que funciona bien con un cristal de 20 mhz.
#include <p30f3014.h>
#include <i2c.h>
#define MIPS 5 // MIPS = cristal/4 = 20 Mhz/ 4 = 5
_FOSC( CSW_FSCM_OFF & HS);
_FWDT(WDT_OFF); //Watchdog deshabilitado
_FBORPOR(PBOR_OFF & PWRT_OFF & MCLR_EN); //Reset por baja tensión deshabilitado, retardo al inicio deshabilitado, pint MCLR habilitado como reset
_FGS(CODE_PROT_OFF); //Protección de código deshabilitado
void Tdelay_ms(unsigned long x); // Funcion para hacer retardos en milisegundos, Cortesía de Nocturno
int main ()
{
unsigned char x=0;
unsigned int config2, config1;
config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
I2C_IPMI_DIS & I2C_7BIT_ADD &
I2C_SLW_EN & I2C_SM_DIS &
I2C_GCALL_DIS & I2C_STR_DIS &
I2C_NACK & I2C_ACK_DIS & I2C_RCV_DIS &
I2C_STOP_DIS & I2C_RESTART_DIS &
I2C_START_DIS);
config2 = 7; //((FCY/SPEED)-(FCY/1111111)) - 1; para 5 mhz & 400000 i2c rate FCY = MIPS = 5
//((5000000/400000)-(5000000/1111111))-1 = 7
TRISBbits.TRISB0 = 0; //Configuramos RB0 como salida
OpenI2C(config1,config2); //open the I2C module
IdleI2C(); //make sure bus is idle
while(1)
{
LATBbits.LATB0=1;
Tdelay_ms(1000);
StartI2C(); //transmit Start bit
while(I2CCONbits.SEN ); //wait till start sequence is complete
MasterWriteI2C(0xa0); // Write Slave address and set master for transmission
while(I2CSTATbits.TBF); // Wait till address is transmitted
while(I2CSTATbits.ACKSTAT);
MasterWriteI2C(x); // Transmit data
while(I2CSTATbits.TBF);
while(I2CSTATbits.ACKSTAT);
StopI2C();
while(I2CCONbits.PEN); // Wait till stop sequence is completed
LATBbits.LATB0=0;
Tdelay_ms(1000);
x++;
}
return 0;
}
Ahora presento el programa para el oscilador de 7.3728 Mhz con PLL igual a 16 que no funciona
#include <p30f3014.h>
#include <i2c.h>
#define MIPS 29.49 // MIPS = cristal*16/4 = 7.3728*16 Mhz/ 4 = 29.49
_FOSC( CSW_FSCM_OFF & XT_PLL16);
_FWDT(WDT_OFF); //Watchdog deshabilitado
_FBORPOR(PBOR_OFF & PWRT_OFF & MCLR_EN); //Reset por baja tensión deshabilitado, retardo al inicio deshabilitado, pint MCLR habilitado como reset
_FGS(CODE_PROT_OFF); //Protección de código deshabilitado
void Tdelay_ms(unsigned long x); // Funcion para hacer retardos en milisegundos, Cortesía de Nocturno
int main ()
{
unsigned char x=0;
unsigned int config2, config1;
config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
I2C_IPMI_DIS & I2C_7BIT_ADD &
I2C_SLW_EN & I2C_SM_DIS &
I2C_GCALL_DIS & I2C_STR_DIS &
I2C_NACK & I2C_ACK_DIS & I2C_RCV_DIS &
I2C_STOP_DIS & I2C_RESTART_DIS &
I2C_START_DIS);
config2 = 46; //((FCY/SPEED)-(FCY/1111111)) - 1; para 29.49 mhz & 400000 i2c rate FCY = MIPS = 29.49
//((29491200/400000)-(29491200/1111111))-1 = 46
TRISBbits.TRISB0 = 0; //Configuramos RB0 como salida
OpenI2C(config1,config2); //open the I2C module
IdleI2C(); //make sure bus is idle
while(1)
{
LATBbits.LATB0=1;
Tdelay_ms(1000);
StartI2C(); //transmit Start bit
while(I2CCONbits.SEN ); //wait till start sequence is complete
MasterWriteI2C(0xa0); // Write Slave address and set master for transmission
while(I2CSTATbits.TBF); // Wait till address is transmitted
while(I2CSTATbits.ACKSTAT);
MasterWriteI2C(x); // Transmit data
while(I2CSTATbits.TBF);
while(I2CSTATbits.ACKSTAT);
StopI2C();
while(I2CCONbits.PEN); // Wait till stop sequence is completed
LATBbits.LATB0=0;
Tdelay_ms(1000);
x++;
}
return 0;
}
void Tdelay_ms(unsigned long x)
{
unsigned long Limite;
Limite = x*MIPS*1000-48;
TMR2=-(Limite);
TMR3=(-Limite)>>16;
T2CON = 0x8008;
while (IFS0bits.T3IF==0);
IFS0bits.T3IF=0;
}
Pues bien este ultimo codigo es el que tiene el problema de no enviar los datos por el I2C, el retardo de la funcion que hizo Nocturno si funciona con la configuracion del cristal y el PLL, no se que este fallando y cual es la configuracion que se deba modificar del I2C. Tambien probe con otro cristal de 8 mhz y un pll de 16 obteniendo por overclocking a 32 MIPS y pasa lo mismo que el anterior, solo sirve la funcion del Tdelay_ms pero no transmite nada por I2C. Cualquier sugerencia es bienvenida GRACIAS.
-
Problema solucionado ya FUNCIONA :-/ :-/ :-/
pues era solo cuestion de poner un retardo Tdelay_ms(1) despues de las funciones MasterWriteI2C(0xa0); y MasterWriteI2C(x) quedando parte del codigo de la siguiente manera:
StartI2C(); //transmit Start bit
while(I2CCONbits.SEN ); //wait till start sequence is complete
MasterWriteI2C(0xa0); // Write Slave address and set master for transmission
Tdelay_ms(1) // RETARDO NECESARIO
while(I2CSTATbits.TBF); // Wait till address is transmitted
while(I2CSTATbits.ACKSTAT);
MasterWriteI2C(x); // Transmit data
Tdelay_ms(1) // RETARDO NECESARIO
while(I2CSTATbits.TBF);
while(I2CSTATbits.ACKSTAT);
StopI2C();
while(I2CCONbits.PEN); // Wait till stop sequence is completed
El retardo que hay que esperar lo he bajado hasta los 50 us y sigue funcionando sin problemas.
Saludos 8)
-
Raro, raro.
En teoría con esta línea que ya tenías puesta no sería necesario retardo alguno:
while(I2CSTATbits.TBF); // Wait till address is transmitted
-
De hecho esa fue mi sorpresa que no funciona jejeje, pero estuve investigando y se puede resolver sin el retardo solo agregando la funcion IdleI2C() que es la encargada de esperar hasta que el bus i2c este inactivo, bueno el codigo queda de la siguiente forma:
StartI2C(); //transmit Start bit
while(I2CCONbits.SEN ); //wait till start sequence is complete
MasterWriteI2C(0xa0); // Write Slave address and set master for transmission
IdleI2C();
MasterWriteI2C(x); // Transmit data
IdleI2C();
StopI2C();
while(I2CCONbits.PEN); // Wait till stop sequence is completed
Ya lo probe y funciona muy bien 8)
Saludos
-
hola es muy interesante este trabajo pero no enteidno nada y necesito configurar mi dspic30f4011 par q escuche datos de un sensor que trabaja con comunicacion i2c sera que conocen de algun tutorial que explique eso que hiciste desde 0 por que sinceramente es la primera vez que voy a intentar i2c y si tienen algun programa que configure los registros y no por libreria seria mejor por q esto de las librerias lo enteido poco
gracias por su ayuda sera de vital importancia