其中的驱动代码:
根据驱动代码和原理图:
这里是.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 = ®_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 = ®_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");
}
实物图