0
\$\begingroup\$

I have a bit of a problem figuring out how harmony i2c driver works. Trying to establish connection between PIC32 and a barometric sensor MS5637 have been a bit of a nightmare for me.

From sensor's datasheet on page 9 we can see that there is a reset sequence and after that a simple prom read. Below you can see what am i trying to do, but I am not quite shure what should I do to make this communication work.

Using MHC the i2c driver is initialized inside System Initialize and then there is my app code.

void send(uint8_t cmd){

    //Start i2c
    DRV_I2C0_MasterStart();

    //Write address write
    DRV_I2C0_ByteWrite(0xEC);
    DRV_I2C0_WaitForByteWriteToComplete();

    //Write command
    DRV_I2C0_ByteWrite(cmd);
    DRV_I2C0_WaitForByteWriteToComplete();

    //Stop i2c
    DRV_I2C0_MasterStop();

}

uint16_t readPROM(uint8_t cmd){
    uint16_t value;

    //Send Prom address
    send(cmd);

    //Start i2c
    DRV_I2C0_MasterStart();

    //Write address read
    DRV_I2C0_ByteWrite(0xED);
    DRV_I2C0_WaitForByteWriteToComplete();

    //Byte read MSB
    DRV_I2C0_WaitForReadByteAvailable();
    value = 256 * DRV_I2C0_ByteRead ();
    DRV_I2C0_MasterACKSend();

    //Byte read LSB
    DRV_I2C0_WaitForReadByteAvailable();
    value = DRV_I2C0_ByteRead();
    DRV_I2C0_MasterNACKSend();

    //Stop i2c
    DRV_I2C0_MasterStop();

    return value;
}

void APP_Tasks ( void ){
    //Reset command
    send(0x1E);
    ShortDelay( 3000 ); //3 ms

    //Read prom
    uint8_t i;
    for (i=0;i<8;i++){
        readPROM(0xA0 + i * 2 );
    }
}

Response is always 0x00, but should be something different than that.

I forgot to mention when sending any kind of command on the i2c lines the current rises on sensor. Does this mean the sensor is responding?

If there might be anything obvious I am missing, please warn me, because this is the first time for me using the i2c.

\$\endgroup\$
  • \$\begingroup\$ Things to try when debugging something like this (in order): Check your connected to the correct pins by setting to high and testing with a multimeter. Check your setting the port directions correctly for I2C Check you have the correct pull up resistors. Check you are outputting any data with a scope. After you have confirmed your outputting data you can start checking pins on the slave device and double checking the commands are correct. Let us know how you get on \$\endgroup\$ – silverscania Nov 25 '15 at 17:34
  • \$\begingroup\$ Thanks for the debugging advices, but there is where everything stops for me, because I only have multimeter with the ability to measure 20 kHz max. So I set the i2c frequency to 10 kHz and multimeter is not recognising anything. What is the right way to measure i2c clock? Putting one end between pullup resistor and chip pin-out and the other end to the ground? \$\endgroup\$ – Nejc Okorn Nov 25 '15 at 19:34
  • \$\begingroup\$ Yes that's the right connection. But you won't see anything with a multimeter. Just get a cheap USB oscilloscope off eBay, it will save you weeks of debugging. \$\endgroup\$ – silverscania Nov 26 '15 at 17:15
2
\$\begingroup\$

After a long time of debugging my own code I started to debug harmony's I2C static driver and notice that inside of DRV_I2C0_MasterACKSend and DRV_I2C0_MasterNACKSend is a checking like

void DRV_I2C0_MasterACKSend(void)
{
    if(!PLIB_I2C_MasterReceiverReadyToAcknowledge(I2C_ID_1))
        PLIB_I2C_ReceivedByteAcknowledge (I2C_ID_1, true);

}

and all you have to do is to change the if statement to while loop

void DRV_I2C0_MasterACKSend(void)
{
    /* Check if receive is ready to ack */
    while(!PLIB_I2C_MasterReceiverReadyToAcknowledge(I2C_ID_1));
    PLIB_I2C_ReceivedByteAcknowledge (I2C_ID_1, true);

}

I noticed in I2C static driver protocol there is a loot of waiting(looping) and I am afraid the main program will lock itself in some of those loops for some case of scenario

\$\endgroup\$
2
\$\begingroup\$

Additionally, DRV_I2C0_WaitForReadByteAvailable() is a non blocking comparison, so with your implementation you might find it more useful to wrap it with a while loop, to become

while(!DRV_I2C0_WaitForReadByteAvailable());

This will sufficiently wait for the condition to be met, and your read will be successful.

\$\endgroup\$
  • \$\begingroup\$ I agree with you. I did already implemented as you said, but I have to say the name of the the function should be something like check... not wait... It made me think the function will wait until byte is available \$\endgroup\$ – Nejc Okorn May 3 '16 at 17:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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