接前一篇文章:ICM-20948 Wake on Motion功能开发全过程(11)
探索工作
深入探索
上一回讲完了InvenSense官方Wake on Motion功能实现指导文档中的各个步骤以及对应的代码。再来回顾一下整体步骤:
但是到这里并不算全部完成,还有一些工作要做。本回就来讲一下后续工作、对应代码以及笔者遇到的实际问题。
上边步骤完成后,还要设置一下中断锁存方式。对应ICM-20948手册中的内容如下:
INT1_LATCH_EN位表示中断锁存方式。值1表示发生中断时,INT1引脚的电平一直保持,直到中断状态被清除;值0表示发生中断时,INT1引脚产生一个50 us的脉冲。
这一部分对应代码如下:
//ret = icm20948_set_int_latch(1);
ret = icm20948_set_int_latch(0);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "icm20948_wom_init failed");
return ret;
}
ESP_LOGI(TAG, "icm20948_wom_init successfully");
static esp_err_t icm20948_set_int_latch(bool mode)
{
esp_err_t ret;
uint8_t tmp;
ret = icm20948_set_bank(icm20948, 0);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "icm20948_set_bank failed");
return ret;
}
ret = icm20948_read(icm20948, ICM20948_INT_PIN_CFG, &tmp, 1);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "icm20948_read failed");
return ret;
}
//bit 5 (INT1_LATCH_EN)
if (mode)
tmp |= 0x20;
else
tmp &= 0xDF;
ret = icm20948_write(icm20948, ICM20948_INT_PIN_CFG, &tmp, 1);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "icm20948_write failed");
return ret;
}
return ESP_OK;
}
别小看这个中断锁存方式,笔者在它身上吃了大亏。从上边代码可以看到,笔者两种方式都尝试了。
//ret = icm20948_set_int_latch(1);
ret = icm20948_set_int_latch(0);
当选择方式0、即发生中断时引脚输出脉冲时,芯片完全正常,通过示波器测量,信号也都对;而当选择方式1、即发生中断时引脚电平保持,直到中断状态清除时,当中断产生后,引脚就一直保持中断有效电平(低或高,根据INT_PIN_CFG寄存器的INT1_ACTL位配置)不变了。这一点与手册所说的完全不同了。
一开始笔者以为是没有清除中断状态所导致的,后来查阅手册,清除中断状态只需要读取中断状态寄存器就可以了。
但是实测发现,当发生中断的时候,第一次读取INT_STAUS寄存器,值为0x08,这就说明确实产生了WOM_INT中断。而紧接着当第二次读取INT_STATUS寄存器的时候,值为0了,也确实说明WOM_INT中断已经清除了。
但是这个时候,中断引脚的有效电平一直保持,并没有清除。为什么会这样?还有哪里没注意到吗?
笔者又反复看了芯片手册,确实也没找到其它地方了。同时,笔者在网上看到了以下几个帖子:
https://github.com/WickedLukas/ICM20948/blob/master/ICM20948.cpp
ICM20648 - Simple driver for the TDK InvenSense ICM20648 6-a… | Mbed
一个帖子还不具备代表性,两个帖子尤其是两种型号的芯片都这样说,那恐怕就是事实了。笔者也觉得应该就是ICM-20948芯片就是这样,这是它硬件的一个bug。
在此,也欢迎和希望如果有后来者解决此问题或者发现此问题的原因了(非芯片设计问题,而是笔者等人的理解问题),在此留言指正,不胜感激!
更多内容请看下回。