cancel
Showing results for 
Search instead for 
Did you mean: 

STM32Cube I2C HAL Issues with HTU21D and BMP180

vishnusmoke
Associate
Posted on October 07, 2015 at 13:16

I am a beginner to STM So far, I have done a lot of work on NETMF and AVR. Starting out with STM

Environment:
  1. I have a super tiny board for STM32F103C8 (like this one

    http://artofcircuits.com/product/minimum-system-development-board-for-arm-microcontroller-stm32f103c8t6

    )
  2. I have a HTU21D sensor board (like this one

    https://www.sparkfun.com/products/12064

    )
  3. I also have a BMP180 (which also is not working and is giving similar issues, so skipping)
  4. The SDA/SCL have been pulled up using 4.7K resistors.

S/W Setup:

  1. I used STM32CubeMX tool to create a project. The tool usesSTM32Cube_FW_F1_V1.2.0 library
  2. I am using EmBlocks IDE to write/compile the code
  3. I have used the STM32CubeMX with EmBlocks successfully for other non-I2C projects on the same board (e.g. USB HID, GPIO, UART)

The code in main.c is given below:


/* Includes ------------------------------------------------------------------*/

#include ''stm32f1xx_hal.h''


/* USER CODE BEGIN Includes */


/* USER CODE END Includes */


/* Private variables ---------------------------------------------------------*/

I2C_HandleTypeDef hi2c1;


/* USER CODE BEGIN PV */

/* Private variables ---------------------------------------------------------*/

#define HTU21D_ADDRESS 0x80 /* Shifted 8-bit I2C address for the sensor */

/* USER CODE END PV */


/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_I2C1_Init(void);


/* USER CODE BEGIN PFP */

/* Private function prototypes -----------------------------------------------*/


/* USER CODE END PFP */


/* USER CODE BEGIN 0 */


/* USER CODE END 0 */


int main(void)

{


/* USER CODE BEGIN 1 */


/* USER CODE END 1 */


/* MCU Configuration----------------------------------------------------------*/


/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();


/* Configure the system clock */

SystemClock_Config();


/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_I2C1_Init();


/* USER CODE BEGIN 2 */

uint8_t data[] = {0xFE,0};

//First do software reset of HTU21D

HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&hi2c1,HTU21D_ADDRESS,data,1,100);

HAL_Delay(20);

//Now we will read user register

data[0] = 0xE7;

status = HAL_I2C_Master_Transmit(&hi2c1,HTU21D_ADDRESS,data,1,100);//write command

status = HAL_I2C_Master_Receive(&hi2c1,HTU21D_ADDRESS,data,1,100);//receive data

/* USER CODE END 2 */


/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

/* USER CODE END WHILE */


/* USER CODE BEGIN 3 */

}

/* USER CODE END 3 */


}


/** System Clock Configuration

*/

void SystemClock_Config(void)

{


RCC_OscInitTypeDef RCC_OscInitStruct;

RCC_ClkInitTypeDef RCC_ClkInitStruct;


RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

RCC_OscInitStruct.HSEState = RCC_HSE_ON;

RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;

HAL_RCC_OscConfig(&RCC_OscInitStruct);


RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);


HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);


HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);


/* SysTick_IRQn interrupt configuration */

HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

}


/* I2C1 init function */

void MX_I2C1_Init(void)

{


hi2c1.Instance = I2C1;

hi2c1.Init.ClockSpeed = 400000;

hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;

hi2c1.Init.OwnAddress1 = 50;

hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;

hi2c1.Init.OwnAddress2 = 0;

hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;

hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;

HAL_I2C_Init(&hi2c1);


}


/** Configure pins as

* Analog

* Input

* Output

* EVENT_OUT

* EXTI

*/

void MX_GPIO_Init(void)

{


GPIO_InitTypeDef GPIO_InitStruct;


/* GPIO Ports Clock Enable */

__GPIOD_CLK_ENABLE();

__GPIOB_CLK_ENABLE();

__GPIOA_CLK_ENABLE();


/*Configure GPIO pin : PB0 */

GPIO_InitStruct.Pin = GPIO_PIN_0;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


}


/* USER CODE BEGIN 4 */


/* USER CODE END 4 */


#ifdef USE_FULL_ASSERT


/**

* @brief Reports the name of the source file and the source line number

* where the assert_param error has occurred.

* @param file: pointer to the source file name

* @param line: assert_param error line source number

* @retval None

*/

void assert_failed(uint8_t* file, uint32_t line)

{

/* USER CODE BEGIN 6 */

/* User can add his own implementation to report the file name and line number,

ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */

/* USER CODE END 6 */


}


#endif


/**

* @}

*/


/**

* @}

*/


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Between line #50 and #60, is the code I added. First, we send a command (0xFE) to the sensor to do ''Soft Reset''. After that, we send command (0xEF) to read the user register, and then, we finally read the returned data. None of this works. Each line simply returns the status as HAL_BUSY. I went through a lot of forum posts and gathered the following: 1. IsDeviceReady is only for memory devices and should not be used (I was using it to test connection earlier, but then removed it, as here also, I was getting HAL_BUSY status) 2. The ''OwnAddress'' should not be left to 0 (zero). So I changed it to 50 (see methodMX_I2C1_Init) 3. The GPIO setup for PB6/7 should be ''Open Drain''. I checked the method named ''HAL_I2C_MspInit'' in the file named ''stm32f1xx_hal_msp.c'' (autogenerated by the cube tool) and the initialization does useGPIO_MODE_AF_OD 4. One forum post said ''STM32Cube software with HAL is buggy''. So I created an I2C slave in Arduino (see sample code

https://www.arduino.cc/en/Tutorial/MasterReader

). When I use ''HAL_I2C_IsDeviceReady'' method and ''HAL_I2C_Master_Transmit/HAL_I2C_Master_Receive'' methods, I'm able to get the value ''hello'' in the STM32 buffer. Therefore, the S/W for I2C is not buggy. Hence the question is....what am I doing wrong here ? Any pointer to highlight my stupidity would be of great help. Thanks, Vishnu #hal #i2c #stm32 #cubemx
1 REPLY 1
vishnusmoke
Associate
Posted on October 09, 2015 at 07:01

No suggestions for 2 days is surprising , but I did find the answer...

4.7K resistances are no good. Use a lower value. 2.2K did work for me.

The BMP180 board that I have, has 4.7K resistors soldered in such a way, that with the tools I have, I cannot take those out. So have ordered for a new board that allows me to choose the pull-up resistance values.

-Thanks