这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » Let'sdo2025第二期活动[智能手环DIY活动]驱动MAXREFDES11

共1条 1/1 1 跳转至

Let'sdo2025第二期活动[智能手环DIY活动]驱动MAXREFDES117

菜鸟
2025-10-03 12:22:54     打赏
驱动MAXREFDES117

其中的驱动代码:linux/drivers/iio/health/max30102.c at main · analogdevicesinc/linux

根据驱动代码和原理图:MAXREFDES117 | 参考设计 | 亚德诺半导体

这里是.c的驱动代码

#include "max30102.h"
#include "i2c.h"
#include "mxc_device.h"
#include "mxc_delay.h"
#include <string.h>
#include <stdio.h>
#include <math.h>

// 缓冲区大小定义
#ifndef BUFFER_SIZE
#define BUFFER_SIZE 100
#endif

// 是否开启调试日志
#define MAX30102_DEBUG 1 // 1: 开启日志,0: 关闭日志

#if MAX30102_DEBUG
#define MAX30102_LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define MAX30102_LOG(fmt, ...) // 什么都不做
#endif

// 全局状态变量
static bool g_initialized = false;
static max30102_mode_t g_current_mode = MAX30102_MODE_SPO2;

// I2C写入函数 - 优化版本
static int MAX30102_WriteReg(uint8_t reg_addr, uint8_t data)
{
   uint8_t reg_data[2] = {reg_addr, data};
   mxc_i2c_req_t req;
   
   req.i2c = MXC_I2C1;
   req.addr = MAX30102_I2C_ADDR;
   req.tx_buf = reg_data;
   req.tx_len = 2;
   req.rx_buf = NULL;
   req.rx_len = 0;
   req.restart = 0;
   req.callback = NULL;

   int ret = MXC_I2C_MasterTransaction(&req);
   if (ret != 0) {
       MAX30102_LOG("[MAX30102] Write register failed: reg=0x%02X, data=0x%02X, ret=%d\n", reg_addr, data, ret);
   }
   
   return ret;
}

// I2C读取函数 - 优化版本
static int MAX30102_ReadReg(uint8_t reg_addr, uint8_t *data)
{
   mxc_i2c_req_t req;
   int err;

   // 第一步:发送寄存器地址
   req.i2c = MXC_I2C1;
   req.addr = MAX30102_I2C_ADDR;
   req.tx_buf = &reg_addr;
   req.tx_len = 1;
   req.rx_buf = NULL;
   req.rx_len = 0;
   req.restart = 1; // Repeated START
   req.callback = NULL;

   err = MXC_I2C_MasterTransaction(&req);
   if (err != 0) {
       MAX30102_LOG("[MAX30102] Read register failed: reg=0x%02X, ret=%d\n", reg_addr, err);
       return err;
   }

   // 第二步:读取数据
   req.tx_buf = NULL;
   req.tx_len = 0;
   req.rx_buf = data;
   req.rx_len = 1;
   req.restart = 0;
   req.callback = NULL;

   return MXC_I2C_MasterTransaction(&req);
}

// I2C多字节读取函数
static int MAX30102_ReadMulti(uint8_t reg_addr, uint8_t *data, uint8_t len)
{
   mxc_i2c_req_t req;
   int err;

   // 第一步:发送寄存器地址
   req.i2c = MXC_I2C1;
   req.addr = MAX30102_I2C_ADDR;
   req.tx_buf = &reg_addr;
   req.tx_len = 1;
   req.rx_buf = NULL;
   req.rx_len = 0;
   req.restart = 1; // Repeated START
   req.callback = NULL;

   err = MXC_I2C_MasterTransaction(&req);
   if (err != 0) {
       MAX30102_LOG("[MAX30102] Read multi failed: reg=0x%02X, ret=%d\n", reg_addr, err);
       return err;
   }

   // 第二步:读取数据
   req.tx_buf = NULL;
   req.tx_len = 0;
   req.rx_buf = data;
   req.rx_len = len;
   req.restart = 0;
   req.callback = NULL;

   return MXC_I2C_MasterTransaction(&req);
}

// 初始化MAX30102 - 简化版本
max30102_error_t MAX30102_Init(void)
{
   MAX30102_LOG("[MAX30102] Initializing...\n");
   
   if (g_initialized) {
       MAX30102_LOG("[MAX30102] Already initialized\n");
       return MAX30102_OK;
   }

   // 读取Part ID验证通信
   uint8_t part_id;
   if (MAX30102_ReadReg(MAX30102_REG_PART_ID, &part_id) != 0) {
       MAX30102_LOG("[MAX30102] Failed to read Part ID\n");
       return MAX30102_ERROR_I2C;
   }
   
   if (part_id != 0x15) { // MAX30102的Part ID是0x15
       MAX30102_LOG("[MAX30102] Invalid Part ID: 0x%02X (expected 0x15)\n", part_id);
       return MAX30102_ERROR_INIT;
   }
   
   MAX30102_LOG("[MAX30102] Part ID verified: 0x%02X\n", part_id);

   // 软复位
   MAX30102_WriteReg(MAX30102_REG_MODE_CONFIG, 0x40);
   MXC_Delay(MXC_DELAY_MSEC(10));

   // 设置SpO2模式
   MAX30102_WriteReg(MAX30102_REG_MODE_CONFIG, 0x03); // SpO2模式
   MAX30102_WriteReg(MAX30102_REG_SPO2_CONFIG, 0x27); // 18-bit, 100Hz
   MAX30102_WriteReg(MAX30102_REG_LED1_PA, 0x24);     // 红光 ~7mA
   MAX30102_WriteReg(MAX30102_REG_LED2_PA, 0x24);     // IR ~7mA
   
   g_initialized = true;
   MAX30102_LOG("[MAX30102] Initialization completed successfully\n");
   return MAX30102_OK;
}

// 反初始化
max30102_error_t MAX30102_Deinit(void)
{
   if (!g_initialized) {
       return MAX30102_OK;
   }
   
   // 关闭传感器
   if (MAX30102_WriteReg(MAX30102_REG_MODE_CONFIG, 0x80) != 0) { // 进入待机模式
       return MAX30102_ERROR_I2C;
   }
   
   g_initialized = false;
   MAX30102_LOG("[MAX30102] Deinitialized\n");
   return MAX30102_OK;
}

// 软复位
max30102_error_t MAX30102_Reset(void)
{
   if (MAX30102_WriteReg(MAX30102_REG_MODE_CONFIG, 0x40) != 0) { // 软复位位
       return MAX30102_ERROR_I2C;
   }
   
   MXC_Delay(MXC_DELAY_MSEC(100)); // 等待复位完成
   MAX30102_LOG("[MAX30102] Reset completed\n");
   return MAX30102_OK;
}

// 读取Part ID
max30102_error_t MAX30102_ReadPartID(uint8_t *part_id)
{
   if (part_id == NULL) {
       return MAX30102_ERROR_PARAM;
   }
   
   if (MAX30102_ReadReg(MAX30102_REG_PART_ID, part_id) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   return MAX30102_OK;
}

// 设置工作模式
max30102_error_t MAX30102_SetMode(max30102_mode_t mode)
{
   // 在初始化过程中也允许设置模式
   if (MAX30102_WriteReg(MAX30102_REG_MODE_CONFIG, mode) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   g_current_mode = mode;
   MAX30102_LOG("[MAX30102] Mode set to: %d\n", mode);
   return MAX30102_OK;
}

// 设置LED功率
max30102_error_t MAX30102_SetLEDPulseAmplitude(max30102_led_pa_t red_pa, max30102_led_pa_t ir_pa)
{
   // 在初始化过程中也允许设置LED功率
   if (MAX30102_WriteReg(MAX30102_REG_LED1_PA, red_pa) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   if (MAX30102_WriteReg(MAX30102_REG_LED2_PA, ir_pa) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   MAX30102_LOG("[MAX30102] LED power set - Red: 0x%02X, IR: 0x%02X\n", red_pa, ir_pa);
   return MAX30102_OK;
}

// 设置采样率
max30102_error_t MAX30102_SetSampleRate(max30102_samprate_t sample_rate)
{
   if (!g_initialized) {
       return MAX30102_ERROR_INIT;
   }
   
   uint8_t spo2_config;
   if (MAX30102_ReadReg(MAX30102_REG_SPO2_CONFIG, &spo2_config) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   spo2_config = (spo2_config & 0xE3) | (sample_rate << 2); // 清除采样率位并设置新值
   
   if (MAX30102_WriteReg(MAX30102_REG_SPO2_CONFIG, spo2_config) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   MAX30102_LOG("[MAX30102] Sample rate set to: %d\n", sample_rate);
   return MAX30102_OK;
}

// 设置脉冲宽度
max30102_error_t MAX30102_SetPulseWidth(max30102_pulse_width_t pulse_width)
{
   if (!g_initialized) {
       return MAX30102_ERROR_INIT;
   }
   
   uint8_t spo2_config;
   if (MAX30102_ReadReg(MAX30102_REG_SPO2_CONFIG, &spo2_config) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   spo2_config = (spo2_config & 0xFC) | pulse_width; // 清除脉冲宽度位并设置新值
   
   if (MAX30102_WriteReg(MAX30102_REG_SPO2_CONFIG, spo2_config) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   MAX30102_LOG("[MAX30102] Pulse width set to: %d\n", pulse_width);
   return MAX30102_OK;
}

// 设置ADC范围
max30102_error_t MAX30102_SetADCRange(max30102_adc_range_t adc_range)
{
   if (!g_initialized) {
       return MAX30102_ERROR_INIT;
   }
   
   uint8_t spo2_config;
   if (MAX30102_ReadReg(MAX30102_REG_SPO2_CONFIG, &spo2_config) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   spo2_config = (spo2_config & 0x9F) | (adc_range << 5); // 清除ADC范围位并设置新值
   
   if (MAX30102_WriteReg(MAX30102_REG_SPO2_CONFIG, spo2_config) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   MAX30102_LOG("[MAX30102] ADC range set to: %d\n", adc_range);
   return MAX30102_OK;
}

// 简化的FIFO读取函数 - 参考优化版本
max30102_error_t MAX30102_ReadFIFO(max30102_sample_t *samples, uint8_t *num_samples)
{
   if (!g_initialized || samples == NULL || num_samples == NULL) {
       return MAX30102_ERROR_PARAM;
   }
   
   // 直接读取一个样本(6字节)
   uint8_t buf[6];
   int ret = MAX30102_ReadMulti(MAX30102_REG_FIFO_DATA, buf, 6);
   if (ret != 0) {
       *num_samples = 0;
       return MAX30102_ERROR_FIFO_EMPTY;
   }
   
   // 解析数据 - 使用18位掩码
   samples[0].red = ((uint32_t)buf[0] << 16) | ((uint32_t)buf[1] << 8) | buf[2];
   samples[0].ir = ((uint32_t)buf[3] << 16) | ((uint32_t)buf[4] << 8) | buf[5];
   samples[0].green = 0; // 在SpO2模式下不使用绿色LED
   
   // 应用18位掩码
   samples[0].red &= 0x3FFFF;
   samples[0].ir &= 0x3FFFF;
   
   *num_samples = 1;
   MAX30102_LOG("[MAX30102] Read 1 sample - Red: %lu, IR: %lu\n",
                samples[0].red, samples[0].ir);
   return MAX30102_OK;
}

// 获取FIFO写指针
max30102_error_t MAX30102_GetFIFOWritePtr(uint8_t *write_ptr)
{
   if (write_ptr == NULL) {
       return MAX30102_ERROR_PARAM;
   }
   
   return (MAX30102_ReadReg(MAX30102_REG_FIFO_WR_PTR, write_ptr) == 0) ? MAX30102_OK : MAX30102_ERROR_I2C;
}

// 获取FIFO读指针
max30102_error_t MAX30102_GetFIFOReadPtr(uint8_t *read_ptr)
{
   if (read_ptr == NULL) {
       return MAX30102_ERROR_PARAM;
   }
   
   return (MAX30102_ReadReg(MAX30102_REG_FIFO_RD_PTR, read_ptr) == 0) ? MAX30102_OK : MAX30102_ERROR_I2C;
}

// 获取FIFO溢出计数器
max30102_error_t MAX30102_GetFIFOOverflowCounter(uint8_t *overflow_count)
{
   if (overflow_count == NULL) {
       return MAX30102_ERROR_PARAM;
   }
   
   return (MAX30102_ReadReg(MAX30102_REG_OVF_COUNTER, overflow_count) == 0) ? MAX30102_OK : MAX30102_ERROR_I2C;
}

// 启用中断
max30102_error_t MAX30102_EnableInterrupts(uint8_t int1_enable, uint8_t int2_enable)
{
   // 在初始化过程中也允许启用中断
   if (MAX30102_WriteReg(MAX30102_REG_INTR_ENABLE_1, int1_enable) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   if (MAX30102_WriteReg(MAX30102_REG_INTR_ENABLE_2, int2_enable) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   MAX30102_LOG("[MAX30102] Interrupts enabled - INT1: 0x%02X, INT2: 0x%02X\n", int1_enable, int2_enable);
   return MAX30102_OK;
}

// 读取中断状态
max30102_error_t MAX30102_ReadInterruptStatus(uint8_t *int1_status, uint8_t *int2_status)
{
   if (int1_status == NULL || int2_status == NULL) {
       return MAX30102_ERROR_PARAM;
   }
   
   if (MAX30102_ReadReg(MAX30102_REG_INTR_STATUS_1, int1_status) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   if (MAX30102_ReadReg(MAX30102_REG_INTR_STATUS_2, int2_status) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   return MAX30102_OK;
}

// 清除中断
max30102_error_t MAX30102_ClearInterrupts(void)
{
   uint8_t int1_status, int2_status;
   return MAX30102_ReadInterruptStatus(&int1_status, &int2_status);
}

// 读取温度
max30102_error_t MAX30102_ReadTemperature(float *temperature)
{
   if (temperature == NULL) {
       return MAX30102_ERROR_PARAM;
   }
   
   if (!g_initialized) {
       return MAX30102_ERROR_INIT;
   }
   
   // 启动温度测量
   if (MAX30102_WriteReg(MAX30102_REG_TEMP_CONFIG, 0x01) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   // 等待测量完成
   MXC_Delay(MXC_DELAY_MSEC(100));
   
   // 读取温度数据
   uint8_t temp_int, temp_frac;
   if (MAX30102_ReadReg(MAX30102_REG_TEMP_INTR, &temp_int) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   if (MAX30102_ReadReg(MAX30102_REG_TEMP_FRAC, &temp_frac) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   *temperature = temp_int + (temp_frac * 0.0625f);
   MAX30102_LOG("[MAX30102] Temperature: %.2f°C\n", (double)*temperature);
   return MAX30102_OK;
}

// 改进的心率计算算法(基于信号处理和峰值检测)
max30102_error_t MAX30102_CalculateHeartRate(float *heart_rate, uint32_t *red_buffer, uint32_t *ir_buffer, uint16_t buffer_length)
{
   if (heart_rate == NULL || red_buffer == NULL || ir_buffer == NULL || buffer_length < 50) {
       return MAX30102_ERROR_PARAM;
   }
   
   // 使用IR信号进行心率计算(更稳定)
   uint32_t *signal = ir_buffer;
   
   // 1. 简单的移动平均滤波
   uint32_t filtered_buffer[100]; // 固定大小,足够大
   for (uint16_t i = 2; i < buffer_length - 2; i++) {
       filtered_buffer[i] = (signal[i-2] + signal[i-1] + signal[i] + signal[i+1] + signal[i+2]) / 5;
   }
   
   // 2. 计算动态阈值
   uint32_t max_val = 0, min_val = 0xFFFFFFFF;
   for (uint16_t i = 10; i < buffer_length - 10; i++) {
       if (filtered_buffer[i] > max_val) max_val = filtered_buffer[i];
       if (filtered_buffer[i] < min_val) min_val = filtered_buffer[i];
   }
   
   uint32_t threshold = min_val + (max_val - min_val) * 0.6f; // 60%阈值
   
   // 3. 峰值检测
   uint16_t peak_count = 0;
   uint32_t last_peak_time = 0;
   bool in_peak = false;
   uint32_t peak_intervals[20]; // 存储峰值间隔
   uint8_t interval_count = 0;
   
   for (uint16_t i = 10; i < buffer_length - 10; i++) {
       uint32_t current_val = filtered_buffer[i];
       
       if (!in_peak && current_val > threshold) {
           // 检测到上升沿
           in_peak = true;
       } else if (in_peak && current_val < threshold) {
           // 检测到下降沿,记录峰值
           in_peak = false;
           
           if (last_peak_time > 0) {
               uint32_t interval = i - last_peak_time;
               // 心率范围:30-200 BPM,对应间隔:30-100个样本(100Hz采样率)
               if (interval >= 30 && interval <= 100 && interval_count < 20) {
                   peak_intervals[interval_count] = interval;
                   interval_count++;
                   peak_count++;
               }
           }
           last_peak_time = i;
       }
   }
   
   // 4. 计算平均心率
   if (peak_count >= 2) {
       // 计算平均间隔
       uint32_t total_interval = 0;
       for (uint8_t i = 0; i < interval_count; i++) {
           total_interval += peak_intervals[i];
       }
       float avg_interval = (float)total_interval / interval_count;
       
       // 转换为BPM(100Hz采样率)
       *heart_rate = 6000.0f / avg_interval;
       
       // 限制在合理范围内
       if (*heart_rate < 30.0f) *heart_rate = 30.0f;
       if (*heart_rate > 200.0f) *heart_rate = 200.0f;
   } else {
       *heart_rate = 0.0f;
   }
   
   MAX30102_LOG("[MAX30102] Calculated heart rate: %.1f BPM (peaks: %d)\n", (double)*heart_rate, peak_count);
   return MAX30102_OK;
}

// 改进的SpO2计算算法
max30102_error_t MAX30102_CalculateSpO2(float *spo2, uint32_t *red_buffer, uint32_t *ir_buffer, uint16_t buffer_length)
{
   if (spo2 == NULL || red_buffer == NULL || ir_buffer == NULL || buffer_length < 50) {
       return MAX30102_ERROR_PARAM;
   }
   
   // 1. 计算AC和DC分量
   uint32_t red_dc = 0, ir_dc = 0;
   uint32_t red_ac_sum = 0, ir_ac_sum = 0;
   
   // 计算DC分量(平均值)
   for (uint16_t i = 0; i < buffer_length; i++) {
       red_dc += red_buffer[i];
       ir_dc += ir_buffer[i];
   }
   red_dc /= buffer_length;
   ir_dc /= buffer_length;
   
   // 计算AC分量(RMS)
   for (uint16_t i = 0; i < buffer_length; i++) {
       int32_t red_ac = (int32_t)red_buffer[i] - (int32_t)red_dc;
       int32_t ir_ac = (int32_t)ir_buffer[i] - (int32_t)ir_dc;
       
       red_ac_sum += red_ac * red_ac;
       ir_ac_sum += ir_ac * ir_ac;
   }
   
   float red_ac_rms = sqrtf((float)red_ac_sum / buffer_length);
   float ir_ac_rms = sqrtf((float)ir_ac_sum / buffer_length);
   
   // 2. 计算R值(红光AC/DC与红外光AC/DC的比值)
   float red_ratio = red_ac_rms / (float)red_dc;
   float ir_ratio = ir_ac_rms / (float)ir_dc;
   
   if (ir_ratio == 0.0f) {
       *spo2 = 0.0f;
       return MAX30102_ERROR_PARAM;
   }
   
   float R = red_ratio / ir_ratio;
   
   // 3. 使用改进的SpO2计算公式
   // 基于Beer-Lambert定律的简化版本
   float spo2_value = 110.0f - 25.0f * R;
   
   // 4. 应用经验修正
   if (R < 0.4f) {
       spo2_value = 100.0f - 15.0f * R;
   } else if (R > 1.0f) {
       spo2_value = 80.0f - 20.0f * (R - 1.0f);
   }
   
   // 5. 限制在合理范围内
   if (spo2_value < 70.0f) spo2_value = 70.0f;
   if (spo2_value > 100.0f) spo2_value = 100.0f;
   
   *spo2 = spo2_value;
   
   MAX30102_LOG("[MAX30102] Calculated SpO2: %.1f%% (R=%.3f)\n", (double)*spo2, (double)R);
   return MAX30102_OK;
}

// 信号质量评估
max30102_error_t MAX30102_AssessSignalQuality(float *quality, uint32_t *red_buffer, uint32_t *ir_buffer, uint16_t buffer_length)
{
   if (quality == NULL || red_buffer == NULL || ir_buffer == NULL || buffer_length < 10) {
       return MAX30102_ERROR_PARAM;
   }
   
   // 计算信号强度
   uint32_t red_sum = 0, ir_sum = 0;
   for (uint16_t i = 0; i < buffer_length; i++) {
       red_sum += red_buffer[i];
       ir_sum += ir_buffer[i];
   }
   
   float red_avg = (float)red_sum / buffer_length;
   float ir_avg = (float)ir_sum / buffer_length;
   
   // 计算信号变化率(AC分量)
   uint32_t red_variance = 0, ir_variance = 0;
   for (uint16_t i = 1; i < buffer_length; i++) {
       int32_t red_diff = (int32_t)red_buffer[i] - (int32_t)red_buffer[i-1];
       int32_t ir_diff = (int32_t)ir_buffer[i] - (int32_t)ir_buffer[i-1];
       
       red_variance += red_diff * red_diff;
       ir_variance += ir_diff * ir_diff;
   }
   
   float red_ac = sqrtf((float)red_variance / buffer_length);
   float ir_ac = sqrtf((float)ir_variance / buffer_length);
   
   // 计算信号质量分数 (0-100)
   float signal_strength = (red_avg + ir_avg) / 2.0f;
   float signal_variation = (red_ac + ir_ac) / 2.0f;
   
   float quality_score = 0.0f;
   
   // 信号强度评分 (0-40分)
   if (signal_strength > 50000) quality_score += 40.0f;
   else if (signal_strength > 30000) quality_score += 30.0f;
   else if (signal_strength > 10000) quality_score += 20.0f;
   else if (signal_strength > 5000) quality_score += 10.0f;
   
   // 信号变化评分 (0-40分)
   if (signal_variation > 1000 && signal_variation < 10000) quality_score += 40.0f;
   else if (signal_variation > 500 && signal_variation < 15000) quality_score += 30.0f;
   else if (signal_variation > 200 && signal_variation < 20000) quality_score += 20.0f;
   else if (signal_variation > 100) quality_score += 10.0f;
   
   // 信号稳定性评分 (0-20分)
   float stability = 100.0f - (signal_variation / signal_strength * 1000.0f);
   if (stability > 80.0f) quality_score += 20.0f;
   else if (stability > 60.0f) quality_score += 15.0f;
   else if (stability > 40.0f) quality_score += 10.0f;
   else if (stability > 20.0f) quality_score += 5.0f;
   
   if (quality_score > 100.0f) quality_score = 100.0f;
   if (quality_score < 0.0f) quality_score = 0.0f;
   
   *quality = quality_score;
   return MAX30102_OK;
}

// 计算心率和SpO2
max30102_error_t MAX30102_CalculateHRSpO2(max30102_hr_spo2_t *result, uint32_t *red_buffer, uint32_t *ir_buffer, uint16_t buffer_length)
{
   if (result == NULL) {
       return MAX30102_ERROR_PARAM;
   }
   
   result->valid = false;
   
   if (MAX30102_CalculateHeartRate(&result->heart_rate, red_buffer, ir_buffer, buffer_length) != MAX30102_OK) {
       return MAX30102_ERROR_PARAM;
   }
   
   if (MAX30102_CalculateSpO2(&result->spo2, red_buffer, ir_buffer, buffer_length) != MAX30102_OK) {
       return MAX30102_ERROR_PARAM;
   }
   
   // 更严格的数据验证
   result->valid = (result->heart_rate >= 50.0f && result->heart_rate <= 150.0f &&
                    result->spo2 >= 85.0f && result->spo2 <= 100.0f);
   
   return MAX30102_OK;
}

// 读取寄存器
max30102_error_t MAX30102_ReadRegister(uint8_t reg_addr, uint8_t *data)
{
   if (data == NULL) {
       return MAX30102_ERROR_PARAM;
   }
   
   return (MAX30102_ReadReg(reg_addr, data) == 0) ? MAX30102_OK : MAX30102_ERROR_I2C;
}

// 写入寄存器
max30102_error_t MAX30102_WriteRegister(uint8_t reg_addr, uint8_t data)
{
   return (MAX30102_WriteReg(reg_addr, data) == 0) ? MAX30102_OK : MAX30102_ERROR_I2C;
}

// 检查传感器状态
max30102_error_t MAX30102_CheckStatus(void)
{
   if (!g_initialized) {
       return MAX30102_ERROR_INIT;
   }
   
   // 读取模式配置寄存器
   uint8_t mode_config;
   if (MAX30102_ReadReg(MAX30102_REG_MODE_CONFIG, &mode_config) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   MAX30102_LOG("[MAX30102] Mode Config: 0x%02X\n", mode_config);
   
   // 检查是否处于工作模式
   if ((mode_config & 0x07) == 0) {
       MAX30102_LOG("[MAX30102] Sensor is in standby mode!\n");
       return MAX30102_ERROR_INIT;
   }
   
   return MAX30102_OK;
}

// 重置FIFO指针
max30102_error_t MAX30102_ResetFIFO(void)
{
   if (!g_initialized) {
       return MAX30102_ERROR_INIT;
   }
   
   MAX30102_LOG("[MAX30102] Resetting FIFO pointers...\n");
   
   // 重置FIFO指针
   if (MAX30102_WriteReg(MAX30102_REG_FIFO_WR_PTR, 0x00) != 0) {
       return MAX30102_ERROR_I2C;
   }
   if (MAX30102_WriteReg(MAX30102_REG_FIFO_RD_PTR, 0x00) != 0) {
       return MAX30102_ERROR_I2C;
   }
   if (MAX30102_WriteReg(MAX30102_REG_OVF_COUNTER, 0x00) != 0) {
       return MAX30102_ERROR_I2C;
   }
   
   MAX30102_LOG("[MAX30102] FIFO pointers reset successfully\n");
   return MAX30102_OK;
}

// 获取错误字符串
const char* MAX30102_GetErrorString(max30102_error_t error)
{
   switch (error) {
       case MAX30102_OK:
           return "OK";
       case MAX30102_ERROR_I2C:
           return "I2C communication error";
       case MAX30102_ERROR_INIT:
           return "Initialization error";
       case MAX30102_ERROR_PARAM:
           return "Invalid parameter";
       case MAX30102_ERROR_TIMEOUT:
           return "Timeout error";
       case MAX30102_ERROR_FIFO_EMPTY:
           return "FIFO empty";
       default:
           return "Unknown error";
   }
}

.h的相关配置

#ifndef MAX30102_H
#define MAX30102_H

#include <stdint.h>
#include <stdbool.h>

// MAX30102 I2C地址
#define MAX30102_I2C_ADDR 0x57

// MAX30102寄存器地址
#define MAX30102_REG_INTR_STATUS_1    0x00
#define MAX30102_REG_INTR_STATUS_2    0x01
#define MAX30102_REG_INTR_ENABLE_1    0x02
#define MAX30102_REG_INTR_ENABLE_2    0x03
#define MAX30102_REG_FIFO_WR_PTR      0x04
#define MAX30102_REG_OVF_COUNTER      0x05
#define MAX30102_REG_FIFO_RD_PTR      0x06
#define MAX30102_REG_FIFO_DATA        0x07
#define MAX30102_REG_FIFO_CONFIG      0x08
#define MAX30102_REG_MODE_CONFIG      0x09
#define MAX30102_REG_SPO2_CONFIG      0x0A
#define MAX30102_REG_LED1_PA          0x0C
#define MAX30102_REG_LED2_PA          0x0D
#define MAX30102_REG_PILOT_PA         0x10
#define MAX30102_REG_MULTI_LED_CTRL1  0x11
#define MAX30102_REG_MULTI_LED_CTRL2  0x12
#define MAX30102_REG_TEMP_INTR        0x1F
#define MAX30102_REG_TEMP_FRAC        0x20
#define MAX30102_REG_TEMP_CONFIG      0x21
#define MAX30102_REG_PROX_INT_THRESH  0x30
#define MAX30102_REG_REV_ID           0xFE
#define MAX30102_REG_PART_ID          0xFF

// 模式配置
typedef enum {
   MAX30102_MODE_HEART_RATE = 0x02,
   MAX30102_MODE_SPO2 = 0x03,
   MAX30102_MODE_MULTI_LED = 0x07
} max30102_mode_t;

// LED功率设置
typedef enum {
   MAX30102_LED_PA_0MA = 0x00,
   MAX30102_LED_PA_4_4MA = 0x01,
   MAX30102_LED_PA_7_6MA = 0x02,
   MAX30102_LED_PA_11MA = 0x03,
   MAX30102_LED_PA_14_2MA = 0x04,
   MAX30102_LED_PA_17_4MA = 0x05,
   MAX30102_LED_PA_20_8MA = 0x06,
   MAX30102_LED_PA_24MA = 0x07,
   MAX30102_LED_PA_27_1MA = 0x08,
   MAX30102_LED_PA_30_6MA = 0x09,
   MAX30102_LED_PA_33_8MA = 0x0A,
   MAX30102_LED_PA_37MA = 0x0B,
   MAX30102_LED_PA_40_2MA = 0x0C,
   MAX30102_LED_PA_43_6MA = 0x0D,
   MAX30102_LED_PA_46_8MA = 0x0E,
   MAX30102_LED_PA_50MA = 0x0F
} max30102_led_pa_t;

// 采样率设置
typedef enum {
   MAX30102_SAMPRATE_50HZ = 0x00,
   MAX30102_SAMPRATE_100HZ = 0x01,
   MAX30102_SAMPRATE_200HZ = 0x02,
   MAX30102_SAMPRATE_400HZ = 0x03,
   MAX30102_SAMPRATE_800HZ = 0x04,
   MAX30102_SAMPRATE_1000HZ = 0x05,
   MAX30102_SAMPRATE_1600HZ = 0x06,
   MAX30102_SAMPRATE_3200HZ = 0x07
} max30102_samprate_t;

// LED脉冲宽度
typedef enum {
   MAX30102_PULSE_WIDTH_69US = 0x00,
   MAX30102_PULSE_WIDTH_118US = 0x01,
   MAX30102_PULSE_WIDTH_215US = 0x02,
   MAX30102_PULSE_WIDTH_411US = 0x03
} max30102_pulse_width_t;

// ADC范围
typedef enum {
   MAX30102_ADC_RANGE_2048 = 0x00,
   MAX30102_ADC_RANGE_4096 = 0x01,
   MAX30102_ADC_RANGE_8192 = 0x02,
   MAX30102_ADC_RANGE_16384 = 0x03
} max30102_adc_range_t;

// 错误代码
typedef enum {
   MAX30102_OK = 0,
   MAX30102_ERROR_I2C = -1,
   MAX30102_ERROR_INIT = -2,
   MAX30102_ERROR_PARAM = -3,
   MAX30102_ERROR_TIMEOUT = -4,
   MAX30102_ERROR_FIFO_EMPTY = -5
} max30102_error_t;

// 传感器数据结构
typedef struct {
   uint32_t red;
   uint32_t ir;
   uint32_t green;
} max30102_sample_t;

// 心率血氧数据
typedef struct {
   float heart_rate;
   float spo2;
   bool valid;
} max30102_hr_spo2_t;

#ifdef __cplusplus
extern "C" {
#endif

// 核心功能函数
max30102_error_t MAX30102_Init(void);
max30102_error_t MAX30102_Deinit(void);
max30102_error_t MAX30102_Reset(void);
max30102_error_t MAX30102_ReadPartID(uint8_t *part_id);

// 配置函数
max30102_error_t MAX30102_SetMode(max30102_mode_t mode);
max30102_error_t MAX30102_SetLEDPulseAmplitude(max30102_led_pa_t red_pa, max30102_led_pa_t ir_pa);
max30102_error_t MAX30102_SetSampleRate(max30102_samprate_t sample_rate);
max30102_error_t MAX30102_SetPulseWidth(max30102_pulse_width_t pulse_width);
max30102_error_t MAX30102_SetADCRange(max30102_adc_range_t adc_range);

// 数据读取函数
max30102_error_t MAX30102_ReadFIFO(max30102_sample_t *samples, uint8_t *num_samples);
max30102_error_t MAX30102_GetFIFOWritePtr(uint8_t *write_ptr);
max30102_error_t MAX30102_GetFIFOReadPtr(uint8_t *read_ptr);
max30102_error_t MAX30102_GetFIFOOverflowCounter(uint8_t *overflow_count);

// 中断控制
max30102_error_t MAX30102_EnableInterrupts(uint8_t int1_enable, uint8_t int2_enable);
max30102_error_t MAX30102_ReadInterruptStatus(uint8_t *int1_status, uint8_t *int2_status);
max30102_error_t MAX30102_ClearInterrupts(void);

// 算法函数
max30102_error_t MAX30102_CalculateHeartRate(float *heart_rate, uint32_t *red_buffer, uint32_t *ir_buffer, uint16_t buffer_length);
max30102_error_t MAX30102_CalculateSpO2(float *spo2, uint32_t *red_buffer, uint32_t *ir_buffer, uint16_t buffer_length);
max30102_error_t MAX30102_CalculateHRSpO2(max30102_hr_spo2_t *result, uint32_t *red_buffer, uint32_t *ir_buffer, uint16_t buffer_length);
max30102_error_t MAX30102_AssessSignalQuality(float *quality, uint32_t *red_buffer, uint32_t *ir_buffer, uint16_t buffer_length);

// 工具函数
max30102_error_t MAX30102_ReadTemperature(float *temperature);
max30102_error_t MAX30102_ReadRegister(uint8_t reg_addr, uint8_t *data);
max30102_error_t MAX30102_WriteRegister(uint8_t reg_addr, uint8_t data);
max30102_error_t MAX30102_CheckStatus(void);
max30102_error_t MAX30102_ResetFIFO(void);
const char* MAX30102_GetErrorString(max30102_error_t error);

#ifdef __cplusplus
}
#endif

#endif // MAX30102_H

读数据将数据通过串口打印出来

#include <stdio.h>  
#include "board.h"  
#include "mxc_device.h"  
#include "mxc_delay.h"  
#include "i2c.h"  
#include "max30102.h"

// 函数声明
static int init_hardware(void);
static void print_sensor_data(void);
// static void handle_error(max30102_error_t error, const char* function);

// 数据缓冲区
#define BUFFER_SIZE 100
static uint32_t red_buffer[BUFFER_SIZE];
static uint32_t ir_buffer[BUFFER_SIZE];
static uint16_t buffer_index = 0;

int main(void)  
{  
   printf("MAX78000 + MAX30102 Heart Rate & SpO2 Monitor\n");
   printf("==============================================\n");

   // 初始化硬件
   if (init_hardware() != 0) {
       printf("Hardware initialization failed!\n");
       return -1;
   }

   printf("\nPlace your finger on the MAX30102 sensor...\n");
   printf("Collecting data for analysis...\n\n");
   
   // 主循环 - 改进版本
   uint32_t loop_count = 0;
   uint32_t last_print_time = 0;
   uint32_t consecutive_valid_reads = 0;
   max30102_sample_t samples[1]; // 每次读取一个样本
   uint8_t num_samples = 1;
   
   printf("\n=== 开始数据采集 ===\n");
   printf("请将手指稳定放置在传感器上,保持静止...\n\n");
   
   while (1)  
   {  
       // 读取MAX30102数据
       max30102_error_t error = MAX30102_ReadFIFO(samples, &num_samples);
       if (error == MAX30102_OK && num_samples > 0) {
           // 数据质量检查
           if (samples[0].red > 1000 && samples[0].ir > 1000) { // 基本数据有效性检查
               // 将数据存储到缓冲区
               if (buffer_index < BUFFER_SIZE) {
                   red_buffer[buffer_index] = samples[0].red;
                   ir_buffer[buffer_index] = samples[0].ir;
                   buffer_index++;
                   consecutive_valid_reads++;
               }
               
               // 当缓冲区满时,计算心率和SpO2
               if (buffer_index >= BUFFER_SIZE) {
                   max30102_hr_spo2_t result;
                   float signal_quality;
                   
                   if (MAX30102_CalculateHRSpO2(&result, red_buffer, ir_buffer, BUFFER_SIZE) == MAX30102_OK &&
                       MAX30102_AssessSignalQuality(&signal_quality, red_buffer, ir_buffer, BUFFER_SIZE) == MAX30102_OK) {
                       
                       // 控制打印频率 - 每2秒打印一次
                       if (loop_count - last_print_time >= 200) { // 200 * 10ms = 2秒
                           print_sensor_data();
                           
                           if (result.valid && signal_quality > 60.0f) {
                               printf("✓ 心率: %.1f BPM, 血氧: %.1f%%\n",
                                      (double)result.heart_rate, (double)result.spo2);
                               printf("信号质量: %.1f%% (连续有效读数: %lu)\n\n",
                                      (double)signal_quality, consecutive_valid_reads);
                           } else {
                               printf("✗ 数据质量不佳 - 请调整手指位置\n");
                               printf("  心率: %.1f BPM, 血氧: %.1f%%\n",
                                      (double)result.heart_rate, (double)result.spo2);
                               printf("  信号质量: %.1f%% (需要 > 60%%)\n", (double)signal_quality);
                               printf("  建议: 保持手指稳定,避免移动,确保完全覆盖传感器\n\n");
                           }
                           last_print_time = loop_count;
                       }
                   }
                   
                   // 重置缓冲区
                   buffer_index = 0;
               }
           } else {
               consecutive_valid_reads = 0; // 重置连续有效读数计数
           }
       } else if (error == MAX30102_ERROR_FIFO_EMPTY) {
           // FIFO为空,继续等待
       } else {
           printf("MAX30102 读取错误: %s\n", MAX30102_GetErrorString(error));
       }
       
       // 每500次循环显示一次状态(5秒)
       if (++loop_count % 500 == 0) {
           printf("状态: 循环 %lu, 缓冲区 %d/%d 样本, 连续有效读数: %lu\n",
                  loop_count, buffer_index, BUFFER_SIZE, consecutive_valid_reads);
       }
       
       MXC_Delay(MXC_DELAY_MSEC(10)); // 10ms延迟
   }  

   return 0;  
}

// 初始化硬件
static int init_hardware(void)
{
   printf("Initializing hardware...\n");
   
   // 初始化I2C
   int res = MXC_I2C_Init(MXC_I2C1, 1, 0);  
   if (res != 0) {
       printf("I2C Init failed: %d\n", res);
       return -1;
   }
   printf("✓ I2C Init: OK\n");
   
   MXC_I2C_SetFrequency(MXC_I2C1, 400000);  
   printf("✓ I2C Frequency: %d Hz\n", MXC_I2C_GetFrequency(MXC_I2C1));  
   
   // 初始化MAX30102
   max30102_error_t error = MAX30102_Init();
   if (error != MAX30102_OK) {
       printf("✗ MAX30102 Init failed: %s\n", MAX30102_GetErrorString(error));
       return -1;
   }
   printf("✓ MAX30102 Init: OK\n");
   
   // 读取Part ID验证
   uint8_t part_id;
   if (MAX30102_ReadPartID(&part_id) == MAX30102_OK) {
       printf("✓ MAX30102 Part ID: 0x%02X\n", part_id);
   }
   
   
   printf("\n✓ Hardware initialization completed successfully!\n");
   return 0;
}

// 打印传感器数据
static void print_sensor_data(void)
{
   printf("\n--- Sensor Data Analysis ---\n");
   printf("Buffer Status: %d/%d samples collected\n", buffer_index, BUFFER_SIZE);
   
   if (buffer_index < BUFFER_SIZE) {
       printf("Status: Collecting data... Please keep finger on sensor\n");
   } else {
       printf("Status: Processing data... Calculating HR & SpO2\n");
   }
   
   // 显示原始数据(最后几个样本)
   if (buffer_index > 0) {
       uint16_t last_index = (buffer_index > 0) ? buffer_index - 1 : 0;
       printf("Latest Sample - Red: %lu, IR: %lu\n",
              red_buffer[last_index] >> 4, ir_buffer[last_index] >> 4);
   }
   
   printf("----------------------------\n");
}

image-20251003122131629

实物图




共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]