我使用FIFO的Continuous mode,并把FIFO的WATERMASK设置为2,然后将FIFO阈值中断路由到INT1,理论上应该每产生一组XL+GY数据,就产生一个中断,然后我就可以在中断处理函数中去读取一组XL+GY数据。
实际运行发现,当产生第二次中断并读取数据后,就不再产生新的中断了。
部分代码如下:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == IMU_INT1_Pin)
{
asm330lhh_fifo_read();
}
}
void asm330lhh_fifo_init(ASM330LHH_FREQ freq)
{
/* Uncomment to configure INT 1 */
asm330lhh_pin_int1_route_t int1_route;
dev_ctx.write_reg = (stmdev_write_ptr)platform_write;
dev_ctx.read_reg = platform_read;
dev_ctx.handle = &SENSOR_BUS;
/* Check device ID */
asm330lhh_device_id_get(&dev_ctx, &whoamI);
if (whoamI != ASM330LHH_ID)
while (1);
/* Restore default configuration */
asm330lhh_reset_set(&dev_ctx, PROPERTY_ENABLE);
do
{
asm330lhh_reset_get(&dev_ctx, &rst);
}
while (rst);
/* Start device configuration. */
asm330lhh_device_conf_set(&dev_ctx, PROPERTY_ENABLE);
/* Enable Block Data Update */
asm330lhh_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
/* Set full scale */
asm330lhh_xl_full_scale_set(&dev_ctx, ASM330LHH_8g);
asm330lhh_gy_full_scale_set(&dev_ctx, ASM330LHH_500dps);
/* Set FIFO mode to Stream mode (aka Continuous Mode) */
asm330lhh_fifo_mode_set(&dev_ctx, ASM330LHH_STREAM_MODE);
/* Uncomment if interrupt generation on FIFO INT1 pin */
int1_route.int1_ctrl.int1_fifo_th = PROPERTY_ENABLE;
asm330lhh_pin_int1_route_set(&dev_ctx, &int1_route);
/* Set FIFO watermark (number of unread sensor data TAG + 6 bytes
* stored in FIFO) to 2 samples
*/
asm330lhh_fifo_watermark_set(&dev_ctx, 2);
/* Set FIFO batch XL/Gyro ODR to freq */
/* Set Output Data Rate */
asm330lhh_fifo_xl_batch_set(&dev_ctx, ASM330LHH_XL_BATCHED_AT_26Hz);
asm330lhh_fifo_gy_batch_set(&dev_ctx, ASM330LHH_GY_BATCHED_AT_26Hz);
asm330lhh_xl_data_rate_set(&dev_ctx, ASM330LHH_XL_ODR_26Hz);
asm330lhh_gy_data_rate_set(&dev_ctx, ASM330LHH_GY_ODR_26Hz);
}
void asm330lhh_fifo_read(void)
{
asm330lhh_fifo_tag_t reg_tag;
uint8_t wmflag = 0;
uint16_t num = 0;
/* Read watermark flag */
asm330lhh_fifo_wtm_flag_get(&dev_ctx, &wmflag);
if (wmflag > 0)
{
/* Read number of samples in FIFO */
asm330lhh_fifo_data_level_get(&dev_ctx, &num);
while (num--)
{
/* Read FIFO tag */
asm330lhh_fifo_sensor_tag_get(&dev_ctx, ®_tag);
switch (reg_tag)
{
case ASM330LHH_XL_NC_TAG:
{
static unsigned long last_tick = 0;
memset(data_raw_acceleration.u8bit, 0x00, 3 * sizeof(int16_t));
asm330lhh_fifo_out_raw_get(&dev_ctx, data_raw_acceleration.u8bit);
acceleration_mg[0] =
asm330lhh_from_fs8g_to_mg(data_raw_acceleration.i16bit[0]);
acceleration_mg[1] =
asm330lhh_from_fs8g_to_mg(data_raw_acceleration.i16bit[1]);
acceleration_mg[2] =
asm330lhh_from_fs8g_to_mg(data_raw_acceleration.i16bit[2]);
/* read temperature */
memset(&data_raw_temperature, 0x00, sizeof(int16_t));
asm330lhh_temperature_raw_get(&dev_ctx, &data_raw_temperature);
temperature_degC = asm330lhh_from_lsb_to_celsius(data_raw_temperature);
#if LOG_OUT
tx_com(tx_buffer, strlen((char const *)tx_buffer));
#endif
}
break;
case ASM330LHH_GYRO_NC_TAG:
{
memset(data_raw_angular_rate.u8bit, 0x00, 3 * sizeof(int16_t));
asm330lhh_fifo_out_raw_get(&dev_ctx, data_raw_angular_rate.u8bit);
angular_rate_mdps[0] =
asm330lhh_from_fs500dps_to_mdps(data_raw_angular_rate.i16bit[0]);
angular_rate_mdps[1] =
asm330lhh_from_fs500dps_to_mdps(data_raw_angular_rate.i16bit[1]);
angular_rate_mdps[2] =
asm330lhh_from_fs500dps_to_mdps(data_raw_angular_rate.i16bit[2]);
#if LOG_OUT
tx_com(tx_buffer, strlen((char const *)tx_buffer));
#endif
}
break;
default:
{
/* Flush unused samples */
memset(dummy.u8bit, 0x00, 3 * sizeof(int16_t));
asm330lhh_fifo_out_raw_get(&dev_ctx, dummy.u8bit);
}
break;
}
}
}
}
|
已解决,原因是第三次通过中断读取数据时,asm330lhh_fifo_wtm_flag_get(&dev_ctx, &wmflag);获取到的wmflag是0,导致没有在本次中断中执行读取,内部产生中断锁存了,所以不再产生新中断;解决办法,在这里retry,基本retry3次就可以读到wmflag==1;
“不再产生中断”是通过什么检查的?示波器?逻辑分析仪?还是没有进代码的中断服务程序?如果是代码没有检测到中断,建议用示波器查看INT管脚的电平,确定是否真的没有中断信号产生。
另外,可以用逻辑分析仪同时监控一下SPI/I2C总线和INT信号,看看sensor到底处于什么状况。
[md](为了便于观测,我将ODR调整为了26Hz,这个改动不影响这个问题,我试过各种频率,都有这个现象),同时使用示波器抓取了INT1的波形,发现确实是前2个脉冲是正常的,但第三个脉冲上升后一直维持在高电平,所以问题就是ASM330LHH这边没有继续发出INT1中断了。