STM32采集3轴加速度传感器信息

  • LIS302DL三轴加速度传感器

  LIS302DL是意法半导体公司生产的一款三轴加速度传感器,内置数字电路可输出±2g/± 8g的加速度测量值,输出接口采用工业标准的I2C/SPI串行接口,并能以100Hz或400Hz的频率输出加速度信息。使用LIS302DL加速度计,可以实现自由落体检测、振动监测与补偿、步行检测等一系列涉及运动状态变化的应用。

  LIS302DL与STM32接线原理图如下图所示,SDI(MOSI)、SDO(MISO)、SPC(SCK)连接到STM32的SPI1上,CS作为片选信号连到PE3引脚。传感器还有两个可编程中断源INT1和INT2,可以在某轴的加速度超过设定阈值或是检测到自由落体事件时产生中断信号,分别将其连接到单片机PE0、PE1引脚。

  其内部功能结构如下图所示:

  使用STM32F407微控制器通过SPI接口读/写LIS302DL的寄存器,我们可以获得加速度信息或者是配置加速度计的参数。根据寄存器地址表,我们最关注的XYZ轴加速度信息分别位于地址为0x29、0x2B、0x2D的寄存器中,每个寄存器中存放8位加速度信息。这里需要注意的是OutX、OutY、OutZ寄存器的地址不连续,中间有不用的寄存器。编程一次读取多字节时要注意跳过。

  在读取加速度信息之前需要先对传感器进行配置,比如量程、传输速率、工作模式等。来看第一个相关的寄存器CTRL_REG1,其中DR位设置输出速率,默认频率为100Hz;FS位设置传感器量程,默认为0(±2g);Xen、Yen、Zen分别为XYZ轴加速度采集使能,默认全部使能;PD位控制功耗模式,PD设为1时为正常模式,PD为0时进入省电/低功耗模式(上电启动后默认进入省电模式);STP、STM设置开机自检。

  对LIS302DL进行初始化时涉及到的寄存器就是CTRL_REG1,初始功能化代码如下:

/* LIS302DL struct */
typedef struct
{
  uint8_t Power_Mode;                         /* Power-down/Active Mode */
  uint8_t Output_DataRate;                    /* OUT data rate 100 Hz / 400 Hz */
  uint8_t Axes_Enable;                        /* Axes enable */
  uint8_t Full_Scale;                         /* Full scale */
  uint8_t Self_Test;                          /* Self test */
}LIS302DL_InitTypeDef;

/**
  * @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  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);
  /*---------------------------------------------------------------------------*/
  /* 复用PA5,PA6,PA7为SPI1引脚 */    
  GPIO_PinAFConfig(GPIOA, LIS302DL_SPI_SCK_SOURCE, LIS302DL_SPI_SCK_AF);
  GPIO_PinAFConfig(GPIOA, LIS302DL_SPI_MISO_SOURCE, LIS302DL_SPI_MISO_AF);
  GPIO_PinAFConfig(GPIOA, 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;

  /* SCK MOSI MISO pin configuration */
  GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_SCK_PIN|LIS302DL_SPI_MOSI_PIN|LIS302DL_SPI_MISO_PIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
    
  /*---------------------------------------------------------------------------*/
  /* SPI configuration */
  SPI_I2S_DeInit(LIS302DL_SPI);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全双工模式
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8位传输
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;  //设置时钟极性,时钟空闲时为高电平,选择SPI_CPOL_High
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//设置时钟相位,在时钟的第二个跳变沿采样,选择SPI_CPHA_2Edge
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //设置NSS信号是由硬件还是软件控制
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;//设置SPI波特率为64分频,传输速度为84M/64=1.3Mhz
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//设置数据传输顺序是MSB位在前还是LSB位在前
  SPI_InitStructure.SPI_CRCPolynomial = 7; //设置CRC校验多项式,提高通信可靠性,该值大于1即可
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI主从模式,这里设为主机模式SPI_Mode_Master
  SPI_Init(SPI1, &SPI_InitStructure); //根据指定的参数初始化外设SPI1寄存器

  /* Enable SPI1  */
  SPI_Cmd(SPI1, 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_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(GPIOE, &GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_INT1_PIN | LIS302DL_SPI_INT2_PIN;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
}
View Code

  状态寄存器STATUS_REG中包含了,传感器的许多状态信息。其中ZXYOR位代表XYZ轴是否有数据被覆盖,0表示没有被覆盖,1表示新数据覆盖了之前的数据(在这个数据被读取之前);ZOR、YOR、XOR分别代表各轴数据是否被覆盖;ZYXDA表示XYZ是否有有效的新的数据,1表示新数据有效,0表示没有有效新数据;ZDA、YDA、XDA分别代表各轴。

  控制寄存器2中的内容如下图所示:

SIM位确定SPI接口模式。0:4-wire interface;1:3-wire interface,默认为0,即四线传输(CS、SCK、MOSI、MISO)。

BOOT位用于控制是否将flash中保存的出厂值刷新相关的内部寄存器。0:normal mode,1:rebbot memory content,默认为0。

FDS位控制是否使能高通滤波器。0:internal filter bypassed,1:data from internal filter sent to output register,默认为0,即不使用高通滤波器;高通滤波是只对低于某一给定频率以下的频率成分有衰减作用,而允许这个截频以上的频率成分通过,主要用来消除低频噪声。

HP_FF_WU2: High Pass filter enabled for FreeFall/WakeUp # 2. Default value: 0 (0: filter bypassed; 1: filter enabled)

HP_FF_WU1: High Pass filter enabled for FreeFall/WakeUp # 1. Default value: 0 (0: filter bypassed; 1: filter enabled)

HP_coeff2和HP_coeff1用于确定高通滤波的截止频率,具体配置见下表:

  关于这里高通滤波器的作用描述如下:跌落保护对于配置了硬盘的便携式设备来说很重要,该功能在高档笔记本电脑中的应用已经非常普遍,三轴加速度传感器LIS302DL能通过对加速度阈值寄存器进行设置来实现跌落保护功能。物体如果处于静止状态,平放在桌子上的(没有加速度),加速度计会读到g = 9.81 m/s2;如果设备做自由落体运动以9.81 m/s2的加速度坠向地面时,加速度计理论上会读到g = 0 m/s2,不过由于空气阻力和下落旋转时产生的离心力,加速度计度数应该是一个比较小的数值。因此,要测出设备真实的加速度,必须排除加速计数据中的重力干扰。这可以通过高通滤波器来实现,LIS302DL中集成了高通滤波器,能够滤除缓慢变化或不变的加速度(如重力加速度),并且可以选择截止频率,只有变化高于截止频率的加速度才能通过。

  与控制寄存器2相关的代码如下:

// SPI_Serial_Interface_Mode_selection 
#define LIS302DL_SERIALINTERFACE_4WIRE                    ((uint8_t)0x00)
#define LIS302DL_SERIALINTERFACE_3WIRE                    ((uint8_t)0x80)

// Boot_Mode_selection 
#define LIS302DL_BOOT_NORMALMODE                          ((uint8_t)0x00)
#define LIS302DL_BOOT_REBOOTMEMORY                        ((uint8_t)0x40)

// Filtered_Data_Selection_Mode_selection 
#define LIS302DL_FILTEREDDATASELECTION_BYPASSED           ((uint8_t)0x00)
#define LIS302DL_FILTEREDDATASELECTION_OUTPUTREGISTER     ((uint8_t)0x10)

// High_Pass_Filter_Interrupt_selection 
#define LIS302DL_HIGHPASSFILTERINTERRUPT_OFF              ((uint8_t)0x00)
#define LIS302DL_HIGHPASSFILTERINTERRUPT_1                ((uint8_t)0x04)
#define LIS302DL_HIGHPASSFILTERINTERRUPT_2                ((uint8_t)0x08)
#define LIS302DL_HIGHPASSFILTERINTERRUPT_1_2              ((uint8_t)0x0C)

// High_Pass_Filter_selection 
#define LIS302DL_HIGHPASSFILTER_LEVEL_0                   ((uint8_t)0x00)
#define LIS302DL_HIGHPASSFILTER_LEVEL_1                   ((uint8_t)0x01)
#define LIS302DL_HIGHPASSFILTER_LEVEL_2                   ((uint8_t)0x02)
#define LIS302DL_HIGHPASSFILTER_LEVEL_3                   ((uint8_t)0x03)


/* LIS302DL High Pass Filter struct */
typedef struct
{
  uint8_t HighPassFilter_Data_Selection;      /* Internal filter bypassed or data from internal filter send to output register*/
  uint8_t HighPassFilter_CutOff_Frequency;    /* High pass filter cut-off frequency */
  uint8_t HighPassFilter_Interrupt;           /* High pass filter enabled for Freefall/WakeUp #1 or #2 */ 
}LIS302DL_FilterConfigTypeDef;  


/**
  * @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  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);
}
View Code

  控制寄存器3中的内容如下图所示:

  I2CFG[2:0] and I1CFG[2:0] bit select which signal has to be sent out from the INT2 and INT1 interrupt pads as described in the following table:

  LIS320DL可以配置两路相互独立的中断INT1和INT2,用于检测事件的发生。

  • SPI通信

  SPI是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口,它是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,STM32F4也SPI接口。SPI是一个环形总线结构,其时序其实很简单,主要是在时钟信号的控制下,两个双向移位寄存器进行数据交换。

  LIS302DL是SPI总线上的从设备,可以通过SPI接口读写其内部寄存器。LIS302DL的SPI接口通过CS,SPC,SDI和SDO这四根线与外部通信。CS决定了唯一的与主设备通信的从设备,如没有CS 信号,则只能存在一个从设备,主设备通过产生移位时钟来发起通讯。通讯时,数据由SDO 输出,SDI 输入,数据在时钟的上升或下降沿由SDO输出,在紧接着的下降或上升沿由SDI 读入。一个完整的传送周期是16位,即两个字节,因为,首先主机要发送命令过去,然后从机根据主机的命令准备数据,主机在下一个8位时钟周期才把数据读回来。LIS302DL的SPI时钟频率最大为10MHz。

  CS is the Serial Port Enable and it is controlled by the SPI master. It goes low at the start of  the transmission and goes back high at the end. SPC is the Serial Port Clock and it is  controlled by the SPI master. It is stopped high when CS is high (no transmission). SDI and SDO are respectively the Serial Port Data Input and Output. Those lines are driven at the falling edge of SPC and should be captured at the rising edge of SPC.

bit 0: RW bit. When 0, the data DI(7:0) is written into the device. When 1, the data DO(7:0) from the device is read.

bit 1: 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.

bit 2 -7 : address AD(5:0). This is the address field of the indexed register.

bit 8-15: data DI(7:0) (write mode). This is the data that will be written into the device (MSb first).

bit 8-15: data DO(7:0) (read mode). This is the data that will be read from the device (MSb first).

  主机和从机都有一个串行移位寄存器,主机通过向它的 SPI 串行寄存器写入一个字节来发起一次传输。寄存器通过 MOSI 信号线将字节传送给从机,从机也将自己的移位寄存器中的内容通过 MISO 信号线返回给主机。这样,两个移位寄存器中的内容就被交换。外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。

  读/写LIS302DL中的一个或多个寄存器的代码如下(这里面用到了STM32F407的标准外设库,因此工程中需要包含stm32f4xx_spi.c和stm32f4xx_spi.h文件)

/* 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)

/**
  * @brief  Writes bytes 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  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 */
View Code
  • Application Information

  ①  Start-up sequence
  Once the device is powered-up it automatically downloads the calibration coefficients from the embedded flash to the internal registers. When the boot procedure is completed, i.e. approximately after 3 milliseconds, the device automatically enters power-down mode. To turn-on the device and gather acceleration data it is necessary to write 47h inside the CTRL_REG1. With this command the three acceleration channels (i.e. X, Y and Z axis) are enabled and the Output Data Rate is set to 100 Hz.

  ②  Read acceleration data
  The device is provided with a STATUS_REG which should be polled to check when a new set of data is available. The reading procedure should be the following:

  The check performed at step 3 allows to understand whether the reading rate is adequate compared to the data production rate. In case one or more acceleration samples have been overwritten by new data because of a reading rate too slow, the bit STATUS_REG(7) will be set to 1. The overrun bit are automatically cleared when all the data present inside the device have been read and new data have not been produced in the meanwhile.

  ③  Understanding acceleration data

  OUTX、OUTY、OUTZ中的加速度信息由8位补码表示,只有7位能表示数值大小,最高位为符号位。查看Datasheet中Mechanical characteristics可知量程选择位FS=0时,灵敏度(最小分辨率)为18mg(2.3 * 1000 / 127 ≈ 18);FS=1时,灵敏度为72mg。

  则根据原始读数计算加速度的公式为:Acc[mg] = sensitivity * raw_data

  如果FS=0,原始数据为0x38,则其代表的加速度为 56*18≈1000mg;原始数据为0xC8时,其十进制数字为-56,则代表的加速度为-56*18≈-1000mg。(正数(符号位为0的数)补码与原码相同;负数(符号位为1的数)补码变原码时,符号位不变,其余各位取反,最低位加1

   读取加速度信息的代码如下:

#define LIS302DL_SENSITIVITY_2_3G                         18  /* 18 mg/digit*/
#define LIS302DL_SENSITIVITY_9_2G                         72  /* 72 mg/digit*/

/**
  * @brief  Read LIS302DL output register, and calculate the acceleration 
  * @param  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;
    }
 }
View Code
  • 加速度计的标定  

  当加速度计水平放置时,理论上Z轴感受到重力将读出XXXX。 同时X轴和Y轴的读数将是0。可实际并不是这样的,这是由于每个芯片在制作时都不一样,数据手册上的都是理论值(查看Datasheet中的Mechanical characteristics,Typical zero-g level offset accuracy在±2g量程时为±40mg;在±8g量程时为±60mg),真正的芯片在水平时Z轴可能并不是XXXX。我们需要找到当各个轴在0g重力时的计数,得到一个补偿值,在每次读取ADC结果后都进行补偿 。

  Zero-g level Offset describes the deviation of an actual output signal from the ideal output signal if there is no acceleration present. A sensor in a steady state on a horizontal surface will measure 0g in X axis and 0g in Y axis whereas the Z axis will measure 1g.

 



参考:

利用三轴加速器的计步测算方法

posted @ 2016-11-13 16:17  XXX已失联  阅读(442)  评论(0编辑  收藏  举报