文章目录
MAX30102配置参数简介
几个关键寄配置如下
Interrupt Enable
就是一些中断的使能,这里我们只使能A_FULL: FIFO Almost Full Flag这个中断,也就是当FIFO要满的时候产生中断(INT引脚拉低),(注:FIFO深度32,FIFO要满的标准可以设定(通过FIFO Configuration设置),比如20,当FIFO中有20个数据时,产生中断,这时候去读FIFO中的数据)。
FIFO Configuration
其中B7-B5设置采样均值(多个采样点求均值输出一个值),B4表示FIFO满之后是否继续写入,B3-B0就是设置Almost Full 的,比如0x00就是FIFO中有32个样本时产生INT中断。
Mode Configuration
模式设置(B2-B0), 0x02表示HR模式,0x03表示SpO2模式。
SpO2 Configuration
这里主要配置采样率,0x17为1000Hz,还得注意对照数据手册,HR和SpO2模式,LED脉宽,都对采样率有限制,具体参考数据手册。
问题描述
使用MAX30102采集数据时,设置SpO2模式,FIFO Almost Full = 20(也用过32),采样率1000,每次中断读一次FIFO(读完),实际采样时,两次INT时间间隔大于20ms,采6000个样本时间大于6s,大概在8s左右,与预想不符合。猜想在FIFO读的时候,未向FIFO写数据,有数据丢失。
配置
max30102_Bus_Write(REG_FIFO_CONFIG,0x0C);//FIFO Almost Full = 20
max30102_Bus_Write(REG_MODE_CONFIG,0x02);//HR Mode
max30102_Bus_Write(REG_SPO2_CONFIG,0x17);//采样率1000 Hz
max30102_Bus_Write(REG_INTR_ENABLE_1,0x80); //INT
问题描述
使用MAX30102的"FIFO Almost Full Flag"中断来读数据,在HR Mode下,当FIFO快满时产生INT中断,然后一次性读出FIFO数据,按照预想,两次中断时间间隔应该等于采样周期*FIFO快满的个数。例如:FIFO快满设置为20,采样率1000,则两个中断之间时间间隔为20ms,但是实际情况不是这样。
实际运行中,两个INT时间间隔为23ms,而从FIFO被读出开始计算,则刚好20ms,如图,难道在FIFO读取期间,没有数据写入FIFO ?
解决方法
配置
max30102_Bus_Write(REG_FIFO_CONFIG,0x10);//FIFO Almost Full = 32
max30102_Bus_Write(REG_MODE_CONFIG,0x03);//SpO2 Mode
max30102_Bus_Write(REG_SPO2_CONFIG,0x14);//采样率1000 Hz
max30102_Bus_Write(REG_INTR_ENABLE_1,0x80); //INT
而采用SPO_2模式就没有出现这种问题,如下图,在采样率1000,FIFO ALMOST FULL为32时,INT间隔恰好为32ms。
反思
因为前期调试一直使用HR模式,然后数据手册中的关于FIFO的描述,HR Mode 和 SpO2 Mode,在使用FIFO的描述上,不知道为什么会出现这种情况,看数据手册,两个模式INT和应该是一样的呀。先这样吧呜呜呜。另外,附上部分代码。
部分代码
使用FreeRTOS,在INT中断服务函数给采集任务抛出事件,任务开始采集
INT中断服务函数
void EXTI9_5_IRQHandler(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (EXTI_GetITStatus(EXTI_Line7)==SET) {//INT中断
xEventGroupSetBitsFromISR(Event_Handle, DATA_INT_EVENT,&xHigherPriorityTaskWoken);
EXTI_ClearITPendingBit(EXTI_Line7);//清除中断函数的标志位,否则程序将一直卡在中断函数中
}
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );//及时切换任务
}
采集任务
void get_data_from_senser_task(void) {
u8 data[FIFO_ALMOST_FULL*3];
while(1) {
xEventGroupWaitBits(
Event_Handle,
DATA_INT_EVENT|KEEP_SAMPLE_EVENT,//开始一次采集并且senser中断产生
pdFALSE,//不清除事件位(主要是不清除持续采集信号
pdTRUE,//与关系
portMAX_DELAY);
xEventGroupClearBits(Event_Handle,DATA_INT_EVENT);//采集完成,清除INT事件
vTaskSuspendAll();//挂起调度器
max30102_FIFO_ReadBytes(REG_FIFO_DATA,data);//读数据
vTaskPrioritySet(get_data_from_senser_task_Handle,3);
vTaskPrioritySet(data_send_2_H750_task_Handle,4);
xTaskResumeAll();//恢复调度器
xQueueSend(DATA_Queue_Handle,data,portMAX_DELAY);//通过消息队列传输,然后发送出去,然后发个ready信号,等主机来读
rx_data_cnt+=FIFO_ALMOST_FULL;
if(rx_data_cnt>=RX_DATA_MAX_CNT) {
rx_data_cnt = 0;
xEventGroupClearBits(Event_Handle,KEEP_SAMPLE_EVENT);//一次采集完成
vTaskSuspend(LED1_Task_Handle);
max30102_close_int();
}
}
}