2 ******************************************************************************
3 * @file stm32f4_discovery_lis302dl.c
4 * @author MCD Application Team
6 * @date 19-September-2011
7 * @brief This file provides a set of functions needed to manage the LIS302DL
8 * MEMS accelerometer available on STM32F4-Discovery Kit.
9 ******************************************************************************
12 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
13 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
14 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
15 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
16 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
17 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
19 * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
20 ******************************************************************************
23 /* Includes ------------------------------------------------------------------*/
24 #include "stm32f4_discovery_lis302dl.h"
25 //ADDED BY ME!!!!!!!!!!!!!!!!!!!!
26 #include "stm32f4xx_conf.h"
28 /** @addtogroup Utilities
32 /** @addtogroup STM32F4_DISCOVERY
36 /** @addtogroup STM32F4_DISCOVERY_LIS302DL
41 /** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_TypesDefinitions
49 /** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Defines
52 __IO uint32_t LIS302DLTimeout = LIS302DL_FLAG_TIMEOUT;
54 /* Read/Write command */
55 #define READWRITE_CMD ((uint8_t)0x80)
56 /* Multiple byte read/write command */
57 #define MULTIPLEBYTE_CMD ((uint8_t)0x40)
58 /* Dummy Byte Send by the SPI Master device in order to generate the Clock to the Slave device */
59 #define DUMMY_BYTE ((uint8_t)0x00)
65 /** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Macros
73 /** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Variables
81 /** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_FunctionPrototypes
84 static uint8_t LIS302DL_SendByte(uint8_t byte);
85 static void LIS302DL_LowLevel_Init(void);
90 /** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Functions
96 * @brief Set LIS302DL Initialization.
97 * @param LIS302DL_Config_Struct: pointer to a LIS302DL_Config_TypeDef structure
98 * that contains the configuration setting for the LIS302DL.
101 void LIS302DL_Init(LIS302DL_InitTypeDef *LIS302DL_InitStruct)
105 /* Configure the low level interface ---------------------------------------*/
106 LIS302DL_LowLevel_Init();
108 /* Configure MEMS: data rate, power mode, full scale, self test and axes */
109 ctrl = (uint8_t) (LIS302DL_InitStruct->Output_DataRate | LIS302DL_InitStruct->Power_Mode | \
110 LIS302DL_InitStruct->Full_Scale | LIS302DL_InitStruct->Self_Test | \
111 LIS302DL_InitStruct->Axes_Enable);
113 /* Write value to MEMS CTRL_REG1 regsister */
114 LIS302DL_Write(&ctrl, LIS302DL_CTRL_REG1_ADDR, 1);
118 * @brief Set LIS302DL Internal High Pass Filter configuration.
119 * @param LIS302DL_Filter_ConfigTypeDef: pointer to a LIS302DL_FilterConfig_TypeDef
120 * structure that contains the configuration setting for the LIS302DL Filter.
123 void LIS302DL_FilterConfig(LIS302DL_FilterConfigTypeDef *LIS302DL_FilterConfigStruct)
127 /* Read CTRL_REG2 register */
128 LIS302DL_Read(&ctrl, LIS302DL_CTRL_REG2_ADDR, 1);
130 /* Clear high pass filter cut-off level, interrupt and data selection bits*/
131 ctrl &= (uint8_t)~(LIS302DL_FILTEREDDATASELECTION_OUTPUTREGISTER | \
132 LIS302DL_HIGHPASSFILTER_LEVEL_3 | \
133 LIS302DL_HIGHPASSFILTERINTERRUPT_1_2);
134 /* Configure MEMS high pass filter cut-off level, interrupt and data selection bits */
135 ctrl |= (uint8_t)(LIS302DL_FilterConfigStruct->HighPassFilter_Data_Selection | \
136 LIS302DL_FilterConfigStruct->HighPassFilter_CutOff_Frequency | \
137 LIS302DL_FilterConfigStruct->HighPassFilter_Interrupt);
139 /* Write value to MEMS CTRL_REG2 register */
140 LIS302DL_Write(&ctrl, LIS302DL_CTRL_REG2_ADDR, 1);
144 * @brief Set LIS302DL Interrupt configuration
145 * @param LIS302DL_InterruptConfig_TypeDef: pointer to a LIS302DL_InterruptConfig_TypeDef
146 * structure that contains the configuration setting for the LIS302DL Interrupt.
149 void LIS302DL_InterruptConfig(LIS302DL_InterruptConfigTypeDef *LIS302DL_IntConfigStruct)
153 /* Read CLICK_CFG register */
154 LIS302DL_Read(&ctrl, LIS302DL_CLICK_CFG_REG_ADDR, 1);
156 /* Configure latch Interrupt request, click interrupts and double click interrupts */
157 ctrl = (uint8_t)(LIS302DL_IntConfigStruct->Latch_Request| \
158 LIS302DL_IntConfigStruct->SingleClick_Axes | \
159 LIS302DL_IntConfigStruct->DoubleClick_Axes);
161 /* Write value to MEMS CLICK_CFG register */
162 LIS302DL_Write(&ctrl, LIS302DL_CLICK_CFG_REG_ADDR, 1);
166 * @brief Change the lowpower mode for LIS302DL
167 * @param LowPowerMode: new state for the lowpower mode.
168 * This parameter can be one of the following values:
169 * @arg LIS302DL_LOWPOWERMODE_POWERDOWN: Power down mode
170 * @arg LIS302DL_LOWPOWERMODE_ACTIVE: Active mode
173 void LIS302DL_LowpowerCmd(uint8_t LowPowerMode)
177 /* Read CTRL_REG1 register */
178 LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
180 /* Set new low power mode configuration */
181 tmpreg &= (uint8_t)~LIS302DL_LOWPOWERMODE_ACTIVE;
182 tmpreg |= LowPowerMode;
184 /* Write value to MEMS CTRL_REG1 regsister */
185 LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
189 * @brief Data Rate command
190 * @param DataRateValue: Data rate value
191 * This parameter can be one of the following values:
192 * @arg LIS302DL_DATARATE_100: 100 Hz output data rate
193 * @arg LIS302DL_DATARATE_400: 400 Hz output data rate
196 void LIS302DL_DataRateCmd(uint8_t DataRateValue)
200 /* Read CTRL_REG1 register */
201 LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
203 /* Set new Data rate configuration */
204 tmpreg &= (uint8_t)~LIS302DL_DATARATE_400;
205 tmpreg |= DataRateValue;
207 /* Write value to MEMS CTRL_REG1 regsister */
208 LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
212 * @brief Change the Full Scale of LIS302DL
213 * @param FS_value: new full scale value.
214 * This parameter can be one of the following values:
215 * @arg LIS302DL_FULLSCALE_2_3: +-2.3g
216 * @arg LIS302DL_FULLSCALE_9_2: +-9.2g
219 void LIS302DL_FullScaleCmd(uint8_t FS_value)
223 /* Read CTRL_REG1 register */
224 LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
226 /* Set new full scale configuration */
227 tmpreg &= (uint8_t)~LIS302DL_FULLSCALE_9_2;
230 /* Write value to MEMS CTRL_REG1 regsister */
231 LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
235 * @brief Reboot memory content of LIS302DL
239 void LIS302DL_RebootCmd(void)
242 /* Read CTRL_REG2 register */
243 LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG2_ADDR, 1);
245 /* Enable or Disable the reboot memory */
246 tmpreg |= LIS302DL_BOOT_REBOOTMEMORY;
248 /* Write value to MEMS CTRL_REG2 regsister */
249 LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG2_ADDR, 1);
253 * @brief Writes one byte to the LIS302DL.
254 * @param pBuffer : pointer to the buffer containing the data to be written to the LIS302DL.
255 * @param WriteAddr : LIS302DL's internal address to write to.
256 * @param NumByteToWrite: Number of bytes to write.
259 void LIS302DL_Write(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite)
261 /* Configure the MS bit:
262 - When 0, the address will remain unchanged in multiple read/write commands.
263 - When 1, the address will be auto incremented in multiple read/write commands.
265 if(NumByteToWrite > 0x01)
267 WriteAddr |= (uint8_t)MULTIPLEBYTE_CMD;
269 /* Set chip select Low at the start of the transmission */
272 /* Send the Address of the indexed register */
273 LIS302DL_SendByte(WriteAddr);
274 /* Send the data that will be written into the device (MSB First) */
275 while(NumByteToWrite >= 0x01)
277 LIS302DL_SendByte(*pBuffer);
282 /* Set chip select High at the end of the transmission */
287 * @brief Reads a block of data from the LIS302DL.
288 * @param pBuffer : pointer to the buffer that receives the data read from the LIS302DL.
289 * @param ReadAddr : LIS302DL's internal address to read from.
290 * @param NumByteToRead : number of bytes to read from the LIS302DL.
293 void LIS302DL_Read(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead)
295 if(NumByteToRead > 0x01)
297 ReadAddr |= (uint8_t)(READWRITE_CMD | MULTIPLEBYTE_CMD);
301 ReadAddr |= (uint8_t)READWRITE_CMD;
303 /* Set chip select Low at the start of the transmission */
306 /* Send the Address of the indexed register */
307 LIS302DL_SendByte(ReadAddr);
309 /* Receive the data that will be read from the device (MSB First) */
310 while(NumByteToRead > 0x00)
312 /* Send dummy byte (0x00) to generate the SPI clock to LIS302DL (Slave device) */
313 *pBuffer = LIS302DL_SendByte(DUMMY_BYTE);
318 /* Set chip select High at the end of the transmission */
323 * @brief Read LIS302DL output register, and calculate the acceleration
324 * ACC[mg]=SENSITIVITY* (out_h*256+out_l)/16 (12 bit rappresentation)
325 * @param s16 buffer to store data
328 void LIS302DL_ReadACC(int32_t* out)
331 uint8_t crtl, i = 0x00;
333 LIS302DL_Read(&crtl, LIS302DL_CTRL_REG1_ADDR, 1);
334 LIS302DL_Read(buffer, LIS302DL_OUT_X_ADDR, 6);
338 /* FS bit = 0 ==> Sensitivity typical value = 18milligals/digit*/
340 for(i=0; i<0x03; i++)
342 *out =(int32_t)(LIS302DL_SENSITIVITY_2_3G * (int8_t)buffer[2*i]);
346 /* FS bit = 1 ==> Sensitivity typical value = 72milligals/digit*/
348 for(i=0; i<0x03; i++)
350 *out =(int32_t)(LIS302DL_SENSITIVITY_9_2G * (int8_t)buffer[2*i]);
360 * @brief Initializes the low level interface used to drive the LIS302DL
364 static void LIS302DL_LowLevel_Init(void)
366 GPIO_InitTypeDef GPIO_InitStructure;
367 SPI_InitTypeDef SPI_InitStructure;
369 /* Enable the SPI periph */
370 RCC_APB2PeriphClockCmd(LIS302DL_SPI_CLK, ENABLE);
372 /* Enable SCK, MOSI and MISO GPIO clocks */
373 RCC_AHB1PeriphClockCmd(LIS302DL_SPI_SCK_GPIO_CLK | LIS302DL_SPI_MISO_GPIO_CLK | LIS302DL_SPI_MOSI_GPIO_CLK, ENABLE);
375 /* Enable CS GPIO clock */
376 RCC_AHB1PeriphClockCmd(LIS302DL_SPI_CS_GPIO_CLK, ENABLE);
378 /* Enable INT1 GPIO clock */
379 RCC_AHB1PeriphClockCmd(LIS302DL_SPI_INT1_GPIO_CLK, ENABLE);
381 /* Enable INT2 GPIO clock */
382 RCC_AHB1PeriphClockCmd(LIS302DL_SPI_INT2_GPIO_CLK, ENABLE);
384 GPIO_PinAFConfig(LIS302DL_SPI_SCK_GPIO_PORT, LIS302DL_SPI_SCK_SOURCE, LIS302DL_SPI_SCK_AF);
385 GPIO_PinAFConfig(LIS302DL_SPI_MISO_GPIO_PORT, LIS302DL_SPI_MISO_SOURCE, LIS302DL_SPI_MISO_AF);
386 GPIO_PinAFConfig(LIS302DL_SPI_MOSI_GPIO_PORT, LIS302DL_SPI_MOSI_SOURCE, LIS302DL_SPI_MOSI_AF);
388 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
389 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
390 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
391 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
393 /* SPI SCK pin configuration */
394 GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_SCK_PIN;
395 GPIO_Init(LIS302DL_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
397 /* SPI MOSI pin configuration */
398 GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_MOSI_PIN;
399 GPIO_Init(LIS302DL_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
401 /* SPI MISO pin configuration */
402 GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_MISO_PIN;
403 GPIO_Init(LIS302DL_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
405 /* SPI configuration -------------------------------------------------------*/
406 SPI_I2S_DeInit(LIS302DL_SPI);
407 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
408 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
409 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
410 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
411 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
412 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
413 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
414 SPI_InitStructure.SPI_CRCPolynomial = 7;
415 SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
416 SPI_Init(LIS302DL_SPI, &SPI_InitStructure);
419 SPI_Cmd(LIS302DL_SPI, ENABLE);
421 /* Configure GPIO PIN for Lis Chip select */
422 GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_CS_PIN;
423 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
424 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
425 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
426 GPIO_Init(LIS302DL_SPI_CS_GPIO_PORT, &GPIO_InitStructure);
428 /* Deselect : Chip Select high */
429 GPIO_SetBits(LIS302DL_SPI_CS_GPIO_PORT, LIS302DL_SPI_CS_PIN);
431 /* Configure GPIO PINs to detect Interrupts */
432 GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_INT1_PIN;
433 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
434 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
435 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
436 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
437 GPIO_Init(LIS302DL_SPI_INT1_GPIO_PORT, &GPIO_InitStructure);
439 GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_INT2_PIN;
440 GPIO_Init(LIS302DL_SPI_INT2_GPIO_PORT, &GPIO_InitStructure);
444 * @brief Sends a Byte through the SPI interface and return the Byte received
446 * @param Byte : Byte send.
447 * @retval The received byte value
449 static uint8_t LIS302DL_SendByte(uint8_t byte)
451 /* Loop while DR register in not emplty */
452 LIS302DLTimeout = LIS302DL_FLAG_TIMEOUT;
453 while (SPI_I2S_GetFlagStatus(LIS302DL_SPI, SPI_I2S_FLAG_TXE) == RESET)
455 if((LIS302DLTimeout--) == 0) return LIS302DL_TIMEOUT_UserCallback();
458 /* Send a Byte through the SPI peripheral */
459 SPI_I2S_SendData(LIS302DL_SPI, byte);
461 /* Wait to receive a Byte */
462 LIS302DLTimeout = LIS302DL_FLAG_TIMEOUT;
463 while (SPI_I2S_GetFlagStatus(LIS302DL_SPI, SPI_I2S_FLAG_RXNE) == RESET)
465 if((LIS302DLTimeout--) == 0) return LIS302DL_TIMEOUT_UserCallback();
468 /* Return the Byte read from the SPI bus */
469 return (uint8_t)SPI_I2S_ReceiveData(LIS302DL_SPI);
472 #ifdef USE_DEFAULT_TIMEOUT_CALLBACK
474 * @brief Basic management of the timeout situation.
478 uint32_t LIS302DL_TIMEOUT_UserCallback(void)
480 /* Block communication and all processes */
485 #endif /* USE_DEFAULT_TIMEOUT_CALLBACK */
504 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/