📄 mems.c
字号:
/********************* (C) COPYRIGHT 2007 RAISONANCE S.A.S. *******************/
/**
*
* @file mems.c
* @brief Mems Initialization and management
* @author FL
* @date 07/2007
* @version 1.1
* @date 10/2007
* @version 1.5 various corrections reported by Ron Miller
*
**/
/******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "circle.h"
/// @cond Internal
/* Private define ------------------------------------------------------------*/
#define RDOUTXL 0xE8 /*!< Multiple Read from OUTXL */
#define WRCTRL_REG1 0x20 /*!< Single Write CTRL_REG */
#define RDCTRL_REG1 0xA0 /*!< Single Read CTRL_REG */
#define RDID 0x8F /*!< Single Read WHO_AM_I */
#define LOW 0x00 /*!< ChipSelect line low */
#define HIGH 0x01 /*!< ChipSelect line high */
#define DUMMY_BYTE 0xA5
#define MEMS_DIVIDER 1
#define MEMS_TESTING_DIVIDER 101
#define MARGIN 500
#define DELAY_REACT 20
#define MIN_REACT 15
#define DIV_REACT 10
#define GRAD_SHOCK 200000
/* Private variables ---------------------------------------------------------*/
tMEMS_Info MEMS_Info = {0}; // structure definition in circle.h
int TestingActive = 0;
int StartingFromResetOrShockCounter = 1000;
int TimeCounterForDoubleClick = 0;
int TimeLastShock = 0;
static int divider = 0;
static Rotate_H12_V_Match_TypeDef previous_Screen_Orientation;
u32 Gradient2;
//Filtering
unsigned N_filtering = 0;
//Gradient
s16 GradX = 0;
s16 GradY = 0;
s16 GradZ = 0;
// Pointer move:
// each coordinate (X, Y and Z) is described by 3 variables where suffix means:
// f = flag to indicate that a move has been done. Cleared by the Ptr Manager when acknowledged.
// i = amplitude of the move (Grad / 10)
// t = delay to accept the counter reaction
int fMovePtrX;
int iMovePtrX;
int tMovePtrX;
int fMovePtrY;
int iMovePtrY;
int tMovePtrY;
int fMovePtrZ;
int iMovePtrZ;
int tMovePtrZ;
s16 XInit = 0;
s16 YInit = 0;
s16 ZInit = 0;
/* Private function prototypes -----------------------------------------------*/
static void MEMS_ChipSelect( u8 State );
static u8 MEMS_SendByte( u8 byte );
static void MEMS_WriteEnable( void );
static u32 MEMS_ReadOutXY( void );
static void MEMS_WakeUp( void );
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
*
* MEMS_WakeUp
*
*******************************************************************************/
/**
* Wake Up Mems.
*
**/
/******************************************************************************/
static void MEMS_WakeUp( void )
{
u8 reg_val;
/* read RDCTRL_REG1 */
/* Chip Select low */
MEMS_ChipSelect( LOW );
/* Send "RDCTRL_REG1" instruction */
MEMS_SendByte( RDCTRL_REG1 );
reg_val = MEMS_SendByte( DUMMY_BYTE );
/* Chip Select high */
MEMS_ChipSelect( HIGH );
/* SET P0:P1 to '11' */
/* 0xC0 to wake up and 0x30 for full speed frequency (640 Hz). */
reg_val = reg_val | 0xC0 | 0x30;
/* Chip Select low */
MEMS_ChipSelect( LOW );
/* Send "WRCTRL_REG1" instruction */
MEMS_SendByte( WRCTRL_REG1 );
MEMS_SendByte( reg_val );
/* Chip Select high */
MEMS_ChipSelect( HIGH );
}
/*******************************************************************************
*
* MEMS_ReadOutXY
*
*******************************************************************************/
/**
* Reads X and Y Out.
*
* @return An unsigned 32 bit word with the highest 16 bits containing the Y
* and the lowest 16 bits the X.
*
**/
/******************************************************************************/
static u32 MEMS_ReadOutXY( void )
{
u8 OutXL;
u8 OutXH;
u8 OutYL;
u8 OutYH;
u8 OutZL;
u8 OutZH;
/* Chip Select low */
MEMS_ChipSelect( LOW );
/* Send "RDOUTXL" instruction */
MEMS_SendByte( RDOUTXL );
/* Read a byte */
OutXL = MEMS_SendByte( DUMMY_BYTE );
/* Read a byte */
OutXH = MEMS_SendByte( DUMMY_BYTE );
/* Read a byte */
OutYL = MEMS_SendByte( DUMMY_BYTE );
/* Read a byte */
OutYH = MEMS_SendByte( DUMMY_BYTE );
/* Read a byte */
OutZL = MEMS_SendByte( DUMMY_BYTE );
/* Read a byte */
OutZH = MEMS_SendByte( DUMMY_BYTE );
MEMS_Info.OutX = OutXL + ( OutXH << 8 );
MEMS_Info.OutY = OutYL + ( OutYH << 8 );
MEMS_Info.OutZ = OutZL + ( OutZH << 8 );
/* Chip Select high */
MEMS_ChipSelect( HIGH );
MEMS_Info.OutX_F4 += ( MEMS_Info.OutX - ( MEMS_Info.OutX_F4 >> 2 ) ); // Filter on 4 values.
MEMS_Info.OutY_F4 += ( MEMS_Info.OutY - ( MEMS_Info.OutY_F4 >> 2 ) ); // Filter on 4 values.
MEMS_Info.OutZ_F4 += ( MEMS_Info.OutZ - ( MEMS_Info.OutZ_F4 >> 2 ) ); // Filter on 4 values.
MEMS_Info.OutX_F16 += ( MEMS_Info.OutX - ( MEMS_Info.OutX_F16 >> 4 ) ); // Filter on 16 values.
MEMS_Info.OutY_F16 += ( MEMS_Info.OutY - ( MEMS_Info.OutY_F16 >> 4 ) ); // Filter on 16 values.
MEMS_Info.OutZ_F16 += ( MEMS_Info.OutZ - ( MEMS_Info.OutZ_F16 >> 4 ) ); // Filter on 16 values.
MEMS_Info.OutX_F64 += ( MEMS_Info.OutX - ( MEMS_Info.OutX_F64 >> 6 ) ); // Filter on 64 values.
MEMS_Info.OutY_F64 += ( MEMS_Info.OutY - ( MEMS_Info.OutY_F64 >> 6 ) ); // Filter on 64 values.
MEMS_Info.OutZ_F64 += ( MEMS_Info.OutZ - ( MEMS_Info.OutZ_F64 >> 6 ) ); // Filter on 64 values.
MEMS_Info.OutX_F256 += ( MEMS_Info.OutX - ( MEMS_Info.OutX_F256 >> 8) ); // Filter on 256 values.
MEMS_Info.OutY_F256 += ( MEMS_Info.OutY - ( MEMS_Info.OutY_F256 >> 8) ); // Filter on 256 values.
MEMS_Info.OutZ_F256 += ( MEMS_Info.OutZ - ( MEMS_Info.OutZ_F256 >> 8) ); // Filter on 256 values.
if( N_filtering < 256 )
{
// Just to validate the calculated average values.
N_filtering++;
}
return ( MEMS_Info.OutX + ( MEMS_Info.OutY << 16 ) );
}
/*******************************************************************************
*
* MEMS_ChipSelect
*
*******************************************************************************/
/**
* Selects or deselects the MEMS device.
*
* @param[in] State Level to be applied on ChipSelect pin.
*
**/
/******************************************************************************/
static void MEMS_ChipSelect( u8 State )
{
/* Set High or low the chip select line on PA.4 pin */
GPIO_WriteBit( GPIOD, GPIO_Pin_2, (BitAction)State );
}
/*******************************************************************************
*
* MEMS_SendByte
*
*******************************************************************************/
/**
* Sends a byte through the SPI interface and return the byte received from
* the SPI bus.
*
* @param[in] byte The byte to send to the SPI interface.
*
* @return The byte returned by the SPI bus.
*
**/
/******************************************************************************/
static u8 MEMS_SendByte( u8 byte )
{
/* Loop while DR register in not emplty */
while( SPI_GetFlagStatus( SPI2, SPI_FLAG_TXE ) == RESET );
/* Send byte through the SPI2 peripheral */
SPI_SendData( SPI2, byte );
/* Wait to receive a byte */
while( SPI_GetFlagStatus( SPI2, SPI_FLAG_RXNE ) == RESET );
/* Return the byte read from the SPI bus */
return SPI_ReceiveData( SPI2 );
}
/* Public functions for CircleOS ---------------------------------------------*/
/*******************************************************************************
*
* MEMS_Init
*
*******************************************************************************/
/**
*
* Initializes the peripherals used by the SPI MEMS driver.
*
* @attention This function must <b>NOT</b> be called by the user.
*
**/
/******************************************************************************/
void MEMS_Init(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure PC6 and PC7 as Output push-pull For MEMS*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init( GPIOC, &GPIO_InitStructure );
/* Enable SPI2 and GPIOA clocks */
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD, ENABLE );
/* Configure SPI2 pins: SCK, MISO and MOSI */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init( GPIOB, &GPIO_InitStructure );
/* Configure PD2 as Output push-pull, used as MEMS Chip select */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init( GPIOD, &GPIO_InitStructure );
/* SPI2 configuration */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -