Soy nuevo en la comunicación I2C y, después de leer una serie de tutoriales sobre el protocolo, intenté conectar un microcontrolador Microchip DSpic 33ev128gm002 a un microcontrolador QMC5883L (Chinese Honeywell HMC5883L) con las bibliotecas periféricas del fabricante. Pude iniciar e iniciar el muestreo continuo en el sensor, y leer los valores x, y, z.
Sin embargo, este código está en un bucle, y en la segunda iteración el código parece detenerse en la instrucción: while(12C1STATbits.TBF)
después de que se realiza la segunda escritura ( MasterWriteI2C1(0b00000000); )
El código que contiene el bucle es el siguiente:
'while(1){
/**
* Read data from the magnetometer registers
**/
//check if idle
IdleI2C1();
//initiate start condition
StartI2C1();
//wait until start condition is over
while(I2C1CON1bits.SEN == 1);
/* Clear interrupt flag */
// IFS1bits.MI2C1IF = 0;
//send magnetometer address and append the write bit of 0
MasterWriteI2C1(0b00011010);
//wait till data is transmitted
while(I2C1STATbits.TBF); // 8 clock cycles
while (!IFS1bits.MI2C1IF); //wait for 9th clock cycle
//clear interrupt flag
IFS1bits.MI2C1IF = 0; //clear interrupt flag
//I2C1STATbits.TBF = 0;
//send register address : 0x00 = 0000000
MasterWriteI2C1(0b00000000);
//wait till address is transmitted
while(I2C1STATbits.TBF); // 8 clock cycles
while (!IFS1bits.MI2C1IF); //wait for 9th clock cycle
/* Clear interrupt flag */
IFS1bits.MI2C1IF = 0;
//generate another start condition
//check if idle
IdleI2C1();
//initiate start condition
StartI2C1();
//wait until start condition is over
while(I2C1CON1bits.SEN == 1);
/* Clear interrupt flag */
IFS1bits.MI2C1IF = 0;
//send magnetometer address and append the write bit of 1 for READ
MasterWriteI2C1(0b00011011);
//wait till data is transmitted
while(I2C1STATbits.TBF); // 8 clock cycles
while (!IFS1bits.MI2C1IF); //wait for 9th clock cycle
//clear interrupt flag
IFS1bits.MI2C1IF = 0; //clear interrupt flag
//read 1 byte
char x_low = MasterReadI2C1();
//send Master ACK
AckI2C1();
//read 1 byte
char x_high = MasterReadI2C1();
//send Master ACK
AckI2C1();
//read 1 byte
char y_low = MasterReadI2C1();
//send Master ACK
AckI2C1();
//read 1 byte
char y_high = MasterReadI2C1();
//send Master ACK
AckI2C1();
//read 1 byte
char z_low = MasterReadI2C1();
//send Master ACK
AckI2C1();
//read 1 byte
char z_high = MasterReadI2C1();
//send Master ACK
AckI2C1();
//read the other registers...
char status_bits = MasterReadI2C1();
//send Master ACK
AckI2C1();
char T_out_low = MasterReadI2C1();
//send Master NACK not ACK!!
NotAckI2C1();
//check if idle
IdleI2C1();
StopI2C1();
while(I2C1CON1bits.PEN == 1);//wait for stop condition flag to clear
U1TXREG = x_low;
//wait until char (byte) has been transmitted)
while (IFS0bits.U1TXIF);
__delay_ms(10);
U1TXREG = x_high;
//wait until char (byte) has been transmitted)
while (IFS0bits.U1TXIF);
__delay_ms(10);
U1TXREG = y_low;
//wait until char (byte) has been transmitted)
while (IFS0bits.U1TXIF);
__delay_ms(10);
U1TXREG = y_high;
//wait until char (byte) has been transmitted)
while (IFS0bits.U1TXIF);
__delay_ms(10);
U1TXREG = z_low;
//wait until char (byte) has been transmitted)
while (IFS0bits.U1TXIF);
__delay_ms(10);
U1TXREG = z_high;
//wait until char (byte) has been transmitted)
while (IFS0bits.U1TXIF);
__delay_ms(1000);
}'
Este es el código para inicializar el módulo I2C:
/*Method to configure and set up I2C*/
void initI2C(void)
{
//SET I2C Lines to inputs
_TRISB5 = 1;
_TRISB6 = 1;
TRISBbits.TRISB5 = 1;
TRISBbits.TRISB6 = 1;
CloseI2C1();
//wait for magnetometer POW On time
__delay_us(360);
I2C1CONLbits.A10M = 0;
I2C1CONLbits.GCEN = 0;
I2C1CONLbits.STREN = 1;
I2C1BRG = 0x10; //16 in decimal
//enable i2c called 12C1CONL register
I2C1CONLbits.I2CEN = 1; }
Este es el código para configurar y configurar el sensor QMC5883L:
'//Method to initialise magnetometer for continuous measurement
void initMagnetometer(void)
{
//Define set/reset period
//check if idle
IdleI2C1();
//initiate start condition
StartI2C1();
//wait until start condition is over
while(I2C1CON1bits.SEN == 1);
//send commands to initialise magnetometer
//define set/reset period
/* Clear interrupt flag */
IFS1bits.MI2C1IF = 0;
//since 7bit address it has to be shifted by one place
// MasterWriteI2C1((0x0D << 1)); //Select device
// MasterWriteI2C1(0x0D);
//send address and append the write bit
MasterWriteI2C1(0b00011010);
//IdleI2C1();
// MasterputcI2C1(MAGNETOMETER_ADD);
//wait till address is transmitted
while(I2C1STATbits.TBF); // 8 clock cycles
while (!IFS1bits.MI2C1IF); //wait for 9th clock cycle
//wait for acknowledgement from slave
//while(I2C1STATbits.ACKSTAT);
/* Clear interrupt flag */
IFS1bits.MI2C1IF = 0;
//send register address : 0x0BH = 00001011
MasterWriteI2C1(0b00001011);
//wait till address is transmitted
while(I2C1STATbits.TBF); // 8 clock cycles
while (!IFS1bits.MI2C1IF); //wait for 9th clock cycle
//clear interrupt flag
IFS1bits.MI2C1IF = 0; //clear interrupt flag
//send data : 00000001
MasterWriteI2C1(0b00000001);
//wait till data is transmitted
while(I2C1STATbits.TBF); // 8 clock cycles
while (!IFS1bits.MI2C1IF); //wait for 9th clock cycle
//clear interrupt flag
IFS1bits.MI2C1IF = 0; //clear interrupt flag
StopI2C1();
/**
* set continuous mode measurement
**/
//check if idle
IdleI2C1();
//initiate start condition
StartI2C1();
//wait until start condition is over
while(I2C1CON1bits.SEN == 1);
/* Clear interrupt flag */
IFS1bits.MI2C1IF = 0;
//send magnetometer address and append the write bit
MasterWriteI2C1(0b00011010);
//wait till address is transmitted
while(I2C1STATbits.TBF); // 8 clock cycles
while (!IFS1bits.MI2C1IF); //wait for 9th clock cycle
/* Clear interrupt flag */
IFS1bits.MI2C1IF = 0;
//send register address : 0x09 = 00001001
MasterWriteI2C1(0b00001001);
//wait till address is transmitted
while(I2C1STATbits.TBF); // 8 clock cycles
while (!IFS1bits.MI2C1IF); //wait for 9th clock cycle
/* Clear interrupt flag */
IFS1bits.MI2C1IF = 0;
//send data
//send data : 00011101
MasterWriteI2C1(0b00011101);
//wait till data is transmitted
while(I2C1STATbits.TBF); // 8 clock cycles
while (!IFS1bits.MI2C1IF); //wait for 9th clock cycle
//clear interrupt flag
IFS1bits.MI2C1IF = 0; //clear interrupt flag
StopI2C1();
while(I2C1CON1bits.PEN == 1);//wait for stop condition flag to clear
//wait for magnetometer to create sample
__delay_ms(1000); }
¡La ayuda es muy apreciada!