stm32f4_discovery_lis302dl.c
504 lines
| 15.2 KiB
| text/x-c
|
CLexer
jeandet@PC-DE-JEANDET.lpp.polytechnique.fr
|
r14 | /** | ||
****************************************************************************** | ||||
* @file stm32f4_discovery_lis302dl.c | ||||
* @author MCD Application Team | ||||
* @version V1.0.0 | ||||
* @date 19-September-2011 | ||||
* @brief This file provides a set of functions needed to manage the LIS302DL | ||||
* MEMS accelerometer available on STM32F4-Discovery Kit. | ||||
****************************************************************************** | ||||
* @attention | ||||
* | ||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS | ||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE | ||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY | ||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING | ||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE | ||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. | ||||
* | ||||
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2> | ||||
****************************************************************************** | ||||
*/ | ||||
/* Includes ------------------------------------------------------------------*/ | ||||
#include "stm32f4_discovery_lis302dl.h" | ||||
//ADDED BY ME!!!!!!!!!!!!!!!!!!!! | ||||
#include "stm32f4xx_conf.h" | ||||
/** @addtogroup Utilities | ||||
* @{ | ||||
*/ | ||||
/** @addtogroup STM32F4_DISCOVERY | ||||
* @{ | ||||
*/ | ||||
/** @addtogroup STM32F4_DISCOVERY_LIS302DL | ||||
* @{ | ||||
*/ | ||||
/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_TypesDefinitions | ||||
* @{ | ||||
*/ | ||||
/** | ||||
* @} | ||||
*/ | ||||
/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Defines | ||||
* @{ | ||||
*/ | ||||
__IO uint32_t LIS302DLTimeout = LIS302DL_FLAG_TIMEOUT; | ||||
/* Read/Write command */ | ||||
#define READWRITE_CMD ((uint8_t)0x80) | ||||
/* Multiple byte read/write command */ | ||||
#define MULTIPLEBYTE_CMD ((uint8_t)0x40) | ||||
/* Dummy Byte Send by the SPI Master device in order to generate the Clock to the Slave device */ | ||||
#define DUMMY_BYTE ((uint8_t)0x00) | ||||
/** | ||||
* @} | ||||
*/ | ||||
/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Macros | ||||
* @{ | ||||
*/ | ||||
/** | ||||
* @} | ||||
*/ | ||||
/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Variables | ||||
* @{ | ||||
*/ | ||||
/** | ||||
* @} | ||||
*/ | ||||
/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_FunctionPrototypes | ||||
* @{ | ||||
*/ | ||||
static uint8_t LIS302DL_SendByte(uint8_t byte); | ||||
static void LIS302DL_LowLevel_Init(void); | ||||
/** | ||||
* @} | ||||
*/ | ||||
/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Functions | ||||
* @{ | ||||
*/ | ||||
/** | ||||
* @brief Set LIS302DL Initialization. | ||||
* @param LIS302DL_Config_Struct: pointer to a LIS302DL_Config_TypeDef structure | ||||
* that contains the configuration setting for the LIS302DL. | ||||
* @retval None | ||||
*/ | ||||
void LIS302DL_Init(LIS302DL_InitTypeDef *LIS302DL_InitStruct) | ||||
{ | ||||
uint8_t ctrl = 0x00; | ||||
/* Configure the low level interface ---------------------------------------*/ | ||||
LIS302DL_LowLevel_Init(); | ||||
/* Configure MEMS: data rate, power mode, full scale, self test and axes */ | ||||
ctrl = (uint8_t) (LIS302DL_InitStruct->Output_DataRate | LIS302DL_InitStruct->Power_Mode | \ | ||||
LIS302DL_InitStruct->Full_Scale | LIS302DL_InitStruct->Self_Test | \ | ||||
LIS302DL_InitStruct->Axes_Enable); | ||||
/* Write value to MEMS CTRL_REG1 regsister */ | ||||
LIS302DL_Write(&ctrl, LIS302DL_CTRL_REG1_ADDR, 1); | ||||
} | ||||
/** | ||||
* @brief Set LIS302DL Internal High Pass Filter configuration. | ||||
* @param LIS302DL_Filter_ConfigTypeDef: pointer to a LIS302DL_FilterConfig_TypeDef | ||||
* structure that contains the configuration setting for the LIS302DL Filter. | ||||
* @retval None | ||||
*/ | ||||
void LIS302DL_FilterConfig(LIS302DL_FilterConfigTypeDef *LIS302DL_FilterConfigStruct) | ||||
{ | ||||
uint8_t ctrl = 0x00; | ||||
/* Read CTRL_REG2 register */ | ||||
LIS302DL_Read(&ctrl, LIS302DL_CTRL_REG2_ADDR, 1); | ||||
/* Clear high pass filter cut-off level, interrupt and data selection bits*/ | ||||
ctrl &= (uint8_t)~(LIS302DL_FILTEREDDATASELECTION_OUTPUTREGISTER | \ | ||||
LIS302DL_HIGHPASSFILTER_LEVEL_3 | \ | ||||
LIS302DL_HIGHPASSFILTERINTERRUPT_1_2); | ||||
/* Configure MEMS high pass filter cut-off level, interrupt and data selection bits */ | ||||
ctrl |= (uint8_t)(LIS302DL_FilterConfigStruct->HighPassFilter_Data_Selection | \ | ||||
LIS302DL_FilterConfigStruct->HighPassFilter_CutOff_Frequency | \ | ||||
LIS302DL_FilterConfigStruct->HighPassFilter_Interrupt); | ||||
/* Write value to MEMS CTRL_REG2 register */ | ||||
LIS302DL_Write(&ctrl, LIS302DL_CTRL_REG2_ADDR, 1); | ||||
} | ||||
/** | ||||
* @brief Set LIS302DL Interrupt configuration | ||||
* @param LIS302DL_InterruptConfig_TypeDef: pointer to a LIS302DL_InterruptConfig_TypeDef | ||||
* structure that contains the configuration setting for the LIS302DL Interrupt. | ||||
* @retval None | ||||
*/ | ||||
void LIS302DL_InterruptConfig(LIS302DL_InterruptConfigTypeDef *LIS302DL_IntConfigStruct) | ||||
{ | ||||
uint8_t ctrl = 0x00; | ||||
/* Read CLICK_CFG register */ | ||||
LIS302DL_Read(&ctrl, LIS302DL_CLICK_CFG_REG_ADDR, 1); | ||||
/* Configure latch Interrupt request, click interrupts and double click interrupts */ | ||||
ctrl = (uint8_t)(LIS302DL_IntConfigStruct->Latch_Request| \ | ||||
LIS302DL_IntConfigStruct->SingleClick_Axes | \ | ||||
LIS302DL_IntConfigStruct->DoubleClick_Axes); | ||||
/* Write value to MEMS CLICK_CFG register */ | ||||
LIS302DL_Write(&ctrl, LIS302DL_CLICK_CFG_REG_ADDR, 1); | ||||
} | ||||
/** | ||||
* @brief Change the lowpower mode for LIS302DL | ||||
* @param LowPowerMode: new state for the lowpower mode. | ||||
* This parameter can be one of the following values: | ||||
* @arg LIS302DL_LOWPOWERMODE_POWERDOWN: Power down mode | ||||
* @arg LIS302DL_LOWPOWERMODE_ACTIVE: Active mode | ||||
* @retval None | ||||
*/ | ||||
void LIS302DL_LowpowerCmd(uint8_t LowPowerMode) | ||||
{ | ||||
uint8_t tmpreg; | ||||
/* Read CTRL_REG1 register */ | ||||
LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1); | ||||
/* Set new low power mode configuration */ | ||||
tmpreg &= (uint8_t)~LIS302DL_LOWPOWERMODE_ACTIVE; | ||||
tmpreg |= LowPowerMode; | ||||
/* Write value to MEMS CTRL_REG1 regsister */ | ||||
LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1); | ||||
} | ||||
/** | ||||
* @brief Data Rate command | ||||
* @param DataRateValue: Data rate value | ||||
* This parameter can be one of the following values: | ||||
* @arg LIS302DL_DATARATE_100: 100 Hz output data rate | ||||
* @arg LIS302DL_DATARATE_400: 400 Hz output data rate | ||||
* @retval None | ||||
*/ | ||||
void LIS302DL_DataRateCmd(uint8_t DataRateValue) | ||||
{ | ||||
uint8_t tmpreg; | ||||
/* Read CTRL_REG1 register */ | ||||
LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1); | ||||
/* Set new Data rate configuration */ | ||||
tmpreg &= (uint8_t)~LIS302DL_DATARATE_400; | ||||
tmpreg |= DataRateValue; | ||||
/* Write value to MEMS CTRL_REG1 regsister */ | ||||
LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1); | ||||
} | ||||
/** | ||||
* @brief Change the Full Scale of LIS302DL | ||||
* @param FS_value: new full scale value. | ||||
* This parameter can be one of the following values: | ||||
* @arg LIS302DL_FULLSCALE_2_3: +-2.3g | ||||
* @arg LIS302DL_FULLSCALE_9_2: +-9.2g | ||||
* @retval None | ||||
*/ | ||||
void LIS302DL_FullScaleCmd(uint8_t FS_value) | ||||
{ | ||||
uint8_t tmpreg; | ||||
/* Read CTRL_REG1 register */ | ||||
LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1); | ||||
/* Set new full scale configuration */ | ||||
tmpreg &= (uint8_t)~LIS302DL_FULLSCALE_9_2; | ||||
tmpreg |= FS_value; | ||||
/* Write value to MEMS CTRL_REG1 regsister */ | ||||
LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1); | ||||
} | ||||
/** | ||||
* @brief Reboot memory content of LIS302DL | ||||
* @param None | ||||
* @retval None | ||||
*/ | ||||
void LIS302DL_RebootCmd(void) | ||||
{ | ||||
uint8_t tmpreg; | ||||
/* Read CTRL_REG2 register */ | ||||
LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG2_ADDR, 1); | ||||
/* Enable or Disable the reboot memory */ | ||||
tmpreg |= LIS302DL_BOOT_REBOOTMEMORY; | ||||
/* Write value to MEMS CTRL_REG2 regsister */ | ||||
LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG2_ADDR, 1); | ||||
} | ||||
/** | ||||
* @brief Writes one byte to the LIS302DL. | ||||
* @param pBuffer : pointer to the buffer containing the data to be written to the LIS302DL. | ||||
* @param WriteAddr : LIS302DL's internal address to write to. | ||||
* @param NumByteToWrite: Number of bytes to write. | ||||
* @retval None | ||||
*/ | ||||
void LIS302DL_Write(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite) | ||||
{ | ||||
/* Configure the MS bit: | ||||
- When 0, the address will remain unchanged in multiple read/write commands. | ||||
- When 1, the address will be auto incremented in multiple read/write commands. | ||||
*/ | ||||
if(NumByteToWrite > 0x01) | ||||
{ | ||||
WriteAddr |= (uint8_t)MULTIPLEBYTE_CMD; | ||||
} | ||||
/* Set chip select Low at the start of the transmission */ | ||||
LIS302DL_CS_LOW(); | ||||
/* Send the Address of the indexed register */ | ||||
LIS302DL_SendByte(WriteAddr); | ||||
/* Send the data that will be written into the device (MSB First) */ | ||||
while(NumByteToWrite >= 0x01) | ||||
{ | ||||
LIS302DL_SendByte(*pBuffer); | ||||
NumByteToWrite--; | ||||
pBuffer++; | ||||
} | ||||
/* Set chip select High at the end of the transmission */ | ||||
LIS302DL_CS_HIGH(); | ||||
} | ||||
/** | ||||
* @brief Reads a block of data from the LIS302DL. | ||||
* @param pBuffer : pointer to the buffer that receives the data read from the LIS302DL. | ||||
* @param ReadAddr : LIS302DL's internal address to read from. | ||||
* @param NumByteToRead : number of bytes to read from the LIS302DL. | ||||
* @retval None | ||||
*/ | ||||
void LIS302DL_Read(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead) | ||||
{ | ||||
if(NumByteToRead > 0x01) | ||||
{ | ||||
ReadAddr |= (uint8_t)(READWRITE_CMD | MULTIPLEBYTE_CMD); | ||||
} | ||||
else | ||||
{ | ||||
ReadAddr |= (uint8_t)READWRITE_CMD; | ||||
} | ||||
/* Set chip select Low at the start of the transmission */ | ||||
LIS302DL_CS_LOW(); | ||||
/* Send the Address of the indexed register */ | ||||
LIS302DL_SendByte(ReadAddr); | ||||
/* Receive the data that will be read from the device (MSB First) */ | ||||
while(NumByteToRead > 0x00) | ||||
{ | ||||
/* Send dummy byte (0x00) to generate the SPI clock to LIS302DL (Slave device) */ | ||||
*pBuffer = LIS302DL_SendByte(DUMMY_BYTE); | ||||
NumByteToRead--; | ||||
pBuffer++; | ||||
} | ||||
/* Set chip select High at the end of the transmission */ | ||||
LIS302DL_CS_HIGH(); | ||||
} | ||||
/** | ||||
* @brief Read LIS302DL output register, and calculate the acceleration | ||||
* ACC[mg]=SENSITIVITY* (out_h*256+out_l)/16 (12 bit rappresentation) | ||||
* @param s16 buffer to store data | ||||
* @retval None | ||||
*/ | ||||
void LIS302DL_ReadACC(int32_t* out) | ||||
{ | ||||
uint8_t buffer[6]; | ||||
uint8_t crtl, i = 0x00; | ||||
LIS302DL_Read(&crtl, LIS302DL_CTRL_REG1_ADDR, 1); | ||||
LIS302DL_Read(buffer, LIS302DL_OUT_X_ADDR, 6); | ||||
switch(crtl & 0x20) | ||||
{ | ||||
/* FS bit = 0 ==> Sensitivity typical value = 18milligals/digit*/ | ||||
case 0x00: | ||||
for(i=0; i<0x03; i++) | ||||
{ | ||||
*out =(int32_t)(LIS302DL_SENSITIVITY_2_3G * (int8_t)buffer[2*i]); | ||||
out++; | ||||
} | ||||
break; | ||||
/* FS bit = 1 ==> Sensitivity typical value = 72milligals/digit*/ | ||||
case 0x20: | ||||
for(i=0; i<0x03; i++) | ||||
{ | ||||
*out =(int32_t)(LIS302DL_SENSITIVITY_9_2G * (int8_t)buffer[2*i]); | ||||
out++; | ||||
} | ||||
break; | ||||
default: | ||||
break; | ||||
} | ||||
} | ||||
/** | ||||
* @brief Initializes the low level interface used to drive the LIS302DL | ||||
* @param None | ||||
* @retval None | ||||
*/ | ||||
static void LIS302DL_LowLevel_Init(void) | ||||
{ | ||||
GPIO_InitTypeDef GPIO_InitStructure; | ||||
SPI_InitTypeDef SPI_InitStructure; | ||||
/* Enable the SPI periph */ | ||||
RCC_APB2PeriphClockCmd(LIS302DL_SPI_CLK, ENABLE); | ||||
/* Enable SCK, MOSI and MISO GPIO clocks */ | ||||
RCC_AHB1PeriphClockCmd(LIS302DL_SPI_SCK_GPIO_CLK | LIS302DL_SPI_MISO_GPIO_CLK | LIS302DL_SPI_MOSI_GPIO_CLK, ENABLE); | ||||
/* Enable CS GPIO clock */ | ||||
RCC_AHB1PeriphClockCmd(LIS302DL_SPI_CS_GPIO_CLK, ENABLE); | ||||
/* Enable INT1 GPIO clock */ | ||||
RCC_AHB1PeriphClockCmd(LIS302DL_SPI_INT1_GPIO_CLK, ENABLE); | ||||
/* Enable INT2 GPIO clock */ | ||||
RCC_AHB1PeriphClockCmd(LIS302DL_SPI_INT2_GPIO_CLK, ENABLE); | ||||
GPIO_PinAFConfig(LIS302DL_SPI_SCK_GPIO_PORT, LIS302DL_SPI_SCK_SOURCE, LIS302DL_SPI_SCK_AF); | ||||
GPIO_PinAFConfig(LIS302DL_SPI_MISO_GPIO_PORT, LIS302DL_SPI_MISO_SOURCE, LIS302DL_SPI_MISO_AF); | ||||
GPIO_PinAFConfig(LIS302DL_SPI_MOSI_GPIO_PORT, LIS302DL_SPI_MOSI_SOURCE, LIS302DL_SPI_MOSI_AF); | ||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; | ||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; | ||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; | ||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; | ||||
/* SPI SCK pin configuration */ | ||||
GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_SCK_PIN; | ||||
GPIO_Init(LIS302DL_SPI_SCK_GPIO_PORT, &GPIO_InitStructure); | ||||
/* SPI MOSI pin configuration */ | ||||
GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_MOSI_PIN; | ||||
GPIO_Init(LIS302DL_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure); | ||||
/* SPI MISO pin configuration */ | ||||
GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_MISO_PIN; | ||||
GPIO_Init(LIS302DL_SPI_MISO_GPIO_PORT, &GPIO_InitStructure); | ||||
/* SPI configuration -------------------------------------------------------*/ | ||||
SPI_I2S_DeInit(LIS302DL_SPI); | ||||
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; | ||||
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; | ||||
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; | ||||
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; | ||||
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; | ||||
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; | ||||
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; | ||||
SPI_InitStructure.SPI_CRCPolynomial = 7; | ||||
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; | ||||
SPI_Init(LIS302DL_SPI, &SPI_InitStructure); | ||||
/* Enable SPI1 */ | ||||
SPI_Cmd(LIS302DL_SPI, ENABLE); | ||||
/* Configure GPIO PIN for Lis Chip select */ | ||||
GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_CS_PIN; | ||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; | ||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; | ||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; | ||||
GPIO_Init(LIS302DL_SPI_CS_GPIO_PORT, &GPIO_InitStructure); | ||||
/* Deselect : Chip Select high */ | ||||
GPIO_SetBits(LIS302DL_SPI_CS_GPIO_PORT, LIS302DL_SPI_CS_PIN); | ||||
/* Configure GPIO PINs to detect Interrupts */ | ||||
GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_INT1_PIN; | ||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; | ||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; | ||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; | ||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; | ||||
GPIO_Init(LIS302DL_SPI_INT1_GPIO_PORT, &GPIO_InitStructure); | ||||
GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_INT2_PIN; | ||||
GPIO_Init(LIS302DL_SPI_INT2_GPIO_PORT, &GPIO_InitStructure); | ||||
} | ||||
/** | ||||
* @brief Sends a Byte through the SPI interface and return the Byte received | ||||
* from the SPI bus. | ||||
* @param Byte : Byte send. | ||||
* @retval The received byte value | ||||
*/ | ||||
static uint8_t LIS302DL_SendByte(uint8_t byte) | ||||
{ | ||||
/* Loop while DR register in not emplty */ | ||||
LIS302DLTimeout = LIS302DL_FLAG_TIMEOUT; | ||||
while (SPI_I2S_GetFlagStatus(LIS302DL_SPI, SPI_I2S_FLAG_TXE) == RESET) | ||||
{ | ||||
if((LIS302DLTimeout--) == 0) return LIS302DL_TIMEOUT_UserCallback(); | ||||
} | ||||
/* Send a Byte through the SPI peripheral */ | ||||
SPI_I2S_SendData(LIS302DL_SPI, byte); | ||||
/* Wait to receive a Byte */ | ||||
LIS302DLTimeout = LIS302DL_FLAG_TIMEOUT; | ||||
while (SPI_I2S_GetFlagStatus(LIS302DL_SPI, SPI_I2S_FLAG_RXNE) == RESET) | ||||
{ | ||||
if((LIS302DLTimeout--) == 0) return LIS302DL_TIMEOUT_UserCallback(); | ||||
} | ||||
/* Return the Byte read from the SPI bus */ | ||||
return (uint8_t)SPI_I2S_ReceiveData(LIS302DL_SPI); | ||||
} | ||||
#ifdef USE_DEFAULT_TIMEOUT_CALLBACK | ||||
/** | ||||
* @brief Basic management of the timeout situation. | ||||
* @param None. | ||||
* @retval None. | ||||
*/ | ||||
uint32_t LIS302DL_TIMEOUT_UserCallback(void) | ||||
{ | ||||
/* Block communication and all processes */ | ||||
while (1) | ||||
{ | ||||
} | ||||
} | ||||
#endif /* USE_DEFAULT_TIMEOUT_CALLBACK */ | ||||
/** | ||||
* @} | ||||
*/ | ||||
/** | ||||
* @} | ||||
*/ | ||||
/** | ||||
* @} | ||||
*/ | ||||
/** | ||||
* @} | ||||
*/ | ||||
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ | ||||