ADXL361(微功耗三轴加速度计)使用笔记

ADXL361(微功耗三轴加速度计)使用笔记

一、硬件介绍

特性:

超低功耗
待机电流: 10nA
运动唤醒模式电流: 270nA
高分辨率: 1 mg/LSB
数字接口: SPI数字接口
供电电压: 1.6 V至3.5 V

概述

ADXL362是一款超低功耗、 3轴MEMS加速度计,输出数据速率为100 Hz时功耗低于2 μA,在运动触发唤醒模式下功耗为270 nA。与使用周期采样来实现低功耗的加速度计不同,ADXL362没有通过欠采样混叠输入信号;它采用全数据速率对传感器的整个带宽进行采样。ADXL362通常提供12位输出分辨率;在较低分辨率足够时,还提供8位数据输出以实现更高效的单字节传送。测量范围为±2 g、 ±4 g及±8 g, ±2 g范围内的分辨率为1 mg/LSB。噪声电平要求低于ADXL362正常值550 μg/√Hz的应用可以选择两个低噪声模式(典型值低至175 μg/√Hz)之一,电源电流增加极小。除了超低功耗以外, ADXL362还具有许多特性来实现真正的系统级节能。该器件包含了一个深度多模式输出FIFO、一个内置微功耗温度传感器和几个运动检测模式,其中包括阙值可调的睡眠和唤醒工作模式,在该模式下当测量速率为6 HZ左右时功耗低至270 nA。如有需要,可在检测到运动时提供一个引脚输出来直接控制外部开关。此外,ADXL362还支持对采样时间和/或系统时钟进行外部控制。ADXL362可以在1.6V至3.5V的宽电源电压范围内工作,并且必要时可以与采用独立低电源电压工作的主机接口。

引脚配置和功能描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9RmMTJ8R-1584185336838)(https://raw.githubusercontent.com/WuliYongShun/PictureHouse/master/img/20200313173608.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t1V7HjV7-1584185336840)(https://raw.githubusercontent.com/WuliYongShun/PictureHouse/master/img/20200313173627.png)]

二、驱动程序

驱动程序调试成功,正常通讯,使用STM32单片机(Hal库)形式对传感器进行控制操作及读取数据,源码如下(程序原理ADI官方代码,修改其中读写程序即可),经过测试驱动程序正常使用。

1、头文件

/**
  ******************************************************************************
  *               Copyright(C) 2016-2026 GDKY All Rights Reserved
  *
  * @file     ADXL362Driver.c
  * @author   YSHUN
  * @version  V1.00
  * @date     2020.02.05
  * @brief    硬件层驱动处理程序.
  ******************************************************************************
  */

#ifndef __ADXL362_H__
#define __ADXL362_H__

/* INCLUDES ------------------------------------------------------------------- */
#include "stm32l0xx_hal.h"
#include "gpio.h"
#include "spi.h"


#ifdef __cplusplus
extern "C" {
#endif
	
/* TYPEDEFS ------------------------------------------------------------------- */
#define ADXL362_CS_Pin GPIO_PIN_1
#define ADXL362_CS_GPIO_Port GPIOB
	
#define Clr_Cs()	HAL_GPIO_WritePin(ADXL362_CS_GPIO_Port, ADXL362_CS_Pin, GPIO_PIN_RESET)
#define Set_Cs()	HAL_GPIO_WritePin(ADXL362_CS_GPIO_Port, ADXL362_CS_Pin, GPIO_PIN_SET)

#define ADXL362_SLAVE_ID    1

/* ADXL362 communication commands */
#define ADXL362_WRITE_REG           0x0A
#define ADXL362_READ_REG            0x0B
#define ADXL362_WRITE_FIFO          0x0D

/* Registers */
#define ADXL362_REG_DEVID_AD            0x00
#define ADXL362_REG_DEVID_MST           0x01
#define ADXL362_REG_PARTID              0x02
#define ADXL362_REG_REVID               0x03
#define ADXL362_REG_XDATA               0x08	//X轴数据(8 MSB)寄存器
#define ADXL362_REG_YDATA               0x09	//Y轴数据(8 MSB)寄存器
#define ADXL362_REG_ZDATA               0x0A	//Z轴数据(8 MSB)寄存器
#define ADXL362_REG_STATUS              0x0B	//状态寄存器,用于指示ADXL362的各种状态
#define ADXL362_REG_FIFO_L              0x0C	//FIFO条目寄存器,低8位
#define ADXL362_REG_FIFO_H              0x0D	//FIFO条目寄存器,高8位
#define ADXL362_REG_XDATA_L             0x0E
#define ADXL362_REG_XDATA_H             0x0F
#define ADXL362_REG_YDATA_L             0x10
#define ADXL362_REG_YDATA_H             0x11
#define ADXL362_REG_ZDATA_L             0x12
#define ADXL362_REG_ZDATA_H             0x13
#define ADXL362_REG_TEMP_L              0x14	//温度数据寄存器
#define ADXL362_REG_TEMP_H              0x15
#define ADXL362_REG_SOFT_RESET          0x1F	//软复位寄存器
#define ADXL362_REG_THRESH_ACT_L        0x20	//运动阈值寄存器,保存8个LSB
#define ADXL362_REG_THRESH_ACT_H        0x21	//运动阈值寄存器,保存3个MSB
#define ADXL362_REG_TIME_ACT            0x22	//运动时间寄存器
#define ADXL362_REG_THRESH_INACT_L      0x23	//静止阈值寄存器,保存8个LSB
#define ADXL362_REG_THRESH_INACT_H      0x24	//静止阈值寄存器,保存3个MSB
#define ADXL362_REG_TIME_INACT_L        0x25	//静止时间寄存器,保存8个LSB
#define ADXL362_REG_TIME_INACT_H        0x26	//静止时间寄存器,保存8个MSB
#define ADXL362_REG_ACT_INACT_CTL       0x27
#define ADXL362_REG_FIFO_CTL            0x28
#define ADXL362_REG_FIFO_SAMPLES        0x29
#define ADXL362_REG_INTMAP1             0x2A	//INT1/INT2功能映射寄存器,INT1映射
#define ADXL362_REG_INTMAP2             0x2B	//INT1/INT2功能映射寄存器,INT2映射
#define ADXL362_REG_FILTER_CTL          0x2C	//滤波器控制寄存器
#define ADXL362_REG_POWER_CTL           0x2D	//电源控制寄存器
#define ADXL362_REG_SELF_TEST           0x2E	//自检寄存器

/* ADXL362_REG_STATUS definitions */
#define ADXL362_STATUS_ERR_USER_REGS        (1 << 7)
#define ADXL362_STATUS_AWAKE                (1 << 6)
#define ADXL362_STATUS_INACT                (1 << 5)
#define ADXL362_STATUS_ACT                  (1 << 4)
#define ADXL362_STATUS_FIFO_OVERRUN         (1 << 3)
#define ADXL362_STATUS_FIFO_WATERMARK       (1 << 2)
#define ADXL362_STATUS_FIFO_RDY             (1 << 1)
#define ADXL362_STATUS_DATA_RDY             (1 << 0)

/* ADXL362_REG_ACT_INACT_CTL definitions */
#define ADXL362_ACT_INACT_CTL_LINKLOOP(x)   (((x) & 0x3) << 4)
#define ADXL362_ACT_INACT_CTL_INACT_REF     (1 << 3)
#define ADXL362_ACT_INACT_CTL_INACT_EN      (1 << 2)
#define ADXL362_ACT_INACT_CTL_ACT_REF       (1 << 1)
#define ADXL362_ACT_INACT_CTL_ACT_EN        (1 << 0)

/* ADXL362_ACT_INACT_CTL_LINKLOOP(x) options */
#define ADXL362_MODE_DEFAULT        0
#define ADXL362_MODE_LINK           1
#define ADXL362_MODE_LOOP           3

/* ADXL362_REG_FIFO_CTL */
#define ADXL362_FIFO_CTL_AH                 (1 << 3)
#define ADXL362_FIFO_CTL_FIFO_TEMP          (1 << 2)
#define ADXL362_FIFO_CTL_FIFO_MODE(x)       (((x) & 0x3) << 0)

/* ADXL362_FIFO_CTL_FIFO_MODE(x) options */
#define ADXL362_FIFO_DISABLE              0
#define ADXL362_FIFO_OLDEST_SAVED         1
#define ADXL362_FIFO_STREAM               2
#define ADXL362_FIFO_TRIGGERED            3

/* ADXL362_REG_INTMAP1 */
#define ADXL362_INTMAP1_INT_LOW             (1 << 7)
#define ADXL362_INTMAP1_AWAKE               (1 << 6)
#define ADXL362_INTMAP1_INACT               (1 << 5)
#define ADXL362_INTMAP1_ACT                 (1 << 4)
#define ADXL362_INTMAP1_FIFO_OVERRUN        (1 << 3)
#define ADXL362_INTMAP1_FIFO_WATERMARK      (1 << 2)
#define ADXL362_INTMAP1_FIFO_READY          (1 << 1)
#define ADXL362_INTMAP1_DATA_READY          (1 << 0)

/* ADXL362_REG_INTMAP2 definitions */
#define ADXL362_INTMAP2_INT_LOW             (1 << 7)
#define ADXL362_INTMAP2_AWAKE               (1 << 6)
#define ADXL362_INTMAP2_INACT               (1 << 5)
#define ADXL362_INTMAP2_ACT                 (1 << 4)
#define ADXL362_INTMAP2_FIFO_OVERRUN        (1 << 3)
#define ADXL362_INTMAP2_FIFO_WATERMARK      (1 << 2)
#define ADXL362_INTMAP2_FIFO_READY          (1 << 1)
#define ADXL362_INTMAP2_DATA_READY          (1 << 0)

/* ADXL362_REG_FILTER_CTL definitions */
#define ADXL362_FILTER_CTL_RANGE(x)         (((x) & 0x3) << 6)
#define ADXL362_FILTER_CTL_RES              (1 << 5)
#define ADXL362_FILTER_CTL_HALF_BW          (1 << 4)
#define ADXL362_FILTER_CTL_EXT_SAMPLE       (1 << 3)
#define ADXL362_FILTER_CTL_ODR(x)           (((x) & 0x7) << 0)

/* ADXL362_FILTER_CTL_RANGE(x) options */
#define ADXL362_RANGE_2G                0 /* +-2 g */
#define ADXL362_RANGE_4G                1 /* +-4 g */
#define ADXL362_RANGE_8G                2 /* +-8 g */

/* ADXL362_FILTER_CTL_ODR(x) options */
#define ADXL362_ODR_12_5_HZ             0 /* 12.5 Hz */
#define ADXL362_ODR_25_HZ               1 /* 25 Hz */
#define ADXL362_ODR_50_HZ               2 /* 50 Hz */
#define ADXL362_ODR_100_HZ              3 /* 100 Hz */
#define ADXL362_ODR_200_HZ              4 /* 200 Hz */
#define ADXL362_ODR_400_HZ              5 /* 400 Hz */

/* ADXL362_REG_POWER_CTL definitions */
#define ADXL362_POWER_CTL_RES               (1 << 7)
#define ADXL362_POWER_CTL_EXT_CLK           (1 << 6)
#define ADXL362_POWER_CTL_LOW_NOISE(x)      (((x) & 0x3) << 4)
#define ADXL362_POWER_CTL_WAKEUP            (1 << 3)
#define ADXL362_POWER_CTL_AUTOSLEEP         (1 << 2)
#define ADXL362_POWER_CTL_MEASURE(x)        (((x) & 0x3) << 0)

/* ADXL362_POWER_CTL_LOW_NOISE(x) options */
#define ADXL362_NOISE_MODE_NORMAL           0
#define ADXL362_NOISE_MODE_LOW              1
#define ADXL362_NOISE_MODE_ULTRALOW         2

/* ADXL362_POWER_CTL_MEASURE(x) options */
#define ADXL362_MEASURE_STANDBY         0
#define ADXL362_MEASURE_ON              2

/* ADXL362_REG_SELF_TEST */
#define ADXL362_SELF_TEST_ST            (1 << 0)

/* ADXL362 device information */
#define ADXL362_DEVICE_AD               0xAD
#define ADXL362_DEVICE_MST              0x1D
#define ADXL362_PART_ID                 0xF2

/* ADXL362 Reset settings */
#define ADXL362_RESET_KEY               0x52


/* MACROS  -------------------------------------------------------------------- */

/* CONSTANTS  ----------------------------------------------------------------- */

/* GLOBAL VARIABLES ----------------------------------------------------------- */

/* GLOBAL FUNCTIONS ----------------------------------------------------------- */

/*! Initializes the device. */
unsigned char ADXL362_Init(void);

/*! Writes data into a register. */
void ADXL362_SetRegisterValue(unsigned char registerValue,
                              unsigned char  registerAddress,
                              unsigned char  bytesNumber);

/*! Performs a burst read of a specified number of registers. */
void ADXL362_GetRegisterValue(unsigned char *pReadData,
                              unsigned char  registerAddress,
                              unsigned char  bytesNumber);

/*! Reads multiple bytes from the device's FIFO buffer. */
void ADXL362_GetFifoValue(unsigned char *pBuffer, unsigned short bytesNumber);

/*! Resets the device via SPI communication bus. */
void ADXL362_SoftwareReset(void);

/*! Places the device into standby/measure mode. */
void ADXL362_SetPowerMode(unsigned char pwrMode);

/*! Selects the measurement range. */
void ADXL362_SetRange(unsigned char gRange);

/*! Selects the Output Data Rate of the device. */
void ADXL362_SetOutputRate(unsigned char outRate);

/*! Reads the 3-axis raw data from the accelerometer. */
void ADXL362_GetXyz(short *x, short *y, short *z);

/*! Reads the temperature of the device. */
float ADXL362_ReadTemperature(void);

/*! Configures the FIFO feature. */
void ADXL362_FifoSetup(unsigned char  mode,
                       unsigned short waterMarkLvl,
                       unsigned char  enTempRead);

/*! Configures activity detection. */
void ADXL362_SetupActivityDetection(unsigned char  refOrAbs,
                                    unsigned short threshold,
                                    unsigned char  time);

/*! Configures inactivity detection. */
void ADXL362_SetupInactivityDetection(unsigned char  refOrAbs,
                                      unsigned short threshold,
                                      unsigned short time);
																			
void ADXL362_Set(void);

/* 芯片ID读取 */																			
uint16_t	ADXL362_ReadID(void);
																			
void ADXL362_GetData(int16_t *Xdata,int16_t *Ydata,int16_t *Zdata,int16_t *Tdata);

/* 唤醒模式初始化 */
void ADXL362_WakeUpMode( void );
																			
																			
#ifdef __cplusplus
}
#endif

#endif	/* __ADXL362_H__ */

1、源码文件

/**
  ******************************************************************************
  *               Copyright(C) 2016-2026 GDKY All Rights Reserved
  *
  * @file     ADXL362Driver.c
  * @author   YSHUN
  * @version  V1.00
  * @date     2020.02.05
  * @brief    硬件层驱动处理程序.
  ******************************************************************************
  */

/* INCLUDES ------------------------------------------------------------------- */
#include "ADXL362.h"

/**
  * @brief  唤醒模式初始化
  * @retval None
  */
void ADXL362_WakeUpMode( void )
{
	/* 1、写入十进制250 (0xFA)到寄存器0x20,写入0到寄存器0x21:将运动阈值设为250 mg */
//	ADXL362_SetRegisterValue( 0xFA, 0x20, 1 );
	ADXL362_SetRegisterValue( 0x32, 0x20, 1 );
	
	
	/* 2、写入十进制150 (0x96)到寄存器0x23,写入0到寄存器0x24:将静止阈值设为150 mg */
//	ADXL362_SetRegisterValue( 0x96, 0x23, 1 );
	ADXL362_SetRegisterValue( 0x32, 0x20, 1 );
	
	/* 3、写入十进制30 (0x1E)到寄存器0x25:将静止定时器设为30个样本或约5秒 */
	ADXL362_SetRegisterValue( 0x1E, 0x25, 1 );
//	ADXL362_SetRegisterValue( 0x10, 0x25, 1 );
	
	/* 4、写入0x3F到寄存器0x27:配置环路模式的运动检测并使能相对运动和静止检测 */
	ADXL362_SetRegisterValue( 0x3F, 0x27, 1 );
	
	/* 5、写入0x40到寄存器0x2B:将AWAKE位映射到INT2。INT2引脚与开关的栅极相连 */
	ADXL362_SetRegisterValue( 0x40, 0x2B, 1 );
	
	/* 6、写入0x0A到寄存器0x2D:开始在唤醒模式下进行测量*/
	ADXL362_SetRegisterValue( 0x0A, 0x2D, 1 );
	
}	

/**
  * @brief  唤醒模式初始化
  * @retval None
  */
void ADXL632_WakeMode(void)
{
	/* 设置设备为待机模式,先进入待机模式配置将不会影响到传感器数据 */
	ADXL362_SetPowerMode(0);
	
	/* 加速计的输出数据速率设置为: 12.5 Hz. */
	ADXL362_SetOutputRate(ADXL362_ODR_12_5_HZ);
	/* 测量范围设置为4g */
	ADXL362_SetRange(ADXL362_RANGE_4G);
	
	
	/* 失能中断输出 */
	ADXL362_SetRegisterValue(ADXL362_REG_INTMAP1, 0, 1);
	ADXL362_SetRegisterValue(ADXL362_REG_INTMAP2, 0, 1);
	
	/* 运动/静止控制寄存器配置,配置为环路模式内部中断信号 */
	ADXL362_SetRegisterValue(ADXL362_ACT_INACT_CTL_LINKLOOP(ADXL362_MODE_LOOP) \
													| ADXL362_ACT_INACT_CTL_INACT_EN \
												 	| ADXL362_ACT_INACT_CTL_ACT_EN , 
													ADXL362_REG_ACT_INACT_CTL, 1);
	/* 设置运动状态阈值 */
	ADXL362_SetupActivityDetection(1, 30, 1);
	/* 设置静止状态阈值 */
	ADXL362_SetupInactivityDetection(1, 700, 25);
	
	/* FIFO缓冲区设置 */
	
	/* 输出中断使能,设置INT1为运动中断  INT2为唤醒中断*/
	ADXL362_SetRegisterValue(ADXL362_INTMAP1_ACT, ADXL362_REG_INTMAP1, 1);
	ADXL362_SetRegisterValue(ADXL362_INTMAP2_INACT, ADXL362_REG_INTMAP2, 1);
	
	/* 进入测量模式,开始测量过程 */
	ADXL362_SetPowerMode(1);
//	ADXL362_SetRegisterValue(0xC0, ADXL362_REG_POWER_CTL, 1);
}

/**
  * @brief  初始化与设备的通信,并通过读取设备id检查部件是否存在
  * @param  
  * @retval 1 成功
	*					0 失败
  */
unsigned char ADXL362_Init(void)
{
	unsigned char regValue = 0;
	unsigned char status   = 0;

	/* SPI Init */
//	MX_SPI1_Init();
	
//	ADXL362_SoftwareReset();
	
	
	
	ADXL362_GetRegisterValue(®Value, ADXL362_REG_PARTID, 1);
	if((regValue != ADXL362_PART_ID))
	{
		status = 0;
	}
	else
	{
		status = 1;
	}
	
	ADXL362_WakeUpMode( );

	return status;
}


/**
  * @brief  写数据到寄存器
  * @param  registerValue - 写数据值
  * @param  registerAddress - 寄存器地址
  * @param  bytesNumber - 字节数. Accepted values: 0 - 1
  * @retval None
  */
void ADXL362_SetRegisterValue(unsigned char registerValue,
                              unsigned char  registerAddress,
                              unsigned char  bytesNumber)
{	
		uint8_t m_reg_cmd = 0;
		m_reg_cmd = ADXL362_WRITE_REG;
		
		if(registerAddress > ADXL362_REG_SELF_TEST)
		{
			return;
		}
		
		Clr_Cs();
		HAL_SPI_Transmit(&hspi1, &m_reg_cmd, 1, 1000);
		HAL_SPI_Transmit(&hspi1, ®isterAddress, 1, 1000);
		HAL_SPI_Transmit(&hspi1, ®isterValue, bytesNumber, 1000);
		Set_Cs();
}

/**
  * @brief  读数据从寄存器
  * @param  pReadData - 读缓冲区
  * @param  registerAddress - 寄存器地址
  * @param  bytesNumber - 字节数
  * @retval None
  */
void ADXL362_GetRegisterValue(unsigned char* pReadData,
                              unsigned char  registerAddress,
                              unsigned char  bytesNumber)
{	
		uint8_t m_reg_addr = 0;
		uint8_t m_reg_cmd = 0;
		
		m_reg_addr = registerAddress;
		m_reg_cmd = ADXL362_READ_REG;
		
		if(pReadData == NULL)
		{
			return;
		}
		if(m_reg_cmd > ADXL362_REG_SELF_TEST)
		{
			return;
		}
		
		Clr_Cs();
		HAL_SPI_Transmit(&hspi1, &m_reg_cmd, 1, 1000);
		HAL_SPI_Transmit(&hspi1, &m_reg_addr, 1, 1000);
		HAL_SPI_Receive(&hspi1, pReadData, bytesNumber, 1000);
		Set_Cs();
}

/**
  * @brief  从设备的FIFO缓冲区读取多个字节
  * @param  pBuffer - 存储读取字节缓冲区
  * @param  bytesNumber - 字节数
  * @retval None
  */
void ADXL362_GetFifoValue(unsigned char* pBuffer, unsigned short bytesNumber)
{
		uint8_t m_reg_cmd = 0;
		
		m_reg_cmd = ADXL362_WRITE_FIFO;
		
		if(pBuffer == NULL)
		{
			return;
		}
		
		Clr_Cs();
		HAL_SPI_Transmit(&hspi1, &m_reg_cmd, 1, 1000);
		HAL_SPI_Receive(&hspi1, pBuffer, bytesNumber, 1000);
		Set_Cs();
}

/**
  * @brief  软复位
  * 
  * @retval None
  */
void ADXL362_SoftwareReset(void)
{
    ADXL362_SetRegisterValue(ADXL362_RESET_KEY, ADXL362_REG_SOFT_RESET, 1);
}

/**
  * @brief  芯片ID读取
  * 
  * @retval 设备ID(默认为0xAD)
  */
uint16_t ADXL362_ReadID(void)
{
	uint8_t defID = 0;
	/* 读取器件ID,默认0xAD */
	ADXL362_GetRegisterValue(&defID, ADXL362_REG_DEVID_AD, 1);
	
	return defID;
}

/**
  * @brief  将设备置于待机/测量模式
  * @param pwrMode - Power mode.
  *                  Example: 0 - standby mode.
  *		                     1 - measure mode.
  * @retval None
  */
void ADXL362_SetPowerMode(unsigned char pwrMode)
{
    unsigned char oldPowerCtl = 0;
    unsigned char newPowerCtl = 0;

    ADXL362_GetRegisterValue(&oldPowerCtl, ADXL362_REG_POWER_CTL, 1);
    newPowerCtl = oldPowerCtl & ~ADXL362_POWER_CTL_MEASURE(0x3);
    newPowerCtl = newPowerCtl |
                  (pwrMode * ADXL362_POWER_CTL_MEASURE(ADXL362_MEASURE_ON));
    ADXL362_SetRegisterValue(newPowerCtl, ADXL362_REG_POWER_CTL, 1);
}


/**
  * @brief  测量范围选择
  * @param gRange - Range option.
  *                  Example: ADXL362_RANGE_2G  -  +-2 g
  *                           ADXL362_RANGE_4G  -  +-4 g
  *                           ADXL362_RANGE_8G  -  +-8 g
  * @retval None
  */
void ADXL362_SetRange(unsigned char gRange)
{
    unsigned char oldFilterCtl = 0;
    unsigned char newFilterCtl = 0;

    ADXL362_GetRegisterValue(&oldFilterCtl, ADXL362_REG_FILTER_CTL, 1);
    newFilterCtl = oldFilterCtl & ~ADXL362_FILTER_CTL_RANGE(0x3);
    newFilterCtl = newFilterCtl | ADXL362_FILTER_CTL_RANGE(gRange);
    ADXL362_SetRegisterValue(newFilterCtl, ADXL362_REG_FILTER_CTL, 1);
}

/**
  * @brief  选择设备的输出数据速率
  * @param outRate - Output Data Rate option.
  *                  Example: ADXL362_ODR_12_5_HZ  -  12.5Hz
  *                           ADXL362_ODR_25_HZ    -  25Hz
  *                           ADXL362_ODR_50_HZ    -  50Hz
  *                           ADXL362_ODR_100_HZ   -  100Hz
  *                           ADXL362_ODR_200_HZ   -  200Hz
  *                           ADXL362_ODR_400_HZ   -  400Hz
  * @retval None
  */
void ADXL362_SetOutputRate(unsigned char outRate)
{
    unsigned char oldFilterCtl = 0;
    unsigned char newFilterCtl = 0;

    ADXL362_GetRegisterValue(&oldFilterCtl, ADXL362_REG_FILTER_CTL, 1);
    newFilterCtl = oldFilterCtl & ~ADXL362_FILTER_CTL_ODR(0x7);
    newFilterCtl = newFilterCtl | ADXL362_FILTER_CTL_ODR(outRate);
    ADXL362_SetRegisterValue(newFilterCtl, ADXL362_REG_FILTER_CTL, 1);
}

/**
  * @brief  从加速度计读取3轴原始数据
  *
  * @param x - Stores the X-axis data(as two's complement).
  * @param y - Stores the X-axis data(as two's complement).
  * @param z - Stores the X-axis data(as two's complement).
  *
  * @retval None
  */
void ADXL362_GetXyz(short* x, short* y, short* z)
{
    unsigned char xyzValues[6] = {0, 0, 0, 0, 0, 0};

    ADXL362_GetRegisterValue(xyzValues, ADXL362_REG_XDATA_L, 6);
    *x = ((short)xyzValues[1] << 8) + xyzValues[0];
    *y = ((short)xyzValues[3] << 8) + xyzValues[2];
    *z = ((short)xyzValues[5] << 8) + xyzValues[4];
}




/**
  * @brief  读设备温度
  *
  * @retval tempCelsius - 温度(摄氏度)
  */
float ADXL362_ReadTemperature(void)
{
    unsigned char rawTempData[2] = {0, 0};
    short         signedTemp     = 0;
    float         tempCelsius    = 0;

    ADXL362_GetRegisterValue(rawTempData, ADXL362_REG_TEMP_L, 2);
    signedTemp = (short)(rawTempData[1] << 8) + rawTempData[0];
    tempCelsius = (float)signedTemp * 0.065;
    
    return tempCelsius;
}

/**
  * @brief  配置FIFO特征
  * @param mode - 可选择模式
  *               Example: ADXL362_FIFO_DISABLE        -  FIFO 失能.
  *                        ADXL362_FIFO_OLDEST_SAVED   -  Oldest saved mode.
  *                        ADXL362_FIFO_STREAM         -  Stream mode.
  *                        ADXL362_FIFO_TRIGGERED      -  Triggered mode.
  * @param waterMarkLvl - 指定要存储在FIFO中的样本数.
  * @param enTempRead - 将温度数据存储到FIFO
  *                     Example: 1 - temperature data is stored in the FIFO
  *                                  together with x-, y- and x-axis data.
  *                              0 - temperature data is skipped.
  * @retval None
  */
void ADXL362_FifoSetup(unsigned char  mode,
                       unsigned short waterMarkLvl,
                       unsigned char  enTempRead)
{
    unsigned char writeVal = 0;

    writeVal = ADXL362_FIFO_CTL_FIFO_MODE(mode) |
               (enTempRead * ADXL362_FIFO_CTL_FIFO_TEMP) |
               ADXL362_FIFO_CTL_AH;
    ADXL362_SetRegisterValue(writeVal, ADXL362_REG_FIFO_CTL, 1);
    ADXL362_SetRegisterValue(waterMarkLvl, ADXL362_REG_FIFO_SAMPLES, 2);
}


/**
  * @brief  配置活动检测
  * @param  refOrAbs - 参考/绝对 活动选择
  *                   Example: 0 - absolute mode.
  *                            1 - referenced mode.
  * @param  threshold - 11-bit unsigned value that the adxl362 samples are
  *                    compared to.
  * @param  time - 8-bit value written to the activity timer register. The amount
  *               of time (in seconds) is: time / ODR, where ODR - is the output 
  *               data rate.
  * @retval None.
  */
void ADXL362_SetupActivityDetection(unsigned char  refOrAbs,
                                    unsigned short threshold,
                                    unsigned char  time)
{
    unsigned char oldActInactReg = 0;
    unsigned char newActInactReg = 0;

    /* Configure motion threshold and activity timer. */
    ADXL362_SetRegisterValue((threshold & 0x7FF), ADXL362_REG_THRESH_ACT_L, 2);
    ADXL362_SetRegisterValue(time, ADXL362_REG_TIME_ACT, 1);
    /* Enable activity interrupt and select a referenced or absolute
       configuration. */
    ADXL362_GetRegisterValue(&oldActInactReg, ADXL362_REG_ACT_INACT_CTL, 1);
    newActInactReg = oldActInactReg & ~ADXL362_ACT_INACT_CTL_ACT_REF;
    newActInactReg |= ADXL362_ACT_INACT_CTL_ACT_EN |
                     (refOrAbs * ADXL362_ACT_INACT_CTL_ACT_REF);
    ADXL362_SetRegisterValue(newActInactReg, ADXL362_REG_ACT_INACT_CTL, 1);
}

/**
  * @brief  配置不活动检测
  * @param refOrAbs - 参考/绝对不活动选择
  *                   Example: 0 - absolute mode.
  *                            1 - referenced mode.
  * @param threshold - 11-bit unsigned value that the adxl362 samples are
  *                    compared to.
  * @param time - 16-bit value written to the inactivity timer register. The 
  *               amount of time (in seconds) is: time / ODR, where ODR - is the 
  *               output  data rate.
  *
  * @retval None
  */
void ADXL362_SetupInactivityDetection(unsigned char  refOrAbs,
                                      unsigned short threshold,
                                      unsigned short time)
{
    unsigned char oldActInactReg = 0;
    unsigned char newActInactReg = 0;
    
    /* Configure motion threshold and inactivity timer. */
    ADXL362_SetRegisterValue((threshold & 0x7FF),
                              ADXL362_REG_THRESH_INACT_L,
                              2);
    ADXL362_SetRegisterValue(time, ADXL362_REG_TIME_INACT_L, 2);
    /* Enable inactivity interrupt and select a referenced or absolute
       configuration. */
    ADXL362_GetRegisterValue(&oldActInactReg, ADXL362_REG_ACT_INACT_CTL, 1);
    newActInactReg = oldActInactReg & ~ADXL362_ACT_INACT_CTL_INACT_REF;
    newActInactReg |= ADXL362_ACT_INACT_CTL_INACT_EN |
                     (refOrAbs * ADXL362_ACT_INACT_CTL_INACT_REF);
    ADXL362_SetRegisterValue(newActInactReg, ADXL362_REG_ACT_INACT_CTL, 1);
}

二、芯片使用

使用芯片的运动唤醒模式功能,通过映射唤醒信号到中断INT2引脚,控制单片机发送数据。

1、运动唤醒模式

唤醒模式非常适合进行简单的有无运动检测,其功耗极低(2.0 V电源电压时仅270 nA)。唤醒模式对于实现运动激活的开关操作特别有用,系统其余部分只有在检测到运动之后才激活。
唤醒模式仅以大约每秒6次的频率测量加速度以确定是否发生运动,从而将功耗降至非常低的水平。如果检测到运动,加速度计可以通过如下方式自治响应:

  • 切换到全带宽测量模式
  • 向微控制器发出一个中断信号
  • 唤醒下游电路,具体依配置而定

在唤醒模式下,除运动定时器以外的所有其它加速计功能都可以使用。所有寄存器都可以访问,实时数据可以读出和/或存入FIFO。

1.1唤醒模式的体现由AWAKE位来体现

AWAKE位用于指示ADXL362处于唤醒还是休眠状态。当器件运动时,器件唤醒;当器件静止时,器件休眠。
唤醒信号可以映射到INT1或INT2引脚,该引脚可以用作状态输出,用以根据加速度计的唤醒状态,连接或断开下游电路的电源。配合环路模式时,此配置可实现自治运动激活的开关,如图所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-miSyGGRd-1584185336842)(https://raw.githubusercontent.com/WuliYongShun/PictureHouse/master/img/20200313172247.png)]
如果下游电路的开启时间是可接受的,此运动开关配置可以消除应用其余部分的待机功耗,从而大幅降低系统级功耗。此待机功耗常常超过ADXL362的正常工作功耗。

1.2自治运动开关原理及程序

ADXL362的特性使它非常适合用作自治运动开关。下面的示例实现了一个开关,配置好后,它不需要主机处理器的干预,就能灵巧地管理系统电源。本例中,唤醒信号映射到INT2引脚,用以驱动高边功率开关(如ADP195等)来控制下游电路的电源,我们这里用中断信号唤醒单片机并,通过485向另一块电路板发送数据。

程序启动流程
假设使用±2 g测量范围和唤醒工作模式

  • 1、写入十进制250 (0xFA)到寄存器0x20,写入0到寄存器0x21:将运动阈值设为250 mg。
  • 2、写入十进制150 (0x96)到寄存器0x23,写入0到寄存器0x24:将静止阈值设为150 mg。
  • 3、写入十进制30 (0x1E)到寄存器0x25:将静止定时器设为30个样本或约5秒。
  • 4、写入0x3F到寄存器0x27:配置环路模式的运动检测并使能相对运动和静止检测。
  • 5、写入0x40到寄存器0x2B:将AWAKE位映射到INT2。INT2引脚与开关的栅极相连。
  • 6、写入0x0A到寄存器0x2D:开始在唤醒模式下进行测量。

对应相关程序代码如下:

void ADXL362_WakeUpMode(void)
{
	/* 1、写入十进制250 (0xFA)到寄存器0x20,写入0到寄存器0x21:将运动阈值设为250 mg。 */
	ADXL362_SetRegisterValue( 0xFA, 0x20, 1 );
	
	/* 2、写入十进制150 (0x96)到寄存器0x23,写入0到寄存器0x24:将静止阈值设为150 mg。 */
	ADXL362_SetRegisterValue( 0x96, 0x23, 1 );
	
	/* 3、写入十进制30 (0x1E)到寄存器0x25:将静止定时器设为30个样本或约5秒。 */
	ADXL362_SetRegisterValue( 0x1E, 0x25, 1 );
	
	/* 4、写入0x3F到寄存器0x27:配置环路模式的运动检测并使能相对运动和静止检测。 */
	ADXL362_SetRegisterValue( 0x3F, 0x27, 1 );
	
	/* 5、写入0x40到寄存器0x2B:将AWAKE位映射到INT2。INT2引脚与开关的栅极相连。 */
	ADXL362_SetRegisterValue( 0x40, 0x2B, 1 );
	
	/* 6、写入0x0A到寄存器0x2D:开始在唤醒模式下进行测量。*/
	ADXL362_SetRegisterValue( 0x0A, 0x2D, 1 );
	
}	

进过验证传感器正常,唤醒功能正常同时该传感器作为动作开关可以根据’ 0x20,和0x23 '设置动作阈值,来改变传感器的灵敏度。
需要注意的是,需要按照参考手册的时序进行操作

2、静止检测模式

后续更新

你可能感兴趣的:(STM32)