1
\$\begingroup\$

I am working on a project using the dsPIC33FJ128MC510, and I spent a week trying to solve a problem with the I2C bus.

My problem is that the I2C bus (both SDA and SCL) is high all the time. No clock and no data. EDIT : while doing step by step I can see BCL bit (from I2C1STAT register) going high as soon as I want to emit a START condition.

I checked the hardware configuration and everything is fine. I have an automatic bidirectionnal level shifter compatible with open-drain, external 4k7 pull-up on 3V3 and 5V sides (see schematic below):

enter image description here

The level shifter is working fine as I can see the correct waveforms when generating DIY pulses instead of enabling the I2C module. As soon as I enable the I2C module the problem appears.

Please note that the dsPIC33FJ128MC510 was not supported by MCC so I had to use the I2C MCC file from another dsPIC33F microcontroller but registers seem to be compatible between the two microcontrollers. I just changed the I2C_Initialize function and the clock configuration. See below the code for I2C_Initialization():

void I2C1_Initialize(void)
{
    
    i2c1_object.pTrHead = i2c1_tr_queue;
    i2c1_object.pTrTail = i2c1_tr_queue;
    i2c1_object.trStatus.s.empty = true;
    i2c1_object.trStatus.s.full = false;

    i2c1_object.i2cErrors = 0;
    
    // initialize the hardware
    // Baud Rate Generator Value: I2CBRG 76;   
    I2C1BRG = 0x4C; // @TODO :  26 before
    // ACKEN disabled; STRICT disabled; STREN disabled; GCEN disabled; SMEN disabled; DISSLW enabled; I2CSIDL disabled; ACKDT Sends ACK; SCLREL Holds; RSEN disabled; A10M 7 Bit; PEN disabled; RCEN disabled; SEN disabled; I2CEN enabled; 
    I2C1CON = 0x8000;
    // BCL disabled; P disabled; S disabled; I2COV disabled; IWCOL disabled; 
    I2C1STAT = 0x00;

    /* I2C1 Master Events */
    // clear the master interrupt flag
    IFS1bits.MI2C1IF = 0;
    // enable the master interrupt
    IEC1bits.MI2C1IE = 1;

}

Here is the code for the clock configuration:

void CLOCK_Initialize(void)
{
    // FRCDIV FRC/1; PLLPRE 8; DOZE 1:8; PLLPOST 1:8; DOZEN disabled; ROI disabled; 
    CLKDIV = 0x30C6;
    
    CLKDIVbits.PLLPOST = 1; // TODO : comment if it doesn't solve the CAN problem. UART baudrate is now x2. Need to multiply U1BRG by 2 in UART1.C and adapt TIMERS
    // Fosc is now 32MHz. Fp= 16MHz
//    CLKDIVbits.DOZE = 1; // TODO : comment if it doesn't solve the CAN problem. Now Fcy = 8MHz (same as before normally ...)
//    CLKDIVbits.DOZEN = 0; // TODO : comment if it doesn't solve the CAN problem. Now Fcy = 8MHz (same as before normally ...)
    // TUN Center frequency; 
    OSCTUN = 0x00;
    // PLLDIV 137; 
    PLLFBD = 0x89;
    
    // AD1MD enabled; PWMMD enabled; T3MD enabled; T4MD enabled; T1MD enabled; U2MD enabled; T2MD enabled; U1MD enabled; SPI2MD enabled; SPI1MD enabled; C1MD enabled; T5MD enabled; I2C1MD enabled; 
    PMD1 = 0x00;
    // IC4MD enabled; IC3MD enabled; OC1MD enabled; IC2MD enabled; OC2MD enabled; IC1MD enabled; OC3MD enabled; OC4MD enabled; 
    PMD2 = 0x00;
    // CMPMD enabled; 
    PMD3 = 0x00;
   
    // CF no clock failure; NOSC FRCPLL; CLKLOCK unlocked; OSWEN Switch is Complete; 
    __builtin_write_OSCCONH((uint8_t) (0x01));
    __builtin_write_OSCCONL((uint8_t) (0x01));
    // Wait for Clock switch to occur
    while (OSCCONbits.OSWEN != 0);
    while (OSCCONbits.LOCK != 1);
}

And here are the two functions thare are called in the main(). These two functions worked with another microcontroller dsPIC33EV128GM106 so the problem is probably not here.

void setup_SHT31(void) {
    
    SHT31.SHT31_ID = 0x44;
   
    pfSHT31_main.tempsEnMs = &tempsEnMsDspic;
    pfSHT31_main.I2C1_MasterReadTRBBuild = &I2C1_MasterReadTRBBuild;
    pfSHT31_main.I2C1_MasterTRBInsert = &I2C1_MasterTRBInsert;
    pfSHT31_main.I2C1_MasterWriteTRBBuild = &I2C1_MasterWriteTRBBuild;

    SHT31_initialize(&SHT31, &pfSHT31_main);
}

void SHT31_initialize(TypeSHT31 *ID, Type_pfSHT31 *pfSHT31 )
{
    pfSHT31_lib = (*pfSHT31); //recopie des pointeurs de fonctions

    
}

void SHT31_readData(TypeSHT31 *ID)
{
    
    (*ID).temps_init = pfSHT31_lib.tempsEnMs();
    
    SHT31_I2C1_MESSAGE_STATUS status = SHT31_I2C1_MESSAGE_PENDING;
    static SHT31_I2C1_TRANSACTION_REQUEST_BLOCK trb[2];
    
    
    (*ID).tampon_ecriture[0] = 0x2C; //clock streching
    (*ID).tampon_ecriture[1] = 0x0D; //med repetability

    
    status = SHT31_I2C1_MESSAGE_PENDING;
    pfSHT31_lib.I2C1_MasterWriteTRBBuild(&trb[0], &(*ID).tampon_ecriture, 2, (*ID).SHT31_ID);
    pfSHT31_lib.I2C1_MasterTRBInsert(1, &trb[0], &status);
    
        while(status == SHT31_I2C1_MESSAGE_PENDING && (pfSHT31_lib.tempsEnMs() - (*ID).temps_init) < SHT31_TIMOUT_in_ms)
    {
      Nop(); //stay here
    }

    
    //attente 5ms // temps de conversion moyen
    while ((pfSHT31_lib.tempsEnMs() - (*ID).temps_init) < SHT31_CONV_TIME_in_ms)
    {
        Nop();
    }
    
    
    
    status = SHT31_I2C1_MESSAGE_PENDING;
    pfSHT31_lib.I2C1_MasterReadTRBBuild(&trb[0], (*ID).tampon_lecture, 6, (*ID).SHT31_ID);                
    pfSHT31_lib.I2C1_MasterTRBInsert(1, &trb[0], &status);
    

    
        while(status == SHT31_I2C1_MESSAGE_PENDING && (pfSHT31_lib.tempsEnMs() - (*ID).temps_init) < SHT31_TIMOUT_in_ms)
    {
      Nop(); //stay here
    }
    

    
    if ((pfSHT31_lib.tempsEnMs() - (*ID).temps_init) < SHT31_TIMOUT_in_ms)
    {
    (*ID).readTemperature.Bits.MSB = (*ID).tampon_lecture[0];
    (*ID).readTemperature.Bits.LSB = (*ID).tampon_lecture[1];
    
    (*ID).readHumidity.Bits.MSB = (*ID).tampon_lecture[3]; 
    (*ID).readHumidity.Bits.LSB = (*ID).tampon_lecture[4]; 
    
    
    ///conversion
    (*ID).Temperature_in_degres = -45.0 + 175.0 * (*ID).readTemperature.Word / 65535.0;
    
    (*ID).Humidity_in_pc = 100.0 * (*ID).readHumidity.Word / 65535.0;
    
    
    
    (*ID).status = 1;
    }
    else 
    {
     (*ID).status = 2;   
    }       
}

Any help would be greatly appreciated!

\$\endgroup\$
7
  • \$\begingroup\$ Have you checked the document - "dsPIC33FJXXXMCX06/X08/X10 Family Silicon Errata and Data Sheet Clarification" at ww1.microchip.com/downloads/aemDocuments/documents/OTH/… . There are quite a number of i2c issues with that chip. \$\endgroup\$
    – HandyHowie
    Feb 1, 2023 at 9:35
  • \$\begingroup\$ @HandyHowie Yes I did implement the required changes but it does not work. Normally I should see at least a START condition on SDA when setting the SEN bit but I see nothing. \$\endgroup\$ Feb 1, 2023 at 9:50
  • \$\begingroup\$ It might just be a software issue, but it might also be hanged because a glitch happened on the bus, and the cause of the glitch may be the automatic level shifter. Which exact level shifter it is and how it is used, how long traces or wires it has on either side, what size pull-up resistors you use, etc? Post the schematics. \$\endgroup\$
    – Justme
    Feb 1, 2023 at 10:08
  • \$\begingroup\$ @Justme I posted the schematic. Track length is around 20cm (with Zo = 50R). So total capacitive load on the bus should be around 25pF. Also I checked the stability of SDA, SCL, 3V3 and 5V with the scope but no external glitches \$\endgroup\$ Feb 1, 2023 at 10:34
  • \$\begingroup\$ @Justme : also I edited my post after doing step by step in MPLABX I can see the BCL bit from I2C1STAT going high as soon as I emit a start condition \$\endgroup\$ Feb 1, 2023 at 11:00

1 Answer 1

1
\$\begingroup\$

OK I finally solved the problem.

I started by removing the level shifter and scoping on the 3V3 side but nothing on the bus.

Solution was to initialize the ports correctly, even if the datasheet says explicitly that we should not care about setting the ports. Missing settings were ODC + TRIS

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.