你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

ASM330LHH使用FIFO阈值中断输出时工作异常

[复制链接]
aurasemi 提问时间:2024-7-8 14:19 / 未解决

我使用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, &reg_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;
            }
        }
    }
}
收藏 评论3 发布时间:2024-7-8 14:19

举报

3个回答
aurasemi 回答时间:2024-7-10 11:34:21

已解决,原因是第三次通过中断读取数据时,asm330lhh_fifo_wtm_flag_get(&dev_ctx, &wmflag);获取到的wmflag是0,导致没有在本次中断中执行读取,内部产生中断锁存了,所以不再产生新中断;解决办法,在这里retry,基本retry3次就可以读到wmflag==1;

st_yujie2510 回答时间:2024-7-9 13:57:11

“不再产生中断”是通过什么检查的?示波器?逻辑分析仪?还是没有进代码的中断服务程序?如果是代码没有检测到中断,建议用示波器查看INT管脚的电平,确定是否真的没有中断信号产生。

另外,可以用逻辑分析仪同时监控一下SPI/I2C总线和INT信号,看看sensor到底处于什么状况。

aurasemi 回答时间:2024-7-9 17:05:29

st_yujie2510 发表于 2024-7-9 13:57
“不再产生中断”是通过什么检查的?示波器?逻辑分析仪?还是没有进代码的中断服务程序?如果是代码没 ...

[md](为了便于观测,我将ODR调整为了26Hz,这个改动不影响这个问题,我试过各种频率,都有这个现象),同时使用示波器抓取了INT1的波形,发现确实是前2个脉冲是正常的,但第三个脉冲上升后一直维持在高电平,所以问题就是ASM330LHH这边没有继续发出INT1中断了。

af1ae0caecf3012997bf1f0f3e23947.jpg

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版