Skip to main content
Graduate II
January 29, 2024
Solved

I2C HAL_BUSY Debugging Help

  • January 29, 2024
  • 2 replies
  • 3382 views

Currently I am trying to interface with a LM75A temperature sensor using the STM32F446RE nucleo board.

From the datasheet of the LM75A, I gathered that the sensor, returns a temperature measurement without any configuration.

So I tried to simply hook up the LM75A (with floating Address Pins) and connecting it to the I2C1 port on the STM32.

Addressing the slave on the given default address of 0x48h

 

The code below returns HAL_BUSY, and locks up. Since I do not have a Logic Analyzer at home, I cannot manually debug what is going on.

 

#include "COM_Driver.h"
#include "LM75A_Driver.h"
#include <string.h>
int main(){

 LM75_Init();
 COM_Init();

 uint8_t data[2];
 float temperature;
 char tes[8];
 while (1)
 {
 HAL_StatusTypeDef status = LM75_ReadReg(LM75A_ADDRESS, LM75_TEMP_REG, data, 2);
 if (status != HAL_OK)
 {
 // Handle I2C communication error
 continue; // Skip to the next iteration of the loop
 }

 temperature = (float)((data[0] << 8) | data[1]) / 256;
 sprintf(tes, "%f\n", temperature);
 COM_printf(tes);
 COM_printf("Hi!");

 HAL_Delay(1000);

 }
}

LM75 Driver is simply an abstraction of HAL_MASTER_TRANSMIT()

#include "LM75A_Driver.h"

I2C_HandleTypeDef hi2c;

// Initialize I2C peripheral and GPIO pins
void LM75_Init(void)
{

 // Enable clock for I2C peripheral and GPIO port
 I2Cx_CLK_ENABLE();
 I2Cx_GPIO_CLK_ENABLE();

 GPIO_InitTypeDef GPIO_InitStruct = {0};

 // Configure SCL, SDA pins as alternate function
 GPIO_InitStruct.Pin = I2Cx_SCL_PIN | I2Cx_SDA_PIN;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 GPIO_InitStruct.Alternate = I2Cx_AF;

 __HAL_RCC_GPIOB_CLK_ENABLE();

 HAL_GPIO_Init(I2Cx_GPIO_PORT, &GPIO_InitStruct);

 __HAL_RCC_I2C1_CLK_ENABLE();

 // I2C peripheral configuration
 hi2c.Instance = I2Cx;
 hi2c.Init.ClockSpeed = 300000; // Adjust as needed
 hi2c.Init.DutyCycle = I2C_DUTYCYCLE_2;
 hi2c.Init.OwnAddress1 = 0;
 hi2c.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 hi2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
 hi2c.Init.OwnAddress2 = 0;
 hi2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
 hi2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

 if (HAL_I2C_Init(&hi2c) != HAL_OK)
 {
 // Initialization Error
 Error_Handler();
 }
}

// Write data to an I2C device
HAL_StatusTypeDef LM75_WriteReg(uint8_t device_address, uint8_t register_address, uint8_t *data, uint16_t size)
{
 if (register_address == LM75_TEMP_REG || register_address == LM75_INFO_REG)
 {
 return HAL_ERROR;
 }

 return HAL_I2C_Master_Transmit(&hi2c, device_address, data, size, HAL_MAX_DELAY);
}

// Read data from an I2C device
HAL_StatusTypeDef LM75_ReadReg(uint8_t device_address, uint8_t register_address, uint8_t *data, uint16_t size)
{
 return HAL_I2C_Master_Receive(&hi2c, device_address, data, size, HAL_MAX_DELAY);
}

And COM_printf() is a implemented function to print the temperature data to my computers terminal! There are no bugs in that piece of code.

Also I have not handled the HAL Errors since this is a prototype code.

If you have any suggestions from my code code that would be much appreciated.


    This topic has been closed for replies.
    Best answer by TDK

    Use HAL_I2C_IsDeviceReady to verify your slave address is being acknowledged. It should return HAL_OK. If it does not, recheck your address and wiring. A 7-bit address should be left-shifted by one bit.

    Note that your LM75_ReadReg function doesn't use register_address at all so is not likely to be implemented correctly.

    Consider using HAL_I2C_Mem_Read and HAL_I2C_Mem_Write instead.

    2 replies

    TDKAnswer
    Super User
    January 29, 2024

    Use HAL_I2C_IsDeviceReady to verify your slave address is being acknowledged. It should return HAL_OK. If it does not, recheck your address and wiring. A 7-bit address should be left-shifted by one bit.

    Note that your LM75_ReadReg function doesn't use register_address at all so is not likely to be implemented correctly.

    Consider using HAL_I2C_Mem_Read and HAL_I2C_Mem_Write instead.

    Super User
    January 29, 2024

    > with floating Address Pins

    This means the address is not defined. Pins should be grounded or tied to 3.3V to establish a 0 or 1 for those bits.

    TDK_0-1706497501339.png

     

    Visitor II
    January 30, 2024

    My five cents (as TDK has mentioned):

    verify what the I2C Slave Address format is:
    Sometimes datasheet, schematics... give you a slave address based on 8bit (where bit 0 is actually RD/nWR).

    Sometimes they give you a 7bit Slave Addr, without the bit 0 considered.

    My suggestion:
    Try the given slave address, e.g. 0x48 and try also to shift this address <<1 or >>1. e.g. 0x90 vs. 0x24.
    Sometimes, it is confusing to know if Slave Address is given as 8bit or 7bit address (with or without the bit 0).
    But you should get a NACK if address is wrong. Verify which error code you get from I2C driver.

    Graduate II
    February 1, 2024

    Hi!

    Thank you for taking the time to look at my issue!

    I just soldered the address pins to point to address 0x48 today (Soldered all Address pins directly to ground). I utilized the same code, as I was using before, and the problem has not gone away. 

    I also looked at my implementation of LM75_ReadReg, as mentioned by @TDK , and the problem still stands. The address was defined in a .h file for the LM75A driver (passed through by the calling function), and the function call in LM75A .c file looked something like this:

     

    HAL_StatusTypeDef LM75_ReadReg(uint8_t device_address, uint8_t register_address, uint8_t *data, uint16_t size)
    {
     return HAL_I2C_Master_Receive(&hi2c, device_address, data, size, HAL_MAX_DELAY);
    }

     

    I know that some of the parameters in the LM75_ReadReg are unneeded, like the register address, the only reason it is there is to facilitate some future logic to handle reading different registers.

    I tried multiple different addresses, tried shifting both left and right by 1, but never got anything other than HAL_BUSY.

    I tried to debug it using the STLink on the nucleo board, but found that after the first iteration of the loop where the I2C port indicates a HAL_Busy, the second iteration completely freezes the program. There is no output to the stlink registers, and there nothing being printed.