Justice_Gao 发表于 2017-9-21 21:49

MAX32630FTHR设计笔记(11):血氧传感器MAX30102采集人体血氧浓度和心率(C语言版...

本帖最后由 Justice_Gao 于 2017-9-21 21:55 编辑

max30102的原理我就不解释了,现在网上能够下载或者共享的MAX30102程序源代码,全部是基于mbed的,编程语言为C++类型,如果使用KEIL或者IAR调试这些基于mbed导出后的程序,非常不方便,也不能很好的将MAX30102驱动程序应用到基于C语言的51单片机、STM32单片机,甚至用IAR和KEIL等C语言开发的平台,不能很好将MAX30102与自己的程序进行结合,现在,福利来了,给你共享一下,基于KEIL C语言的MAX30102驱动,以及采集人体血氧浓度和心率的测试程序。(1)首先来看,网络上共享的基于mbed的C++类型的max30102驱动程序,第一个algorithm.cpp为血氧和心率的计算算法,可以直接调用过了,无需做任何改变,只需将文件改为algorithm.c即可。

第二个main.cpp文件改成一下代码


/**
* @file    main.c
* @brief   低功耗设计,程序实现舒眠科技智眠传感带信号采集和呼吸,心跳提取功能,实现和上位设备的通信功能
*/
//作者:Justice
//版本:V1.0.0
//日期:2017-05-25
//工具:Keil MDK 5.23
//修改日期:2017-06-28
//修改内容:不修改底层源代码,把需要改的函数放在相应的自定义文件中
//修改日期:2017-06-29
//修改内容:增加了BootLoader程序,支持IAP升级
/***** Includes *****/

#include "Com.h"

#define REPORTING_PERIOD_MS 1000
const uint8_t Test_Buff = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A};

uint32_t aun_ir_buffer; //IR LED sensor data
int32_t n_ir_buffer_length;    //data length
uint32_t aun_red_buffer;    //Red LED sensor data
int32_t n_sp02; //SPO2 value
int8_t ch_spo2_valid;   //indicator to show if the SP02 calculation is valid
int32_t n_heart_rate;   //heart rate value
int8_tch_hr_valid;    //indicator to show if the heart rate calculation is valid
uint8_t uch_dummy;
#define MAX_BRIGHTNESS 255
#define false 0
#define true 1
int main(void)
{
      uint32_t un_min, un_max, un_prev_data;//variables to calculate the on-board LED brightness that reflects the heartbeats
      int i;
      int32_t n_brightness;
      float f_temp;
      USART2_Configuration(115200);
      I2CM_Init(MAX14690_I2CM, &max14690_sys_cfg, I2CM_SPEED_100KHZ);
      I2CM_Init(MXC_I2CM1, &max30102_sys_cfg, I2CM_SPEED_100KHZ);
      //Device_Hardware_Init();
      maxim_max30102_reset(); //resets the MAX30102

            //read and clear status register
                maxim_max30102_read_reg(0,&uch_dummy);
                maxim_max30102_init();//initializes the MAX30102
                n_brightness=0;
    un_min=0x3FFFF;
    un_max=0;

    n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
   
    //read the first 500 samples, and determine the signal range
    for(i=0;i<n_ir_buffer_length;i++)
    {
      //while(INT.read()==1);   //wait until the interrupt pin asserts
      
      maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));//read from MAX30102 FIFO
            
      if(un_min>aun_red_buffer)
            un_min=aun_red_buffer;    //update signal min
      if(un_max<aun_red_buffer)
            un_max=aun_red_buffer;    //update signal max
      printf("red=");
      printf("%i", aun_red_buffer);
      printf(", ir=");
      printf("%i\n\r", aun_ir_buffer);
    }
    un_prev_data=aun_red_buffer;


    //calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
    maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);

    //Continuously taking samples from MAX30102.Heart rate and SpO2 are calculated every 1 second
    while(1)
    {
      i=0;
      un_min=0x3FFFF;//???
      un_max=0;

      //dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
      for(i=100;i<500;i++)
      {
            aun_red_buffer=aun_red_buffer;
            aun_ir_buffer=aun_ir_buffer;

            //update the signal min and max
            if(un_min>aun_red_buffer)
            un_min=aun_red_buffer;
            if(un_max<aun_red_buffer)
            un_max=aun_red_buffer;
      }

      //take 100 sets of samples before calculating the heart rate.
      for(i=400;i<500;i++)
      {
            un_prev_data=aun_red_buffer;
         // while(INT.read()==1);
            maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));

            if(aun_red_buffer>un_prev_data)//just to determine the brightness of LED according to the deviation of adjacent two AD data
            {
                f_temp=aun_red_buffer-un_prev_data;
                f_temp/=(un_max-un_min);
                f_temp*=MAX_BRIGHTNESS;
                n_brightness-=(int)f_temp;
                if(n_brightness<0)
                  n_brightness=0;
            }
            else
            {
                f_temp=un_prev_data-aun_red_buffer;
                f_temp/=(un_max-un_min);
                f_temp*=MAX_BRIGHTNESS;
                n_brightness+=(int)f_temp;
                if(n_brightness>MAX_BRIGHTNESS)
                  n_brightness=MAX_BRIGHTNESS;
            }

            //led.write(1-(float)n_brightness/256);//pwm control led brightness

            //send samples and calculation result to terminal program through UART
            printf("red=");
            printf("%i", aun_red_buffer);
            printf(", ir=");
            printf("%i", aun_ir_buffer);
            printf(", HR=%i, ", n_heart_rate);
            printf("HRvalid=%i, ", ch_hr_valid);
            printf("SpO2=%i, ", n_sp02);
            printf("SPO2Valid=%i\n\r", ch_spo2_valid);
      }
      maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
    }

}


第三个文件max30102.cpp是重点,先给出max30102.cpp的源代码:
/** \file max30102.cpp ******************************************************
*
* Project: MAXREFDES117#
* Filename: max30102.cpp
* Description: This module is an embedded controller driver for the MAX30102
*
*
* --------------------------------------------------------------------
*
* This code follows the following naming conventions:
*
* char            ch_pmod_value
* char (array)      s_pmod_s_string
* float             f_pmod_value
* int32_t         n_pmod_value
* int32_t (array)   an_pmod_value
* int16_t         w_pmod_value
* int16_t (array)   aw_pmod_value
* uint16_t          uw_pmod_value
* uint16_t (array)auw_pmod_value
* uint8_t         uch_pmod_value
* uint8_t (array)   auch_pmod_buffer
* uint32_t          un_pmod_value
* int32_t *         pn_pmod_value
*
* ------------------------------------------------------------------------- */
/*******************************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*******************************************************************************
*/
#include "mbed.h"
#include "MAX30102.h"

I2C i2c(P3_4, P3_5);

bool maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)
/**
* \brief      Write a value to a MAX30102 register
* \par          Details
*               This function writes a value to a MAX30102 register
*
* \param    uch_addr    - register address
* \param    uch_data    - register data
*
* \retval       true on success
*/
{
char ach_i2c_data;
ach_i2c_data=uch_addr;
ach_i2c_data=uch_data;

if(i2c.write(I2C_WRITE_ADDR, ach_i2c_data, 2, false)==0)
    return true;
else
    return false;
}

bool maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)
/**
* \brief      Read a MAX30102 register
* \par          Details
*               This function reads a MAX30102 register
*
* \param    uch_addr    - register address
* \param   puch_data    - pointer that stores the register data
*
* \retval       true on success
*/
{
char ch_i2c_data;
ch_i2c_data=uch_addr;
if(i2c.write(I2C_WRITE_ADDR, &ch_i2c_data, 1, true)!=0)
    return false;
if(i2c.read(I2C_READ_ADDR, &ch_i2c_data, 1, false)==0)
{
    *puch_data=(uint8_t) ch_i2c_data;
    return true;
}
else
    return false;
}

bool maxim_max30102_init()
/**
* \brief      Initialize the MAX30102
* \par          Details
*               This function initializes the MAX30102
*
* \param      None
*
* \retval       true on success
*/
{
if(!maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)) // INTR setting
    return false;
if(!maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x00))
    return false;
if(!maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00))//FIFO_WR_PTR
    return false;
if(!maxim_max30102_write_reg(REG_OVF_COUNTER,0x00))//OVF_COUNTER
    return false;
if(!maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00))//FIFO_RD_PTR
    return false;
if(!maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f))//sample avg = 1, fifo rollover=false, fifo almost full = 17
    return false;
if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x03))   //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
    return false;
if(!maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27))// SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)
    return false;

if(!maxim_max30102_write_reg(REG_LED1_PA,0x24))   //Choose value for ~ 7mA for LED1
    return false;
if(!maxim_max30102_write_reg(REG_LED2_PA,0x24))   // Choose value for ~ 7mA for LED2
    return false;
if(!maxim_max30102_write_reg(REG_PILOT_PA,0x7f))   // Choose value for ~ 25mA for Pilot LED
    return false;
return true;
}

bool maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
/**
* \brief      Read a set of samples from the MAX30102 FIFO register
* \par          Details
*               This function reads a set of samples from the MAX30102 FIFO register
*
* \param   *pun_red_led   - pointer that stores the red LED reading data
* \param   *pun_ir_led    - pointer that stores the IR LED reading data
*
* \retval       true on success
*/
{
uint32_t un_temp;
unsigned char uch_temp;
*pun_red_led=0;
*pun_ir_led=0;
char ach_i2c_data;

//read and clear status register
maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);

ach_i2c_data=REG_FIFO_DATA;
if(i2c.write(I2C_WRITE_ADDR, ach_i2c_data, 1, true)!=0)
    return false;
if(i2c.read(I2C_READ_ADDR, ach_i2c_data, 6, false)!=0)
{
    return false;
}
un_temp=(unsigned char) ach_i2c_data;
un_temp<<=16;
*pun_red_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data;
un_temp<<=8;
*pun_red_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data;
*pun_red_led+=un_temp;

un_temp=(unsigned char) ach_i2c_data;
un_temp<<=16;
*pun_ir_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data;
un_temp<<=8;
*pun_ir_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data;
*pun_ir_led+=un_temp;
*pun_red_led&=0x03FFFF;//Mask MSB
*pun_ir_led&=0x03FFFF;//Mask MSB


return true;
}

bool maxim_max30102_reset()
/**
* \brief      Reset the MAX30102
* \par          Details
*               This function resets the MAX30102
*
* \param      None
*
* \retval       true on success
*/
{
    if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x40))
      return false;
    else
      return true;   
}

移植改编后的程序为:
/***********************************************
@from Justice_Gao
***********************************************/

#include "Com.h"

/** \file max30102.cpp ******************************************************
*
* Project: MAXREFDES117#
* Filename: max30102.cpp
* Description: This module is an embedded controller driver for the MAX30102
*
*
* --------------------------------------------------------------------
*
* This code follows the following naming conventions:
*
* char            ch_pmod_value
* char (array)      s_pmod_s_string
* float             f_pmod_value
* int32_t         n_pmod_value
* int32_t (array)   an_pmod_value
* int16_t         w_pmod_value
* int16_t (array)   aw_pmod_value
* uint16_t          uw_pmod_value
* uint16_t (array)auw_pmod_value
* uint8_t         uch_pmod_value
* uint8_t (array)   auch_pmod_buffer
* uint32_t          un_pmod_value
* int32_t *         pn_pmod_value
*
* ------------------------------------------------------------------------- */
/*******************************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*******************************************************************************
*/
#include "MAX30100.h"
#include "i2cm.h"
#define MBED_ASSERT(expr) ((void)0)
// write - Master Transmitter Mode
void lock()
{
}
void unlock()
{
}
int I2C_write(int address, const char* data, int length, uint8_t repeated)
{
    lock();
   // aquire();

    int stop = (repeated) ? 0 : 1;
    int written = i2c_write(MXC_I2CM1, address, data, length, stop);

    unlock();
    return length != written;
}
// read - Master Reciever Mode
int I2C_read(int address, char* data, int length, uint8_t repeated) {
    lock();
   // aquire();

    int stop = (repeated) ? 0 : 1;
    int read = i2c_read(MXC_I2CM1, address, data, length, stop);

    unlock();
    return length != read;
}
//******************************************************************************
int i2c_read(mxc_i2cm_regs_t *i2cm, int address, char *data, int length, int stop)
{
    MBED_ASSERT(stop != 0);
    return I2CM_Read(i2cm, address >> 1, NULL, 0, (uint8_t *)data, length);
}
//******************************************************************************
int i2c_write(mxc_i2cm_regs_t *i2cm, int address, const char *data, int length, int stop)
{
    mxc_i2cm_fifo_regs_t *fifo = MXC_I2CM1_FIFO;

    if (stop) {
      return I2CM_Write(i2cm, address >> 1, NULL, 0, (uint8_t *)data, length);
    }

    i2cm->inten = 0;
    i2cm->intfl = i2cm->intfl;
    if (I2CM_Tx(i2cm, fifo, address >> 1, (uint8_t *)data, length, 0) == E_NO_ERROR) {
      return length;
    } else {
      return -1;
    }
}
//I2C i2c(I2C_SDA, I2C_SCL);//SDA-PB9,SCL-PB8


uint8_t maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)
/**
* \brief      Write a value to a MAX30102 register
* \par          Details
*               This function writes a value to a MAX30102 register
*
* \param    uch_addr    - register address
* \param    uch_data    - register data
*
* \retval       true on success
*/
{
char ach_i2c_data;
ach_i2c_data=uch_addr;
ach_i2c_data=uch_data;

if(I2C_write(I2C_WRITE_ADDR, ach_i2c_data, 2, 0)==0)
    return 1;
else
    return 0;
}

uint8_t maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)
/**
* \brief      Read a MAX30102 register
* \par          Details
*               This function reads a MAX30102 register
*
* \param    uch_addr    - register address
* \param   puch_data    - pointer that stores the register data
*
* \retval       true on success
*/
{
char ch_i2c_data;
ch_i2c_data=uch_addr;
if(I2C_write(I2C_WRITE_ADDR, &ch_i2c_data, 1, 1)!=0)
    return 0;
if(I2C_read(I2C_READ_ADDR, &ch_i2c_data, 1, 0)==0)
{
    *puch_data=(uint8_t) ch_i2c_data;
    return 1;
}
else
    return 0;
}

uint8_t maxim_max30102_init()
/**
* \brief      Initialize the MAX30102
* \par          Details
*               This function initializes the MAX30102
*
* \param      None
*
* \retval       true on success
*/
{
if(!maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)) // INTR setting
    return 0;
if(!maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x00))
    return 0;
if(!maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00))//FIFO_WR_PTR
    return 0;
if(!maxim_max30102_write_reg(REG_OVF_COUNTER,0x00))//OVF_COUNTER
    return 0;
if(!maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00))//FIFO_RD_PTR
    return 0;
if(!maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f))//sample avg = 1, fifo rollover=false, fifo almost full = 17
    return 0;
if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x03))   //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
    return 0;
if(!maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27))// SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)
    return 0;

if(!maxim_max30102_write_reg(REG_LED1_PA,0x24))   //Choose value for ~ 7mA for LED1
    return 0;
if(!maxim_max30102_write_reg(REG_LED2_PA,0x24))   // Choose value for ~ 7mA for LED2
    return 0;
if(!maxim_max30102_write_reg(REG_PILOT_PA,0x7f))   // Choose value for ~ 25mA for Pilot LED
    return 0;
return 1;
}

uint8_t maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
/**
* \brief      Read a set of samples from the MAX30102 FIFO register
* \par          Details
*               This function reads a set of samples from the MAX30102 FIFO register
*
* \param   *pun_red_led   - pointer that stores the red LED reading data
* \param   *pun_ir_led    - pointer that stores the IR LED reading data
*
* \retval       true on success
*/
{
uint32_t un_temp;
unsigned char uch_temp;
*pun_red_led=0;
*pun_ir_led=0;
char ach_i2c_data;

//read and clear status register
maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);

ach_i2c_data=REG_FIFO_DATA;
if(I2C_write(I2C_WRITE_ADDR, ach_i2c_data, 1, 1)!=0)
    return 0;
if(I2C_read(I2C_READ_ADDR, ach_i2c_data, 6, 0)!=0)
{
    return 0;
}
un_temp=(unsigned char) ach_i2c_data;
un_temp<<=16;
*pun_red_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data;
un_temp<<=8;
*pun_red_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data;
*pun_red_led+=un_temp;

un_temp=(unsigned char) ach_i2c_data;
un_temp<<=16;
*pun_ir_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data;
un_temp<<=8;
*pun_ir_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data;
*pun_ir_led+=un_temp;
*pun_red_led&=0x03FFFF;//Mask MSB
*pun_ir_led&=0x03FFFF;//Mask MSB


return 1;
}

uint8_t maxim_max30102_reset()
/**
* \brief      Reset the MAX30102
* \par          Details
*               This function resets the MAX30102
*
* \param      None
*
* \retval       true on success
*/
{
    if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x40))
      return 0;
    else
      return 1;   
}
移植过程中,其实难点在于将i2c.write函数和i2c.read函数转换为代码中的I2C_write(int address, const char* data, int length, uint8_t repeated) 和I2C_read(int address, char* data, int length, uint8_t repeated),因为被移植的代码中的读写函数是调用mbed平台的API,凭借我的聪明才智,我改写处出lock(),unlock(),I2C_write,I2C_read,i2c_read,i2c_write等关键函数,解决了这几个函数,程序就可以运行了

第4个文件是max14690的驱动文件,可以借鉴我的另外一篇帖子MAX32630FTHR设计笔记(1):流水灯(GPIO输出配置)及I2C驱动MAX14690,也是基于C语言编写的,需要注意的是,我分享的所有帖子都是用KEIL C语言编写的

最后给出测试图片吧,视频就不拍了

第一图为max30102模块测到的心率为64,血氧浓度为96,第二图为专业标准设备测得的心率为64,血氧浓度为97,可以说非常准确。


早起的 发表于 2017-9-23 18:01

楼主,能发一份工程吗,邮箱:3139927868@qq.com,万分感谢

Justice_Gao 发表于 2017-9-23 18:46

早起的 发表于 2017-9-23 18:01
楼主,能发一份工程吗,邮箱:3139927868@qq.com,万分感谢

发你,这可是呕心沥血的作品,你先发给ipad过来吧 哈哈

早起的 发表于 2017-9-23 23:07

楼主帮忙看看输出不是很稳定,是啥原因,谢谢了Ipad已备好哈

Justice_Gao 发表于 2017-9-23 23:23

早起的 发表于 2017-9-23 23:07
楼主帮忙看看输出不是很稳定,是啥原因,谢谢了Ipad已备好哈

先寄过来 哈哈

chenweigang 发表于 2018-3-9 15:39

Justice_Gao 发表于 2017-9-23 23:23
先寄过来 哈哈

楼主的ipad拿到了吗,程序可以开源了:congratulate:

一株草 发表于 2018-3-13 14:35

路过看看

懂你的人 发表于 2018-3-19 19:41

楼主能麻烦发一份心率和血氧计算算法吗   不知道我现在手里的算法对不对谢谢楼主了

补充内容 (2018-4-2 12:35):
楼主我用的是和你一样的测量算法,现在测量结果出来饱和度是正确的,但是心率结果一会维持一个数值,过一会又发生变化,请问你的也是这种情况吗?还是一直稳定在一个数值?

补充内容 (2018-4-2 12:35):
楼主我用的是和你一样的测量算法,现在测量结果出来饱和度是正确的,但是心率结果一会维持一个数值,过一会又发生变化,请问你的也是这种情况吗?还是一直稳定在一个数值?

qinyu10 发表于 2018-4-15 19:13

楼主,可以给我一份文件么,最近电设做这个题目,一直没有头绪
1083557165@qq.com

christopher007 发表于 2018-8-25 13:50

楼主我的q2649558793,可以加上交流一下吗!

time_opp 发表于 2019-2-13 18:41

请问Com.h文件在哪找的?

Justice_Gao 发表于 2019-2-14 08:46

time_opp 发表于 2019-2-13 18:41
请问Com.h文件在哪找的?

自己编写的

小西瓜213 发表于 2019-3-16 22:48

大佬,能发一份工程吗,邮箱:1536760015@qq.com,万分感谢

加油加油加加油 发表于 2019-3-22 15:08

楼主,跪求一份工程,毕设因为这个模块卡了很久:Cry:,万分感谢!!!
邮箱:978460447@qq.com

TANTINGZUIBANG 发表于 2019-4-14 09:49

楼主可以发一下工程文件吗?邮箱1197421427@qq.com 万分感谢!

TANTINGZUIBANG 发表于 2019-4-14 10:55

早起的 发表于 2017-9-23 23:07
楼主帮忙看看输出不是很稳定,是啥原因,谢谢了Ipad已备好哈

你好,请问你对这个压缩包里的代码进行了改动吗?我从串口输出的数据是乱码

zhuyebb 发表于 2019-4-14 15:15

玲66123 发表于 2019-4-17 17:32

楼主,跪求一份工程,万分感谢!!!
邮箱:2366299515@qq.com

嘚唔杜 发表于 2019-7-1 17:02

<p>楼主&nbsp; 能否加个qq:1148543046&nbsp; 想请教</p>

zhw625 发表于 2019-8-3 16:20

<p>我用nrf53832能接收到MAX30102心率血氧数据后就没搞了,不知楼主研究到什么程度了</p>
页: [1] 2
查看完整版本: MAX32630FTHR设计笔记(11):血氧传感器MAX30102采集人体血氧浓度和心率(C语言版...