I want to use the latest HAL library instead of Standard Peripheral Library.
And i want to readout the BMA250E G-sensor's chip_id, but it doesn't work.
Value of aRxBuffer always keep at 0x00. But it should be 0xf9!
What's wrong in my code?
#include "stm32f4xx_hal.h" #define I2Cx_SDA_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE() #define I2Cx_SDA_PIN GPIO_PIN_9 #define I2Cx_SDA_GPIO_PORT GPIOB #define I2Cx_SDA_AF GPIO_AF4_I2C1 #define I2Cx_SCL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE() #define I2Cx_SCL_PIN GPIO_PIN_6 #define I2Cx_SCL_GPIO_PORT GPIOB #define I2Cx_SCL_AF GPIO_AF4_I2C1 #define I2Cx_CLK_ENABLE() __HAL_RCC_I2C1_CLK_ENABLE() #define I2Cx_FORCE_RESET() __HAL_RCC_I2C1_FORCE_RESET() #define I2Cx_RELEASE_RESET() __HAL_RCC_I2C1_RELEASE_RESET()
#define I2C_ADDRESS 0x18
static void SystemClock_Config(void);
uint8_t aTxBuffer[2],aRxBuffer;
int main()
{
HAL_Init();
SystemClock_Config();
I2C_HandleTypeDef I2cHandle;
I2cHandle.Instance = I2C1;
I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
I2cHandle.Init.ClockSpeed = 400000;
I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9;
I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
I2cHandle.Init.OwnAddress1 = 0;
I2cHandle.Init.OwnAddress2 = 0;
HAL_I2C_Init(&I2cHandle);
aTxBuffer[0]=0x00;
HAL_I2C_Master_Transmit(&I2cHandle, I2C_ADDRESS,aTxBuffer, 1, 10000);
HAL_I2C_Master_Receive(&I2cHandle,I2C_ADDRESS|0x01 ,&aRxBuffer, 1, 10000);
HAL_Delay(1000);
}
static void SystemClock_Config(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 360; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; HAL_RCC_OscConfig(&RCC_OscInitStruct); RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); } void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) { GPIO_InitTypeDef GPIO_InitStruct; I2Cx_SCL_GPIO_CLK_ENABLE(); I2Cx_SDA_GPIO_CLK_ENABLE(); GPIO_InitStruct.Pin = I2Cx_SCL_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; GPIO_InitStruct.Alternate = I2Cx_SCL_AF; HAL_GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = I2Cx_SDA_PIN; GPIO_InitStruct.Alternate = I2Cx_SDA_AF; HAL_GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStruct); } void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) { I2Cx_FORCE_RESET(); I2Cx_RELEASE_RESET(); HAL_GPIO_DeInit(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN); HAL_GPIO_DeInit(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_PIN); }
First, I would advise you to use STMCube. It will set up the clock and the I2C bus for you.
It is very good practice to check what the HAL functions return. If you don't have HAL_OK
, something went wrong.
Try at 100KHz first, and then increase to 400KHz.
The I2C address of the device is 0x18
(if SDO is grounded, which I assume it is). But in the HAL driver, you have to define:
#define I2C_ADDRESS (0x18<<1)
What you want to do is to read a register, so don't use HAL_I2C_Master_Receive
or HAL_I2C_Master_Transmit
, but HAL_I2C_Mem_Read
or HAL_I2C_Mem_Write
, like this:
#define REG_CHIP_ID 0x00
HAL_I2C_Mem_Read(&I2cHandle, I2C_ADDRESS, REG_CHIP_ID, I2C_MEMADD_SIZE_8BIT, &aRxBuffer, 1, 10000);
Also, note that the HAL takes care of the R/W bit of the address, so you don't need to do:
I2C_ADDRESS|0x01