以STSW-STLKT01例程里的LSM6DSM加速度传感器的初始化为例分析一下各种函数是怎么调用的
在main.c文件中有一个initializeAllSensors函数,用来初始化所有传感器
通过调用BSP_ACCELERO_Init( LSM6DSM_X_0, &LSM6DSM_X_0_handle
) 实现LSM6DSM加速度传感器的初始化
if (BSP_ACCELERO_Init( LSM6DSM_X_0, &LSM6DSM_X_0_handle
) != COMPONENT_OK)
{
while(1);
}
|
BSP_ACCELERO_Init函数在SensorTile_accelero.c里
现在的文件关系是main.c ->SensorTile_accelero.c
SensorTile_accelero.c里的DrvStatusTypeDef
BSP_ACCELERO_Init( ACCELERO_ID_t id, void **handle )函数通过id来判断初始化哪个加速度传感器
因为SensorTile上有2颗IC都有加速度功能
id是ACCELERO_SENSORS_AUTO时先初始化LSM6DSM里的加速度传感器,如果LSM6DSM初始化失败再初始化LSM303AGR
id是LSM6DSM_X_0时初始化LSM6DSM
id是LSM303AGR_X_0时初始化LSM303AGR
见下边代码
DrvStatusTypeDef
BSP_ACCELERO_Init( ACCELERO_ID_t
id, void **handle
)
{
*handle = NULL;
switch(id)
{
case ACCELERO_SENSORS_AUTO:
default:
{
/* Try to init the LSM6DSM before */
if(BSP_LSM6DSM_ACCELERO_Init(handle) == COMPONENT_ERROR
)
{
/* Normally it must not happen */
/* Try to init the LSM303AGR accelerometer */
if( BSP_LSM303AGR_ACCELERO_Init(handle) == COMPONENT_ERROR
)
{
return COMPONENT_ERROR;
}
}
break;
}
case LSM6DSM_X_0:
{
if( BSP_LSM6DSM_ACCELERO_Init(handle) == COMPONENT_ERROR
)
{
return COMPONENT_ERROR;
}
break;
}
case LSM303AGR_X_0:
{
if( BSP_LSM303AGR_ACCELERO_Init(handle) == COMPONENT_ERROR
)
{
return COMPONENT_ERROR;
}
break;
}
}
return COMPONENT_OK;
}
|
当id为LSM6DSM_X_0 时执行了static DrvStatusTypeDef
BSP_LSM6DSM_ACCELERO_Init( void **handle )函数
static DrvStatusTypeDef
BSP_LSM6DSM_ACCELERO_Init( void **handle
)
{
ACCELERO_Drv_t *driver = NULL;
uint8_t data = 0x0C;
if(ACCELERO_SensorHandle[ LSM6DSM_X_0
].isInitialized == 1)
{
/* We have reached the max num of instance for this component */
return COMPONENT_ERROR;
}
if ( Sensor_IO_SPI_Init() == COMPONENT_ERROR
)
{
return COMPONENT_ERROR;
}
/* Setup sensor handle. */
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].who_am_i
= LSM6DSM_ACC_GYRO_WHO_AM_I;
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].ifType
= 1; //
SPI interface
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].address
= LSM6DSM_ACC_GYRO_I2C_ADDRESS;
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].spiDevice
= LSM6DSM;
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].instance
= LSM6DSM_X_0;
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].isInitialized
= 0;
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].isEnabled
= 0;
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].isCombo
= 1;
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].pData
= ( void * )&ACCELERO_Data[ LSM6DSM_X_0
];
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].pVTable
= ( void * )&LSM6DSM_X_Drv;
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].pExtVTable
= ( void * )&LSM6DSM_X_ExtDrv;
LSM6DSM_X_0_Data.comboData = &LSM6DSM_Combo_Data[0];
ACCELERO_Data[ LSM6DSM_X_0 ].pComponentData
= ( void * )&LSM6DSM_X_0_Data;
ACCELERO_Data[ LSM6DSM_X_0 ].pExtData
= 0;
*handle = (void *)&ACCELERO_SensorHandle[ LSM6DSM_X_0
];
Sensor_IO_SPI_CS_Init(*handle);
if(LSM6DSM_Combo_Data[0].isGyroInitialized
== 0)
{
// SPI Serial Interface Mode selection --> 3Wires
if( Sensor_IO_Write(*handle, LSM6DSM_ACC_GYRO_CTRL3_C, &data, 1) )
{
return COMPONENT_ERROR;
}
}
driver = ( ACCELERO_Drv_t
* )((DrvContextTypeDef
*)(*handle))->pVTable;
if ( driver->Init
== NULL )
{
memset((*handle), 0, sizeof(DrvContextTypeDef));
*handle = NULL;
return COMPONENT_ERROR;
}
if ( driver->Init( (DrvContextTypeDef
*)(*handle) ) == COMPONENT_ERROR
)
{
memset((*handle), 0, sizeof(DrvContextTypeDef));
*handle = NULL;
return COMPONENT_ERROR;
}
/* Configure interrupt lines for LSM6DSM */
LSM6DSM_Sensor_IO_ITConfig();
return COMPONENT_OK;
}
|
红字部分
ACCELERO_SensorHandle[ LSM6DSM_X_0 ].pVTable = ( void * )&LSM6DSM_X_Drv;中的LSM6DSM_X_Drv类型为ACCELERO_Drv_t结构体,结构体中定义了一些基本函数
LSM6DSM_X_ExtDrv定义了一些额外的扩展函数
typedef struct
{
DrvStatusTypeDef ( *Init
) ( DrvContextTypeDef* );
DrvStatusTypeDef ( *DeInit
) ( DrvContextTypeDef* );
DrvStatusTypeDef ( *Sensor_Enable
) ( DrvContextTypeDef* );
DrvStatusTypeDef ( *Sensor_Disable
) ( DrvContextTypeDef* );
DrvStatusTypeDef ( *Get_WhoAmI
) ( DrvContextTypeDef*, uint8_t* );
DrvStatusTypeDef ( *Check_WhoAmI
) ( DrvContextTypeDef* );
DrvStatusTypeDef ( *Get_Axes
) ( DrvContextTypeDef*, SensorAxes_t* );
DrvStatusTypeDef ( *Get_AxesRaw
) ( DrvContextTypeDef*, SensorAxesRaw_t* );
DrvStatusTypeDef ( *Get_Sensitivity
) ( DrvContextTypeDef*, float* );
DrvStatusTypeDef ( *Get_ODR
) ( DrvContextTypeDef*, float* );
DrvStatusTypeDef ( *Set_ODR
) ( DrvContextTypeDef*, SensorOdr_t
);
DrvStatusTypeDef ( *Set_ODR_Value
) ( DrvContextTypeDef*, float );
DrvStatusTypeDef ( *Get_FS
) ( DrvContextTypeDef*, float* );
DrvStatusTypeDef ( *Set_FS
) ( DrvContextTypeDef*, SensorFs_t
);
DrvStatusTypeDef ( *Set_FS_Value
) ( DrvContextTypeDef*, float );
DrvStatusTypeDef ( *Get_Axes_Status
) ( DrvContextTypeDef*, uint8_t* );
DrvStatusTypeDef ( *Set_Axes_Status
) ( DrvContextTypeDef*, uint8_t* );
} ACCELERO_Drv_t;
|
typedef struct
{
/* Identity */
uint8_t who_am_i;
/* Configuration */
uint8_t ifType;
/* 0 means I2C, 1 means SPI, etc. */
uint8_t address;
/* Sensor I2C address (NOTE: Not a unique sensor ID). */
uint8_t spiDevice;
/* Sensor Chip Select for SPI Bus */
uint8_t instance;
/* Sensor instance (NOTE: Sensor ID unique only within its
class). */
uint8_t isInitialized; /*
Sensor setup done. */
uint8_t isEnabled;
/* Sensor ON. */
uint8_t isCombo;
/* Combo sensor (component consists of more sensors). */
/* Pointer to the Data */
void *pData;
/* Pointer to the Virtual Table */
void *pVTable;
/* Pointer to the Extended Virtual Table */
void *pExtVTable;
} DrvContextTypeDef;
|
初始化的时候把LSM6DSM_ACC_GYRO_driver_HL.c里的基本函数填了进去
ACCELERO_Drv_t
LSM6DSM_X_Drv =
{
LSM6DSM_X_Init,
LSM6DSM_X_DeInit,
LSM6DSM_X_Sensor_Enable,
LSM6DSM_X_Sensor_Disable,
LSM6DSM_X_Get_WhoAmI,
LSM6DSM_X_Check_WhoAmI,
LSM6DSM_X_Get_Axes,
LSM6DSM_X_Get_AxesRaw,
LSM6DSM_X_Get_Sensitivity,
LSM6DSM_X_Get_ODR,
LSM6DSM_X_Set_ODR,
LSM6DSM_X_Set_ODR_Value,
LSM6DSM_X_Get_FS,
LSM6DSM_X_Set_FS,
LSM6DSM_X_Set_FS_Value,
0,
0
};
|
现在的文件关系是main.c ->SensorTile_accelero.c –> LSM6DSM_ACC_GYRO_driver_HL.c
BSP_LSM6DSM_ACCELERO_Init函数后来通过
driver = ( ACCELERO_Drv_t *
)((DrvContextTypeDef *)(*handle))->pVTable;
把pVTable赋值给driver
接下来判断driver->Init是否为空
if ( driver->Init == NULL )
然后通过driver->Init调用LSM6DSM_ACC_GYRO_driver_HL.c 中的LSM6DSM_X_Init函数
if ( driver->Init( (DrvContextTypeDef
*)(*handle) ) == COMPONENT_ERROR
)
初始化函数LSM6DSM_X_Init如下
static DrvStatusTypeDef
LSM6DSM_X_Init( DrvContextTypeDef *handle
)
{
ACCELERO_Data_t *pData = ( ACCELERO_Data_t
* )handle->pData;
LSM6DSM_X_Data_t *pComponentData
= ( LSM6DSM_X_Data_t
* )pData->pComponentData;
LSM6DSM_Combo_Data_t *comboData = pComponentData->comboData;
if ( LSM6DSM_Check_WhoAmI( handle
) == COMPONENT_ERROR
)
{
return COMPONENT_ERROR;
}
/* Enable register address automatically incremented during a
multiple byte
access with a serial interface. */
if ( LSM6DSM_ACC_GYRO_W_IF_Addr_Incr( (void *)handle, LSM6DSM_ACC_GYRO_IF_INC_ENABLED
) == MEMS_ERROR )
{
return COMPONENT_ERROR;
}
/* Enable BDU */
if ( LSM6DSM_ACC_GYRO_W_BDU( (void *)handle, LSM6DSM_ACC_GYRO_BDU_BLOCK_UPDATE
) == MEMS_ERROR )
{
return COMPONENT_ERROR;
}
/* FIFO mode selection */
if ( LSM6DSM_ACC_GYRO_W_FIFO_MODE( (void *)handle, LSM6DSM_ACC_GYRO_FIFO_MODE_BYPASS
) == MEMS_ERROR )
{
return COMPONENT_ERROR;
}
/* Select default output data rate. */
pComponentData->Previous_ODR = 104.0f;
/*
Output data rate selection - power down. */
if ( LSM6DSM_ACC_GYRO_W_ODR_XL( (void *)handle, LSM6DSM_ACC_GYRO_ODR_XL_POWER_DOWN
) == MEMS_ERROR )
{
return COMPONENT_ERROR;
}
/* Full scale selection. */
if ( LSM6DSM_X_Set_FS( handle, FS_LOW
) == COMPONENT_ERROR
)
{
return COMPONENT_ERROR;
}
comboData->isAccInitialized = 1;
handle->isInitialized = 1;
return COMPONENT_OK;
}
|
LSM6DSM_X_Init函数第一步先判断WhoAmI是否正确
if ( LSM6DSM_Check_WhoAmI( handle
) == COMPONENT_ERROR
)
{
return COMPONENT_ERROR;
}
LSM6DSM_ACC_GYRO_driver_HL.c 中的LSM6DSM_Check_WhoAmI函数
static DrvStatusTypeDef
LSM6DSM_Check_WhoAmI( DrvContextTypeDef
*handle )
{
uint8_t who_am_i = 0x00;
if ( LSM6DSM_Get_WhoAmI( handle, &who_am_i
) == COMPONENT_ERROR
)
{
return COMPONENT_ERROR;
}
if ( who_am_i != handle->who_am_i
)
{
return COMPONENT_ERROR;
}
return COMPONENT_OK;
}
|
LSM6DSM_Check_WhoAmI函数通过LSM6DSM_Get_WhoAmI函数来读取WhoAmI
static DrvStatusTypeDef
LSM6DSM_Get_WhoAmI( DrvContextTypeDef
*handle, uint8_t *who_am_i
)
{
/* Read WHO AM I register */
if ( LSM6DSM_ACC_GYRO_R_WHO_AM_I( (void *)handle, ( uint8_t* )who_am_i
) == MEMS_ERROR )
{
return COMPONENT_ERROR;
}
return COMPONENT_OK;
}
|
LSM6DSM_Get_WhoAmI函数调用了LSM6DSM_ACC_GYRO_driver.c文件中的LSM6DSM_ACC_GYRO_R_WHO_AM_I函数
现在的文件关系是main.c ->SensorTile_accelero.c –> LSM6DSM_ACC_GYRO_driver_HL.c
-> LSM6DSM_ACC_GYRO_driver.c
LSM6DSM_ACC_GYRO_R_WHO_AM_I函数通过LSM6DSM_ACC_GYRO_ReadReg函数来读对应的LSM6DSM_ACC_GYRO_WHO_AM_I_REG寄存器
status_t
LSM6DSM_ACC_GYRO_R_WHO_AM_I(void *handle, u8_t
*value)
{
if( !LSM6DSM_ACC_GYRO_ReadReg(handle, LSM6DSM_ACC_GYRO_WHO_AM_I_REG, (u8_t
*)value) )
return MEMS_ERROR;
*value &= LSM6DSM_ACC_GYRO_WHO_AM_I_BIT_MASK; //coerce
*value = *value
>> LSM6DSM_ACC_GYRO_WHO_AM_I_BIT_POSITION; //mask
return MEMS_SUCCESS;
}
|
LSM6DSM_ACC_GYRO_ReadReg函数调用SensorTile.c文件中的Sensor_IO_Read函数来读取寄存器数据
status_t
LSM6DSM_ACC_GYRO_ReadReg(void *handle, u8_t
Reg, u8_t* Data)
{
if (Sensor_IO_Read(handle, Reg, Data, 1))
{
return MEMS_ERROR;
}
else
{
return MEMS_SUCCESS;
}
}
|
现在的文件关系是main.c ->SensorTile_accelero.c –> LSM6DSM_ACC_GYRO_driver_HL.c
-> LSM6DSM_ACC_GYRO_driver.c -> SensorTile.c
Sensor_IO_Read函数通过ifType来决定使用I2C总线还是SPI总线
在BSP_LSM6DSM_ACCELERO_Init
函数里有一句话ACCELERO_SensorHandle[
LSM6DSM_X_0 ].ifType = 1; // SPI
interface
确定为使用SPI总线
通过调用Sensor_IO_SPI_Read函数通过SPI读取寄存器数据
uint8_t Sensor_IO_Read( void *handle, uint8_t ReadAddr, uint8_t *pBuffer, uint16_t nBytesToRead
)
{
DrvContextTypeDef *ctx = (DrvContextTypeDef
*)handle;
if(ctx->ifType
== 0)
{
return Sensor_IO_I2C_Read( handle, ReadAddr, pBuffer, nBytesToRead
);
}
if(ctx->ifType
== 1)
{
return Sensor_IO_SPI_Read( handle, ReadAddr, pBuffer, nBytesToRead
);
}
return COMPONENT_ERROR;
}
|
Sensor_IO_SPI_Read函数通过Sensor_IO_SPI_CS_Enable函数来控制CS线的输出
Sensor_IO_SPI_CS_Enable函数通过调用stm32l4xx_hal_gpio.c里的对应函数来控制CS线的电平
现在的文件关系是main.c ->SensorTile_accelero.c –> LSM6DSM_ACC_GYRO_driver_HL.c
-> LSM6DSM_ACC_GYRO_driver.c -> SensorTile.c -> stm32l4xx_hal_gpio.c
uint8_t Sensor_IO_SPI_CS_Enable(void *handle)
{
DrvContextTypeDef *ctx = (DrvContextTypeDef
*)handle;
switch(ctx->spiDevice)
{
case LSM6DSM:
HAL_GPIO_WritePin(SENSORTILE_LSM6DSM_SPI_CS_Port, SENSORTILE_LSM6DSM_SPI_CS_Pin, GPIO_PIN_RESET);
break;
case LSM303AGR_X:
HAL_GPIO_WritePin(SENSORTILE_LSM303AGR_X_SPI_CS_Port, SENSORTILE_LSM303AGR_X_SPI_CS_Pin, GPIO_PIN_RESET);
break;
case LSM303AGR_M:
HAL_GPIO_WritePin(SENSORTILE_LSM303AGR_M_SPI_CS_Port, SENSORTILE_LSM303AGR_M_SPI_CS_Pin, GPIO_PIN_RESET);
break;
case LPS22HB:
HAL_GPIO_WritePin(SENSORTILE_LPS22HB_SPI_CS_Port, SENSORTILE_LPS22HB_SPI_CS_Pin, GPIO_PIN_RESET);
break;
}
return COMPONENT_OK;
}
|
同时Sensor_IO_SPI_Read函数通过调用SPI_Write和SPI_Read函数来读到数据
uint8_t Sensor_IO_SPI_Read( void *handle, uint8_t ReadAddr, uint8_t *pBuffer, uint16_t nBytesToRead
)
{
uint8_t i;
//
Select the correct device
Sensor_IO_SPI_CS_Enable(handle);
SPI_Write(&SPI_Sensor_Handle, ReadAddr
| 0x80);
//
SYNCHRO_WAIT(SYNCHRO_SPI_DELAY);
__HAL_SPI_DISABLE(&SPI_Sensor_Handle);
SPI_1LINE_RX(&SPI_Sensor_Handle);
//
SYNCHRO_WAIT(SYNCHRO_SPI_DELAY);
for(i=0;i<nBytesToRead;i++)
{
SPI_Read(&SPI_Sensor_Handle, pBuffer++);
}
//
SYNCHRO_WAIT(SYNCHRO_SPI_DELAY);
SPI_1LINE_TX(&SPI_Sensor_Handle);
__HAL_SPI_ENABLE(&SPI_Sensor_Handle);
//
SYNCHRO_WAIT(SYNCHRO_SPI_DELAY);
// Deselect the device
Sensor_IO_SPI_CS_Disable(handle);
return COMPONENT_OK;
}
|
SPI_Write和SPI_Read直接操作SPI寄存器
/**
*
@brief This function send a command through SPI bus.
*
@param command : command id.
*
@param val : value.
*
@retval None
*/
void SPI_Read(SPI_HandleTypeDef* xSpiHandle, uint8_t *val)
{
/* In master RX mode the clock is automaticaly generated on the
SPI enable.
So to guarantee the clock generation for only one data, the clock must be
disabled after the first bit and before the latest bit */
/* Interrupts should be disabled during this operation */
__disable_irq();
__HAL_SPI_ENABLE(xSpiHandle);
__asm("dsb\n");
__asm("dsb\n");
__HAL_SPI_DISABLE(xSpiHandle);
__enable_irq();
while ((xSpiHandle->Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE);
/* read the received data */
*val = *(__IO
uint8_t *) &xSpiHandle->Instance->DR;
while ((xSpiHandle->Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY);
}
/**
*
@brief This function send a command through SPI bus.
*
@param command : command id.
*
@param val : value.
*
@retval None
*/
void SPI_Write(SPI_HandleTypeDef* xSpiHandle, uint8_t val)
{
/* check TXE flag */
while ((xSpiHandle->Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE);
/* Write the data */
*((__IO uint8_t*) &xSpiHandle->Instance->DR) = val;
/* Wait BSY flag */
while ((xSpiHandle->Instance->SR & SPI_FLAG_FTLVL) != SPI_FTLVL_EMPTY);
while ((xSpiHandle->Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY);
}
|
同时Sensor_IO_SPI_Read函数还调用了stm32l4xx_hal_spi.h文件中的SPI_1LINE_RX和SPI_1LINE_TX函数(宏定义)
/** @brief
Set the SPI transmit-only mode.
* @param __HANDLE__: specifies the SPI Handle.
* This parameter can be SPI
where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#define
SPI_1LINE_TX(__HANDLE__) ((__HANDLE__)->Instance->CR1 |=
SPI_CR1_BIDIOE)
/** @brief
Set the SPI receive-only mode.
* @param __HANDLE__: specifies the SPI Handle.
* This parameter can be SPI
where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#define
SPI_1LINE_RX(__HANDLE__) ((__HANDLE__)->Instance->CR1 &=
(~SPI_CR1_BIDIOE))
|
最后的文件关系是
main.c ->SensorTile_accelero.c –> LSM6DSM_ACC_GYRO_driver_HL.c
-> LSM6DSM_ACC_GYRO_driver.c -> SensorTile.c -> stm32l4xx_hal_gpio.c
main.c ->SensorTile_accelero.c –> LSM6DSM_ACC_GYRO_driver_HL.c
-> LSM6DSM_ACC_GYRO_driver.c -> SensorTile.c ->stm32l4xx_hal_spi.h