AnsweredAssumed Answered

STM32Cube I2C HAL Issues with HTU21D and BMP180

Question asked by sharma.vishnu on Oct 7, 2015
Latest reply on Oct 9, 2015 by sharma.vishnu
I am a beginner to STM32. So far, I have done a lot of work on NETMF and AVR. Starting out with STM32.

Environment:
       
  1. I have a super tiny board for STM32F103C8 (like this one here)
  2.    
  3. I have a HTU21D  sensor board (like this one here
  4.    
  5. I also have a BMP180 (which also is not working and is giving similar issues, so skipping)
  6.    
  7. 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 uses STM32Cube_FW_F1_V1.2.0 library
  2.    
  3. I am using EmBlocks IDE to write/compile the code
  4.    
  5. 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:
001./* Includes ------------------------------------------------------------------*/
002.#include "stm32f1xx_hal.h"
003. 
004./* USER CODE BEGIN Includes */
005. 
006./* USER CODE END Includes */
007. 
008./* Private variables ---------------------------------------------------------*/
009.I2C_HandleTypeDef hi2c1;
010. 
011./* USER CODE BEGIN PV */
012./* Private variables ---------------------------------------------------------*/
013.#define HTU21D_ADDRESS              0x80    /* Shifted 8-bit I2C address for the sensor */
014./* USER CODE END PV */
015. 
016./* Private function prototypes -----------------------------------------------*/
017.void SystemClock_Config(void);
018.static void MX_GPIO_Init(void);
019.static void MX_I2C1_Init(void);
020. 
021./* USER CODE BEGIN PFP */
022./* Private function prototypes -----------------------------------------------*/
023. 
024./* USER CODE END PFP */
025. 
026./* USER CODE BEGIN 0 */
027. 
028./* USER CODE END 0 */
029. 
030.int main(void)
031.{
032. 
033.  /* USER CODE BEGIN 1 */
034. 
035.  /* USER CODE END 1 */
036. 
037.  /* MCU Configuration----------------------------------------------------------*/
038. 
039.  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
040.  HAL_Init();
041. 
042.  /* Configure the system clock */
043.  SystemClock_Config();
044. 
045.  /* Initialize all configured peripherals */
046.  MX_GPIO_Init();
047.  MX_I2C1_Init();
048. 
049.  /* USER CODE BEGIN 2 */
050.  uint8_t data[] = {0xFE,0};
051.  //First do software reset of HTU21D
052.  HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&hi2c1,HTU21D_ADDRESS,data,1,100);
053.  HAL_Delay(20);
054.  //Now we will read user register
055.  data[0] = 0xE7;
056.  status = HAL_I2C_Master_Transmit(&hi2c1,HTU21D_ADDRESS,data,1,100);//write command
057.  status = HAL_I2C_Master_Receive(&hi2c1,HTU21D_ADDRESS,data,1,100);//receive data
058.  /* USER CODE END 2 */
059. 
060.  /* Infinite loop */
061.  /* USER CODE BEGIN WHILE */
062.  while (1)
063.  {
064.  /* USER CODE END WHILE */
065. 
066.  /* USER CODE BEGIN 3 */
067.  }
068.  /* USER CODE END 3 */
069. 
070.}
071. 
072./** System Clock Configuration
073.*/
074.void SystemClock_Config(void)
075.{
076. 
077.  RCC_OscInitTypeDef RCC_OscInitStruct;
078.  RCC_ClkInitTypeDef RCC_ClkInitStruct;
079. 
080.  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
081.  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
082.  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
083.  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
084.  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
085.  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
086.  HAL_RCC_OscConfig(&RCC_OscInitStruct);
087. 
088.  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;
089.  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
090.  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
091.  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
092.  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
093.  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
094. 
095.  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
096. 
097.  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
098. 
099.  /* SysTick_IRQn interrupt configuration */
100.  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
101.}
102. 
103./* I2C1 init function */
104.void MX_I2C1_Init(void)
105.{
106. 
107.  hi2c1.Instance = I2C1;
108.  hi2c1.Init.ClockSpeed = 400000;
109.  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
110.  hi2c1.Init.OwnAddress1 = 50;
111.  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
112.  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
113.  hi2c1.Init.OwnAddress2 = 0;
114.  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
115.  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
116.  HAL_I2C_Init(&hi2c1);
117. 
118.}
119. 
120./** Configure pins as
121.        * Analog
122.        * Input
123.        * Output
124.        * EVENT_OUT
125.        * EXTI
126.*/
127.void MX_GPIO_Init(void)
128.{
129. 
130.  GPIO_InitTypeDef GPIO_InitStruct;
131. 
132.  /* GPIO Ports Clock Enable */
133.  __GPIOD_CLK_ENABLE();
134.  __GPIOB_CLK_ENABLE();
135.  __GPIOA_CLK_ENABLE();
136. 
137.  /*Configure GPIO pin : PB0 */
138.  GPIO_InitStruct.Pin = GPIO_PIN_0;
139.  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
140.  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
141.  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
142. 
143.}
144. 
145./* USER CODE BEGIN 4 */
146. 
147./* USER CODE END 4 */
148. 
149.#ifdef USE_FULL_ASSERT
150. 
151./**
152.   * @brief Reports the name of the source file and the source line number
153.   * where the assert_param error has occurred.
154.   * @param file: pointer to the source file name
155.   * @param line: assert_param error line source number
156.   * @retval None
157.   */
158.void assert_failed(uint8_t* file, uint32_t line)
159.{
160.  /* USER CODE BEGIN 6 */
161.  /* User can add his own implementation to report the file name and line number,
162.    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
163.  /* USER CODE END 6 */
164. 
165.}
166. 
167.#endif
168. 
169./**
170.  * @}
171.  */
172. 
173./**
174.  * @}
175.*/
176. 
177./************************ (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 method MX_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 use GPIO_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 here). 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

Outcomes