0
\$\begingroup\$

I'm at using SAM E54 Xplained Pro to get temperature readings from a MCP9600 hooked up to a thermocouple over an I2C bus. I'm using Atmel Studio 7 with I2C drivers generated with Atmel Start. I'm using a Saleae logic analyzer to help debug.

The temperature read works fine using an optimization level of -O1, but when optimization is changed to -O0, the I2C timing is changed, resulting in faulty temperature reads.

Here is a temperature read with -O1 optimization level: enter image description here

As you can see the temperature is read as 0x016B which corresponds to about 73 degrees F.

Here is a temperature read with -O0 optimization level: enter image description here The temperature is read as 0x0101, which is incorrect.

Can anyone offer insight into why removing optimization changes things, and how I can make the code work with optimization level -O0? Any help is greatly appreciated.

Here is the code:

#include "driver_init.h"

#define MCP9600_I2C_ADDR 0x60

int main(void)
{

    struct io_descriptor *I2C_0_io;
    uint8_t th_register = 0x00; //register that holds temperature measurement
    uint8_t temp[2];

    i2c_m_sync_get_io_descriptor(&I2C_0, &I2C_0_io);
    i2c_m_sync_enable(&I2C_0);
    i2c_m_sync_set_slaveaddr(&I2C_0, MCP9600_I2C_ADDR, I2C_M_SEVEN);

    io_write(I2C_0_io, &th_register, 1);
    io_read(I2C_0_io, &temp[0], 2);


    while (1) {
    }
}

EDIT- SOLUTION Finally figured it out. Just had to reduce SCL frequency. I noticed that the clock line was a low for a lot longer between bytes for the -O0 optimization waveforms, so I figured it had something to do with the slave clock stretching. I found a note in the MCP datasheet that mentioned if the master doesn't have features to detect slave clock stretching you should reduce SCL frequency, and that worked out.

\$\endgroup\$
  • \$\begingroup\$ Hi Eugene, I added the code I wrote. The functions I'm using are generated by Atmel Start. \$\endgroup\$ – Peter Kapteyn Jul 15 at 17:49
  • \$\begingroup\$ In your O0 case there is a longer delay between the write and the read (probably depending on the optimization) which is making your hardware to behave differently. Check the device timing requirements carefully. There is nothing wrong with the code as it seems. \$\endgroup\$ – Eugene Sh. Jul 15 at 17:56
  • \$\begingroup\$ Thanks for your answer Eugene. Can you think of any ways to fix the -O0 timing that I can look into? \$\endgroup\$ – Peter Kapteyn Jul 15 at 18:01
  • \$\begingroup\$ Read it multiple times not just once, remember resetting the CPU does not reset the peripheral chip. Check return values. Don't assume vendor code cannot have things that break with a different optimization level. \$\endgroup\$ – Chris Stratton Jul 15 at 18:08
  • \$\begingroup\$ Solutions get posted in the answer field and accepted when the self answer timer expires. Do not edit them into the question, that turns the question into an unresolved zombie that will haunt the site for years. \$\endgroup\$ – Chris Stratton Jul 15 at 19:52
0
\$\begingroup\$

Finally figured it out. Just had to reduce SCL frequency. I noticed that the clock line was a low for a lot longer between bytes for the -O0 optimization waveforms, so I figured it had something to do with the slave clock stretching. I found a note in the MCP9600 datasheet that mentioned if the master doesn't have features to detect slave clock stretching you should reduce SCL frequency, and that worked out.

\$\endgroup\$

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.