cancel
Showing results for 
Search instead for 
Did you mean: 

I2C Troubleshooting without an oscilloscope

Matthieu Tanguay
Associate II
Posted on July 20, 2017 at 22:52

Hello everyone,

I recently got myself a little nucleo compatible

http://www.waveshare.com/w/upload/3/3a/Accessory-Shield-Schematic.pdf

that comes with at I2C Temperature sensor 

http://www.nxp.com/docs/en/data-sheet/LM75B.pdf

. After carefully reading the datasheet I felt confident that I could get a working code quick enough. As a first test I decided to try to do a read of the temperature sensor using the pointer. I found some example online that I modified for my needs that look something like that : 

I2C_HandleTypeDef hi2c1;

volatile uint8_t buffer[5];

volatile uint16_t rawTemp;

int16_t Temp;

void TempMeasurement(void){

buffer[0] = 0x00; //Pointer to the Temp. Register

HAL_I2C_Master_Transmit(&hi2c1,0x48<<1,buffer,1,100); //Send pointer for Temperature Register

HAL_Delay(10);

HAL_I2C_Master_Receive(&hi2c1,0x48<<1,buffer,2,100);

//Buffer[0] : MSB

//Buffer[1] : LSB

printf('Buffer After %d\r\n',buffer[0]);

rawTemp = buffer[0]<<5 | buffer[1]; //combine 2 MSB and LSB in one 10 bit number

}

I use the cube to generate the basic code for the I2C Bus. I also know that the sensor is working because I ran the provided mbed code as a check to verify that the electric part of the 'project' is working. If you could help with the code that would be great. On the other hand what I am interested in is ways that I can use HAL librairies to inspect where and how the code is breaking?

I tried to dig into the code and found various values like TIMEOUT and ERROR. Could I use these to check how my bus is failing?

Thank you in advance. 

1 ACCEPTED SOLUTION

Accepted Solutions
john doe
Lead
Posted on July 21, 2017 at 03:09

one command looks more complex than the three you're doing? i'm simply adding sanity checks anyone should be doing. making sure the bus is ready. making sure the device is ready.  otherwise, i've actually replaced two commands and a delay, with one. and done some error checking.

regardless, the point im trying to make is look at the definition of the function you're trying to use and meet it's demands.  the HAL wants a pointer to a buffer's address. you're not giving it that. that may be one of your problems with your code.

your code:

HAL_I2C_Master_Transmit(&hi2c1,0x48<<1,buffer,1,100); //Send pointer for Temperature Register

HAL_Delay(10);

HAL_I2C_Master_Receive(&hi2c1,0x48<<1,buffer,2,100);

this is the definition for Master_Transmit

HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)

it returns the status of the command

it wants a pointer to the address of the handle

it wants the device's i2c address, as a 16 bit integer left-aligned

it wants a pointer to the address of the variable containing the data

it wants the size of the data in numbers of bytes

it wants to know how long to wait in ms before the timeout

your code:

attempt to transmit

wait for 10 ms

attempt to receive

try:

is device ready

if yes, transmit to device

if no, handle it

is transmit finished

if yes, receive response

if no, handle it

View solution in original post

4 REPLIES 4
Posted on July 21, 2017 at 00:04

Hello!

In your code   you use  hi2c1 without initialize it

Is it an external handle initialised somewere else?

extern I2C_HandleTypeDef hi2c1;

john doe
Lead
Posted on July 21, 2017 at 01:17

to read a register use I2C_MemRead();

while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY) {}

while (HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(0x48<<1), 3, 100) != HAL_OK) {}

HAL_StatusTypeDef status = HAL_OK;

status = HAL_I2C_Mem_Read(&hi2c1,                             // i2c handle

                             (uint16_t)(0x48<<1),                             // i2c address, left aligned

                             (uint16_t)register_addr,                        // register address

                             I2C_MEMADD_SIZE_8BIT,                  // device uses 8-bit register addresses

                             (uint8_t*)(&buffer),                                // variable to put returned value

                             2,                                                         // return two bytes

                             100);                                                    // timeout in ms

    if(status != HAL_OK)

    {

      switch(status)

           {

                     case HAL_ERROR: do error stuff; break;

                     case HAL_BUSY: do busy stuff; break;

                     case HAL_TIMEOUT: do timeout stuff; break;

           }

    }

as far as troubleshooting without a scope goes, you probably have a debugger in your tool chain, and a person can go pretty far with an LED and a few printf() statements

john doe
Lead
Posted on July 21, 2017 at 03:09

one command looks more complex than the three you're doing? i'm simply adding sanity checks anyone should be doing. making sure the bus is ready. making sure the device is ready.  otherwise, i've actually replaced two commands and a delay, with one. and done some error checking.

regardless, the point im trying to make is look at the definition of the function you're trying to use and meet it's demands.  the HAL wants a pointer to a buffer's address. you're not giving it that. that may be one of your problems with your code.

your code:

HAL_I2C_Master_Transmit(&hi2c1,0x48<<1,buffer,1,100); //Send pointer for Temperature Register

HAL_Delay(10);

HAL_I2C_Master_Receive(&hi2c1,0x48<<1,buffer,2,100);

this is the definition for Master_Transmit

HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)

it returns the status of the command

it wants a pointer to the address of the handle

it wants the device's i2c address, as a 16 bit integer left-aligned

it wants a pointer to the address of the variable containing the data

it wants the size of the data in numbers of bytes

it wants to know how long to wait in ms before the timeout

your code:

attempt to transmit

wait for 10 ms

attempt to receive

try:

is device ready

if yes, transmit to device

if no, handle it

is transmit finished

if yes, receive response

if no, handle it

Posted on July 21, 2017 at 02:45

Is there an issue doing a receive the way I chose to? Because the 

I2C_MemRead(); method looks a lot more complex and less straight forward?