本次计步手环设计基于F103核心板与X-NUCLEO-IKS01A3传感器开发板。唤醒功能通过X-NUCLEO-IKS01A3上的LIS2DW12传感器来实现。
LIS2DW12是一款高性能超低功耗三轴加速度计。供电电压1.62V-3.6V,可以通过常用的SPI与I2C进行通讯。LIS2DW12带有静止检测、运动检测功能。
计步手环使用LIS2DW12的运动检测来实现唤醒功能。在之前添加计步功能的程序(参看《 基于F103与X-NUCLEO-IKS01A3的计步手环之计步功能》)基础上进行功能添加。LIS2DW12传感器在(灵敏度可通过设置调整)受到震动后通过INT引脚输出高电平信号,通知F103核心板执行唤醒动作。实际操作时只要轻点X-NUCLEO-IKS01A3,产生震动效果就可触发唤醒功能。
首先对之前的程序作了一些改动,使能了LIS2DW12传感器,并增加了一个检测LIS2DW12的INT1的中断的引脚PB11。接着就是添加唤醒功能。在完成对LIS2DW12的初始化之后,需要使能LIS2DW12的唤醒功能,并配置相应的参数及中断输出。然后是检测唤醒中断及事件处理(这里是点亮OLED屏)。
1.设置LIS2DW12的输出频率、运行模式选择及满量程设置
运行可选模式如下:
根据选择的模式,对以下三个寄存器进行配置。
2.设置唤醒参数
3.设置唤醒中断通过INT1输出
INT1 pin可以绑定多个功能或状态同时使用。当检测到中断后,通过读取对应的事件状态寄存器来确定事件源。
唤醒中断为INT1_WU。
使能LIS2DW12的唤醒功能,并配置相应的参数及中断输出
/**
* @brief Enable wake up detection
* @param pObj the device pObj
* @retval 0 in case of success, an error code otherwise
*/
int32_t LIS2DW12_ACC_Enable_Wake_Up_Detection(LIS2DW12_Object_t *pObj)
{
int32_t ret = LIS2DW12_OK;
lis2dw12_ctrl4_int1_pad_ctrl_t val;
/* Output Data Rate selection */
if (LIS2DW12_ACC_SetOutputDataRate(pObj, 200.0f) != LIS2DW12_OK)
{
return LIS2DW12_ERROR;
}
/* Full scale selection */
if (LIS2DW12_ACC_SetFullScale(pObj, 2) != LIS2DW12_OK)
{
return LIS2DW12_ERROR;
}
/* WAKE_DUR setting */
if (lis2dw12_wkup_dur_set(&(pObj->Ctx), 0x00) != LIS2DW12_OK)
{
return LIS2DW12_ERROR;
}
/* Set wake up threshold. */
if (lis2dw12_wkup_threshold_set(&(pObj->Ctx), 0xf) != LIS2DW12_OK)
{
return LIS2DW12_ERROR;
}
if (lis2dw12_pin_int1_route_get(&(pObj->Ctx), &val) != LIS2DW12_OK)
{
return LIS2DW12_ERROR;
}
val.int1_wu = PROPERTY_ENABLE;
if (lis2dw12_pin_int1_route_set(&(pObj->Ctx), &val) != LIS2DW12_OK)
{
return LIS2DW12_ERROR;
}
return ret;
}
4.事件确认及处理
检测STATUS寄存器中的WU_IA标志位,为1,则表示检测到有唤醒行为。执行唤醒后的动作,点亮OLED屏显示当前步数。
获取状态寄存器的操作代码
/**
* @brief Get the status of all hardware events
* @param pObj the device pObj
* @param Status the status of all hardware events
* @retval 0 in case of success, an error code otherwise
*/
int32_t LIS2DW12_ACC_Get_Event_Status(LIS2DW12_Object_t *pObj, LIS2DW12_Event_Status_t *Status)
{
lis2dw12_status_t status_reg;
lis2dw12_ctrl4_int1_pad_ctrl_t ctrl4_int1_reg;
lis2dw12_ctrl5_int2_pad_ctrl_t ctrl5_int2_reg;
(void)memset((void *)Status, 0x0, sizeof(LIS2DW12_Event_Status_t));
if (lis2dw12_read_reg(&(pObj->Ctx), LIS2DW12_STATUS, (uint8_t *)&status_reg, 1) != LIS2DW12_OK)
{
return LIS2DW12_ERROR;
}
if (lis2dw12_read_reg(&(pObj->Ctx), LIS2DW12_CTRL4_INT1_PAD_CTRL, (uint8_t *)&ctrl4_int1_reg, 1) != LIS2DW12_OK)
{
return LIS2DW12_ERROR;
}
if (lis2dw12_read_reg(&(pObj->Ctx), LIS2DW12_CTRL5_INT2_PAD_CTRL, (uint8_t *)&ctrl5_int2_reg, 1) != LIS2DW12_OK)
{
return LIS2DW12_ERROR;
}
if (ctrl4_int1_reg.int1_wu == 1U)
{
if (status_reg.wu_ia == 1U)
{
Status->WakeUpStatus = 1;
}
}
if (ctrl4_int1_reg.int1_6d == 1U)
{
if (status_reg._6d_ia == 1U)
{
Status->D6DOrientationStatus = 1;
}
}
if (ctrl5_int2_reg.int2_sleep_chg == 1U)
{
if (status_reg.sleep_state == 1U)
{
Status->SleepStatus = 1;
}
}
return LIS2DW12_OK;
}
附源码:
LIS2DW12手册: