Tengo un problema al usar I2C en un dsPIC33EP512MU810. Utilizo la biblioteca periférica para PIC24 y dsPIC33 para administrar los registros, pero también escribí algunas funciones. Aquí están las funciones que uso para I2C
#include <xc.h>
#include <stdint.h>
#include "I2C1.h"
#include <i2c.h>
#include <libpic30.h>
#include "common.h"
void Open_I2C1(void)
{
// Configre SCA/SDA pin as open-drain. This may change from device to device.
//Refer the datasheet for more information.
ODCDbits.ODCD9 = 0;
ODCDbits.ODCD10 = 0;
OpenI2C1((I2C2_ON & I2C2_IDLE_CON & I2C2_CLK_HLD & I2C2_IPMI_DIS &
I2C2_7BIT_ADD & I2C2_SLW_EN & I2C2_SM_DIS &
I2C2_GCALL_DIS & I2C2_STR_DIS &
I2C2_NACK & I2C2_ACK_DIS & I2C2_RCV_DIS &
I2C2_STOP_DIS & I2C2_RESTART_DIS &
I2C2_START_DIS), 0x4E);
IdleI2C1();
I2C1CONbits.I2CEN = 1;
IEC1bits.MI2C1IE = 1;
IFS1bits.MI2C1IF = 0;
}
void WriteByte_I2C1(unsigned char WriteAddressIC, unsigned char WriteAddressRegister, uint8_t MSByte, uint8_t LSByte)
{
ResetVariables_I2C1();
Start_I2C1();
while(!IFS1bits.MI2C1IF);
IFS1bits.MI2C1IF=0;
//Write Slave address and set master for transmission
MasterWriteI2C1(WriteAddressIC);
WaitFlag_I2C1();
WaitForACK_I2C1();
MasterWriteI2C1(WriteAddressRegister);
WaitFlag_I2C1();
WaitForACK_I2C1();
MasterWriteI2C1(MSByte);
WaitFlag_I2C1();
WaitForACK_I2C1();
MasterWriteI2C1(LSByte);
WaitFlag_I2C1();
WaitForACK_I2C1();
ResetVariables_I2C1();
StopI2C1();
WaitFlag_I2C1();
WaitForACK_I2C1();
IdleI2C1();
}
uint16_t ReadByte_I2C1 (unsigned char ReadAddressIC, unsigned char RegisterAddress)
{
uint8_t Byte = 0x00;
uint16_t result = 0x0000;
ResetVariables_I2C1();
Start_I2C1();
while((!IFS1bits.MI2C1IF)) {
}
//Write Slave address and set master for transmission
MasterWriteI2C1(ReadAddressIC);
WaitFlag_I2C1();
WaitForACK_I2C1();
MasterWriteI2C1(RegisterAddress);
WaitFlag_I2C1();
WaitForACK_I2C1();
ResetVariables_I2C1();
RestartI2C1();
WaitFlag_I2C1();
MasterWriteI2C1(ReadAddressIC + 1);
WaitFlag_I2C1();
WaitForACK_I2C1();
ResetVariables_I2C1();
I2C1CONbits.RCEN = 1;
while(I2C1CONbits.RCEN)
{
LATCbits.LATC2 ^= 1;
}
I2C1STATbits.I2COV = 0;
Byte = I2C1RCV;
result = Byte<<8;
WaitFlag_I2C1();
I2C1CONbits.RCEN = 1;
while(I2C1CONbits.RCEN)
{
LATCbits.LATC2 ^= 1;
}
I2C1STATbits.I2COV = 0;
Byte = I2C1RCV;
result |= Byte;
WaitFlag_I2C1();
ResetVariables_I2C1();
NotAckI2C1();
WaitFlag_I2C1();
ResetVariables_I2C1();
StopI2C1();
WaitFlag_I2C1();
IdleI2C1();
return Byte;
}
void ResetVariables_I2C1(void)
{
I2C1CONbits.ACKEN=0;
I2C1CONbits.PEN=0;
I2C1CONbits.RCEN=0;
I2C1CONbits.RSEN=0;
I2C1CONbits.SEN=0;
}
void WaitFlag_I2C1(void)
{
while(!IFS1bits.MI2C1IF);
LATCbits.LATC2 ^=1; // wait for flag to be high
IFS1bits.MI2C1IF=0;
}
void WaitForACK_I2C1(void)
{
while(I2C1STATbits.ACKSTAT); // wait for ack receive from slave
LATCbits.LATC2 ^=1;
}
void Start_I2C1(void){
I2C1CONbits.SEN = 1;
}
Cuando uso la función de escritura, la función se detiene justo después de enviar la condición de inicio porque la bandera nunca se establece. Lo medí con la buena y antigua técnica de paso de LED en la que enciendo un LED después de cada paso para ver cuándo se detiene. También eché un vistazo a la línea SDA y SCL con un osciloscopio y solo puedo ver las condiciones de inicio. También verifiqué la configuración de mi hardware, por ejemplo, si todo está conectado, no hay cortocircuitos o casi cortocircuitos y verifiqué si puedo usar otros dispositivos para comunicarme con el IC con el que quiero hablar con el dsPIC33. También verifiqué si uso los pines correctos. Uso ASD1/RD9 y ASCL1/RD10, lo que significa que tengo que configurar 'ALTI2C1 = ON' en los bits de configuración.
Pero ahora me quedé sin ideas de qué podría ser lo que hice mal aquí y por qué la bandera no se levanta. Estaría agradecido si alguien pudiera señalarme en la dirección correcta aquí
Creo que encontré la respuesta. En la función de inicialización encendí la interrupción I2C, aunque no tengo un ISR. No configurar IEC1bits.MI2C1IE resolvió mi problema
adam lorenzo