社区导航

 

搜索
查看: 13939|回复: 23

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

  [复制链接]

113

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2017-9-21 21:49 | 显示全部楼层 |阅读模式
本帖最后由 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即可。
QQ图片20170920094626.png

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


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

  14. #include "Com.h"

  15. #define REPORTING_PERIOD_MS 1000
  16. const uint8_t Test_Buff[10] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A};

  17. uint32_t aun_ir_buffer[500]; //IR LED sensor data
  18. int32_t n_ir_buffer_length;    //data length
  19. uint32_t aun_red_buffer[500];    //Red LED sensor data
  20. int32_t n_sp02; //SPO2 value
  21. int8_t ch_spo2_valid;   //indicator to show if the SP02 calculation is valid
  22. int32_t n_heart_rate;   //heart rate value
  23. int8_t  ch_hr_valid;    //indicator to show if the heart rate calculation is valid
  24. uint8_t uch_dummy;
  25. #define MAX_BRIGHTNESS 255
  26. #define false 0
  27. #define true 1
  28. int main(void)
  29. {
  30.         uint32_t un_min, un_max, un_prev_data;  //variables to calculate the on-board LED brightness that reflects the heartbeats
  31.         int i;  
  32.         int32_t n_brightness;
  33.         float f_temp;
  34.         USART2_Configuration(115200);
  35.         I2CM_Init(MAX14690_I2CM, &max14690_sys_cfg, I2CM_SPEED_100KHZ);
  36.         I2CM_Init(MXC_I2CM1, &max30102_sys_cfg, I2CM_SPEED_100KHZ);
  37.         //Device_Hardware_Init();
  38.         maxim_max30102_reset(); //resets the MAX30102

  39.             //read and clear status register
  40.                 maxim_max30102_read_reg(0,&uch_dummy);
  41.                 maxim_max30102_init();  //initializes the MAX30102
  42.                 n_brightness=0;
  43.     un_min=0x3FFFF;
  44.     un_max=0;
  45.   
  46.     n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
  47.    
  48.     //read the first 500 samples, and determine the signal range
  49.     for(i=0;i<n_ir_buffer_length;i++)
  50.     {
  51.         //while(INT.read()==1);   //wait until the interrupt pin asserts
  52.         
  53.         maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));  //read from MAX30102 FIFO
  54.             
  55.         if(un_min>aun_red_buffer[i])[/i]
  56. [i]            un_min=aun_red_buffer;    //update signal min[/i]
  57. [i]        if(un_max<aun_red_buffer)[/i]
  58. [i]            un_max=aun_red_buffer;    //update signal max[/i]
  59. [i]        printf("red=");[/i]
  60. [i]        printf("%i", aun_red_buffer);[/i]
  61. [i]        printf(", ir=");[/i]
  62. [i]        printf("%i\n\r", aun_ir_buffer);[/i]
  63. [i]    }[/i]
  64. [i]    un_prev_data=aun_red_buffer;[/i]


  65. [i]    //calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)[/i]
  66. [i]    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); [/i]

  67. [i]    //Continuously taking samples from MAX30102.  Heart rate and SpO2 are calculated every 1 second[/i]
  68. [i]    while(1)[/i]
  69. [i]    {[/i]
  70. [i]        i=0;[/i]
  71. [i]        un_min=0x3FFFF;//???[/i]
  72. [i]        un_max=0;[/i]

  73. [i]        //dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top[/i]
  74. [i]        for(i=100;i<500;i++)[/i]
  75. [i]        {[/i]
  76. [i]            aun_red_buffer[i-100]=aun_red_buffer;[/i]
  77. [i]            aun_ir_buffer[i-100]=aun_ir_buffer;[/i]

  78. [i]            //update the signal min and max[/i]
  79. [i]            if(un_min>aun_red_buffer)[/i]
  80. [i]            un_min=aun_red_buffer;[/i]
  81. [i]            if(un_max<aun_red_buffer)[/i]
  82. [i]            un_max=aun_red_buffer;[/i]
  83. [i]        }[/i]

  84. [i]        //take 100 sets of samples before calculating the heart rate.[/i]
  85. [i]        for(i=400;i<500;i++)[/i]
  86. [i]        {[/i]
  87. [i]            un_prev_data=aun_red_buffer[i-1];[/i]
  88. [i]           // while(INT.read()==1);[/i]
  89. [i]            maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));[/i]

  90. [i]            if(aun_red_buffer>un_prev_data)//just to determine the brightness of LED according to the deviation of adjacent two AD data[/i]
  91. [i]            {[/i]
  92. [i]                f_temp=aun_red_buffer-un_prev_data;[/i]
  93. [i]                f_temp/=(un_max-un_min);[/i]
  94. [i]                f_temp*=MAX_BRIGHTNESS;[/i]
  95. [i]                n_brightness-=(int)f_temp;[/i]
  96. [i]                if(n_brightness<0)[/i]
  97. [i]                    n_brightness=0;[/i]
  98. [i]            }[/i]
  99. [i]            else[/i]
  100. [i]            {[/i]
  101. [i]                f_temp=un_prev_data-aun_red_buffer;[/i]
  102. [i]                f_temp/=(un_max-un_min);[/i]
  103. [i]                f_temp*=MAX_BRIGHTNESS;[/i]
  104. [i]                n_brightness+=(int)f_temp;[/i]
  105. [i]                if(n_brightness>MAX_BRIGHTNESS)[/i]
  106. [i]                    n_brightness=MAX_BRIGHTNESS;[/i]
  107. [i]            }[/i]

  108. [i]            //led.write(1-(float)n_brightness/256);//pwm control led brightness[/i]

  109. [i]            //send samples and calculation result to terminal program through UART[/i]
  110. [i]            printf("red=");[/i]
  111. [i]            printf("%i", aun_red_buffer);[/i]
  112. [i]            printf(", ir=");[/i]
  113. [i]            printf("%i", aun_ir_buffer);[/i]
  114. [i]            printf(", HR=%i, ", n_heart_rate); [/i]
  115. [i]            printf("HRvalid=%i, ", ch_hr_valid);[/i]
  116. [i]            printf("SpO2=%i, ", n_sp02);[/i]
  117. [i]            printf("SPO2Valid=%i\n\r", ch_spo2_valid);[/i]
  118. [i]        }[/i]
  119. [i]        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); [/i]
  120. [i]    }[/i]

  121. [i]}[/i]
  122. [i]
复制代码


第三个文件max30102.cpp是重点,先给出max30102.cpp的源代码:
  1. /** \file max30102.cpp ******************************************************[/i]
  2. [i]*[/i]
  3. [i]* Project: MAXREFDES117#[/i]
  4. [i]* Filename: max30102.cpp[/i]
  5. [i]* Description: This module is an embedded controller driver for the MAX30102[/i]
  6. [i]*[/i]
  7. [i]*[/i]
  8. [i]* --------------------------------------------------------------------[/i]
  9. [i]*[/i]
  10. [i]* This code follows the following naming conventions:[/i]
  11. [i]*[/i]
  12. [i]* char              ch_pmod_value[/i]
  13. [i]* char (array)      s_pmod_s_string[16][/i]
  14. [i]* float             f_pmod_value[/i]
  15. [i]* int32_t           n_pmod_value[/i]
  16. [i]* int32_t (array)   an_pmod_value[16][/i]
  17. [i]* int16_t           w_pmod_value[/i]
  18. [i]* int16_t (array)   aw_pmod_value[16][/i]
  19. [i]* uint16_t          uw_pmod_value[/i]
  20. [i]* uint16_t (array)  auw_pmod_value[16][/i]
  21. [i]* uint8_t           uch_pmod_value[/i]
  22. [i]* uint8_t (array)   auch_pmod_buffer[16][/i]
  23. [i]* uint32_t          un_pmod_value[/i]
  24. [i]* int32_t *         pn_pmod_value[/i]
  25. [i]*[/i]
  26. [i]* ------------------------------------------------------------------------- */[/i]
  27. [i]/*******************************************************************************[/i]
  28. [i]* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.[/i]
  29. [i]*[/i]
  30. [i]* Permission is hereby granted, free of charge, to any person obtaining a[/i]
  31. [i]* copy of this software and associated documentation files (the "Software"),[/i]
  32. [i]* to deal in the Software without restriction, including without limitation[/i]
  33. [i]* the rights to use, copy, modify, merge, publish, distribute, sublicense,[/i]
  34. [i]* and/or sell copies of the Software, and to permit persons to whom the[/i]
  35. [i]* Software is furnished to do so, subject to the following conditions:[/i]
  36. [i]*[/i]
  37. [i]* The above copyright notice and this permission notice shall be included[/i]
  38. [i]* in all copies or substantial portions of the Software.[/i]
  39. [i]*[/i]
  40. [i]* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS[/i]
  41. [i]* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF[/i]
  42. [i]* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.[/i]
  43. [i]* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES[/i]
  44. [i]* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,[/i]
  45. [i]* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR[/i]
  46. [i]* OTHER DEALINGS IN THE SOFTWARE.[/i]
  47. [i]*[/i]
  48. [i]* Except as contained in this notice, the name of Maxim Integrated[/i]
  49. [i]* Products, Inc. shall not be used except as stated in the Maxim Integrated[/i]
  50. [i]* Products, Inc. Branding Policy.[/i]
  51. [i]*[/i]
  52. [i]* The mere transfer of this software does not imply any licenses[/i]
  53. [i]* of trade secrets, proprietary technology, copyrights, patents,[/i]
  54. [i]* trademarks, maskwork rights, or any other form of intellectual[/i]
  55. [i]* property whatsoever. Maxim Integrated Products, Inc. retains all[/i]
  56. [i]* ownership rights.[/i]
  57. [i]*******************************************************************************[/i]
  58. [i]*/[/i]
  59. [i]#include "mbed.h"[/i]
  60. [i]#include "MAX30102.h"[/i]

  61. [i]I2C i2c(P3_4, P3_5);[/i]

  62. [i]bool maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)[/i]
  63. [i]/**[/i]
  64. [i]* \brief        Write a value to a MAX30102 register[/i]
  65. [i]* \par          Details[/i]
  66. [i]*               This function writes a value to a MAX30102 register[/i]
  67. [i]*[/i]
  68. [i]* \param[in]    uch_addr    - register address[/i]
  69. [i]* \param[in]    uch_data    - register data[/i]
  70. [i]*[/i]
  71. [i]* \retval       true on success[/i]
  72. [i]*/[/i]
  73. [i]{[/i]
  74. [i]  char ach_i2c_data[2];[/i]
  75. [i]  ach_i2c_data[0]=uch_addr;[/i]
  76. [i]  ach_i2c_data[1]=uch_data;[/i]

  77. [i]  if(i2c.write(I2C_WRITE_ADDR, ach_i2c_data, 2, false)==0)[/i]
  78. [i]    return true;[/i]
  79. [i]  else[/i]
  80. [i]    return false;[/i]
  81. [i]}[/i]

  82. [i]bool maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)[/i]
  83. [i]/**[/i]
  84. [i]* \brief        Read a MAX30102 register[/i]
  85. [i]* \par          Details[/i]
  86. [i]*               This function reads a MAX30102 register[/i]
  87. [i]*[/i]
  88. [i]* \param[in]    uch_addr    - register address[/i]
  89. [i]* \param[out]   puch_data    - pointer that stores the register data[/i]
  90. [i]*[/i]
  91. [i]* \retval       true on success[/i]
  92. [i]*/[/i]
  93. [i]{[/i]
  94. [i]  char ch_i2c_data;[/i]
  95. [i]  ch_i2c_data=uch_addr;[/i]
  96. [i]  if(i2c.write(I2C_WRITE_ADDR, &ch_i2c_data, 1, true)!=0)[/i]
  97. [i]    return false;[/i]
  98. [i]  if(i2c.read(I2C_READ_ADDR, &ch_i2c_data, 1, false)==0)[/i]
  99. [i]  {[/i]
  100. [i]    *puch_data=(uint8_t) ch_i2c_data;[/i]
  101. [i]    return true;[/i]
  102. [i]  }[/i]
  103. [i]  else[/i]
  104. [i]    return false;[/i]
  105. [i]}[/i]

  106. [i]bool maxim_max30102_init()[/i]
  107. [i]/**[/i]
  108. [i]* \brief        Initialize the MAX30102[/i]
  109. [i]* \par          Details[/i]
  110. [i]*               This function initializes the MAX30102[/i]
  111. [i]*[/i]
  112. [i]* \param        None[/i]
  113. [i]*[/i]
  114. [i]* \retval       true on success[/i]
  115. [i]*/[/i]
  116. [i]{[/i]
  117. [i]  if(!maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)) // INTR setting[/i]
  118. [i]    return false;[/i]
  119. [i]  if(!maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x00))[/i]
  120. [i]    return false;[/i]
  121. [i]  if(!maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00))  //FIFO_WR_PTR[4:0][/i]
  122. [i]    return false;[/i]
  123. [i]  if(!maxim_max30102_write_reg(REG_OVF_COUNTER,0x00))  //OVF_COUNTER[4:0][/i]
  124. [i]    return false;[/i]
  125. [i]  if(!maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00))  //FIFO_RD_PTR[4:0][/i]
  126. [i]    return false;[/i]
  127. [i]  if(!maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f))  //sample avg = 1, fifo rollover=false, fifo almost full = 17[/i]
  128. [i]    return false;[/i]
  129. [i]  if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x03))   //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED[/i]
  130. [i]    return false;[/i]
  131. [i]  if(!maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27))  // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)[/i]
  132. [i]    return false;[/i]

  133. [i]  if(!maxim_max30102_write_reg(REG_LED1_PA,0x24))   //Choose value for ~ 7mA for LED1[/i]
  134. [i]    return false;[/i]
  135. [i]  if(!maxim_max30102_write_reg(REG_LED2_PA,0x24))   // Choose value for ~ 7mA for LED2[/i]
  136. [i]    return false;[/i]
  137. [i]  if(!maxim_max30102_write_reg(REG_PILOT_PA,0x7f))   // Choose value for ~ 25mA for Pilot LED[/i]
  138. [i]    return false;[/i]
  139. [i]  return true;  [/i]
  140. [i]}[/i]

  141. [i]bool maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)[/i]
  142. [i]/**[/i]
  143. [i]* \brief        Read a set of samples from the MAX30102 FIFO register[/i]
  144. [i]* \par          Details[/i]
  145. [i]*               This function reads a set of samples from the MAX30102 FIFO register[/i]
  146. [i]*[/i]
  147. [i]* \param[out]   *pun_red_led   - pointer that stores the red LED reading data[/i]
  148. [i]* \param[out]   *pun_ir_led    - pointer that stores the IR LED reading data[/i]
  149. [i]*[/i]
  150. [i]* \retval       true on success[/i]
  151. [i]*/[/i]
  152. [i]{[/i]
  153. [i]  uint32_t un_temp;[/i]
  154. [i]  unsigned char uch_temp;[/i]
  155. [i]  *pun_red_led=0;[/i]
  156. [i]  *pun_ir_led=0;[/i]
  157. [i]  char ach_i2c_data[6];[/i]

  158. [i]  //read and clear status register[/i]
  159. [i]  maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);[/i]
  160. [i]  maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);[/i]

  161. [i]  ach_i2c_data[0]=REG_FIFO_DATA;[/i]
  162. [i]  if(i2c.write(I2C_WRITE_ADDR, ach_i2c_data, 1, true)!=0)[/i]
  163. [i]    return false;[/i]
  164. [i]  if(i2c.read(I2C_READ_ADDR, ach_i2c_data, 6, false)!=0)[/i]
  165. [i]  {[/i]
  166. [i]    return false;[/i]
  167. [i]  }[/i]
  168. [i]  un_temp=(unsigned char) ach_i2c_data[0];[/i]
  169. [i]  un_temp<<=16;[/i]
  170. [i]  *pun_red_led+=un_temp;[/i]
  171. [i]  un_temp=(unsigned char) ach_i2c_data[1];[/i]
  172. [i]  un_temp<<=8;[/i]
  173. [i]  *pun_red_led+=un_temp;[/i]
  174. [i]  un_temp=(unsigned char) ach_i2c_data[2];[/i]
  175. [i]  *pun_red_led+=un_temp;[/i]

  176. [i]  un_temp=(unsigned char) ach_i2c_data[3];[/i]
  177. [i]  un_temp<<=16;[/i]
  178. [i]  *pun_ir_led+=un_temp;[/i]
  179. [i]  un_temp=(unsigned char) ach_i2c_data[4];[/i]
  180. [i]  un_temp<<=8;[/i]
  181. [i]  *pun_ir_led+=un_temp;[/i]
  182. [i]  un_temp=(unsigned char) ach_i2c_data[5];[/i]
  183. [i]  *pun_ir_led+=un_temp;[/i]
  184. [i]  *pun_red_led&=0x03FFFF;  //Mask MSB [23:18][/i]
  185. [i]  *pun_ir_led&=0x03FFFF;  //Mask MSB [23:18][/i]


  186. [i]  return true;[/i]
  187. [i]}[/i]

  188. [i]bool maxim_max30102_reset()[/i]
  189. [i]/**[/i]
  190. [i]* \brief        Reset the MAX30102[/i]
  191. [i]* \par          Details[/i]
  192. [i]*               This function resets the MAX30102[/i]
  193. [i]*[/i]
  194. [i]* \param        None[/i]
  195. [i]*[/i]
  196. [i]* \retval       true on success[/i]
  197. [i]*/[/i]
  198. [i]{[/i]
  199. [i]    if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x40))[/i]
  200. [i]        return false;[/i]
  201. [i]    else[/i]
  202. [i]        return true;    [/i]
  203. [i]}[/i]
  204. [i]
复制代码

移植改编后的程序为:
  1. /***********************************************
  2. @from Justice_Gao
  3. ***********************************************/

  4. #include "Com.h"

  5. /** \file max30102.cpp ******************************************************
  6. *
  7. * Project: MAXREFDES117#
  8. * Filename: max30102.cpp
  9. * Description: This module is an embedded controller driver for the MAX30102
  10. *
  11. *
  12. * --------------------------------------------------------------------
  13. *
  14. * This code follows the following naming conventions:
  15. *
  16. * char              ch_pmod_value
  17. * char (array)      s_pmod_s_string[16]
  18. * float             f_pmod_value
  19. * int32_t           n_pmod_value
  20. * int32_t (array)   an_pmod_value[16]
  21. * int16_t           w_pmod_value
  22. * int16_t (array)   aw_pmod_value[16]
  23. * uint16_t          uw_pmod_value
  24. * uint16_t (array)  auw_pmod_value[16]
  25. * uint8_t           uch_pmod_value
  26. * uint8_t (array)   auch_pmod_buffer[16]
  27. * uint32_t          un_pmod_value
  28. * int32_t *         pn_pmod_value
  29. *
  30. * ------------------------------------------------------------------------- */
  31. /*******************************************************************************
  32. * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
  33. *
  34. * Permission is hereby granted, free of charge, to any person obtaining a
  35. * copy of this software and associated documentation files (the "Software"),
  36. * to deal in the Software without restriction, including without limitation
  37. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  38. * and/or sell copies of the Software, and to permit persons to whom the
  39. * Software is furnished to do so, subject to the following conditions:
  40. *
  41. * The above copyright notice and this permission notice shall be included
  42. * in all copies or substantial portions of the Software.
  43. *
  44. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  45. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  46. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  47. * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
  48. * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  49. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  50. * OTHER DEALINGS IN THE SOFTWARE.
  51. *
  52. * Except as contained in this notice, the name of Maxim Integrated
  53. * Products, Inc. shall not be used except as stated in the Maxim Integrated
  54. * Products, Inc. Branding Policy.
  55. *
  56. * The mere transfer of this software does not imply any licenses
  57. * of trade secrets, proprietary technology, copyrights, patents,
  58. * trademarks, maskwork rights, or any other form of intellectual
  59. * property whatsoever. Maxim Integrated Products, Inc. retains all
  60. * ownership rights.
  61. *******************************************************************************
  62. */
  63. #include "MAX30100.h"
  64. #include "i2cm.h"
  65. #define MBED_ASSERT(expr) ((void)0)
  66. // write - Master Transmitter Mode
  67. void lock()
  68. {
  69. }
  70. void unlock()
  71. {
  72. }
  73. int I2C_write(int address, const char* data, int length, uint8_t repeated)
  74. {
  75.     lock();
  76.    // aquire();

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

  79.     unlock();
  80.     return length != written;
  81. }
  82. // read - Master Reciever Mode
  83. int I2C_read(int address, char* data, int length, uint8_t repeated) {
  84.     lock();
  85.    // aquire();

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

  88.     unlock();
  89.     return length != read;
  90. }
  91. //******************************************************************************
  92. int i2c_read(mxc_i2cm_regs_t *i2cm, int address, char *data, int length, int stop)
  93. {
  94.     MBED_ASSERT(stop != 0);
  95.     return I2CM_Read(i2cm, address >> 1, NULL, 0, (uint8_t *)data, length);
  96. }
  97. //******************************************************************************
  98. int i2c_write(mxc_i2cm_regs_t *i2cm, int address, const char *data, int length, int stop)
  99. {
  100.     mxc_i2cm_fifo_regs_t *fifo = MXC_I2CM1_FIFO;

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

  104.     i2cm->inten = 0;
  105.     i2cm->intfl = i2cm->intfl;
  106.     if (I2CM_Tx(i2cm, fifo, address >> 1, (uint8_t *)data, length, 0) == E_NO_ERROR) {
  107.         return length;
  108.     } else {
  109.         return -1;
  110.     }
  111. }
  112. //I2C i2c(I2C_SDA, I2C_SCL);//SDA-PB9,SCL-PB8


  113. uint8_t maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)
  114. /**
  115. * \brief        Write a value to a MAX30102 register
  116. * \par          Details
  117. *               This function writes a value to a MAX30102 register
  118. *
  119. * \param[in]    uch_addr    - register address
  120. * \param[in]    uch_data    - register data
  121. *
  122. * \retval       true on success
  123. */
  124. {
  125.   char ach_i2c_data[2];
  126.   ach_i2c_data[0]=uch_addr;
  127.   ach_i2c_data[1]=uch_data;
  128.   
  129.   if(I2C_write(I2C_WRITE_ADDR, ach_i2c_data, 2, 0)==0)
  130.     return 1;
  131.   else
  132.     return 0;
  133. }

  134. uint8_t maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)
  135. /**
  136. * \brief        Read a MAX30102 register
  137. * \par          Details
  138. *               This function reads a MAX30102 register
  139. *
  140. * \param[in]    uch_addr    - register address
  141. * \param[out]   puch_data    - pointer that stores the register data
  142. *
  143. * \retval       true on success
  144. */
  145. {
  146.   char ch_i2c_data;
  147.   ch_i2c_data=uch_addr;
  148.   if(I2C_write(I2C_WRITE_ADDR, &ch_i2c_data, 1, 1)!=0)
  149.     return 0;
  150.   if(I2C_read(I2C_READ_ADDR, &ch_i2c_data, 1, 0)==0)
  151.   {
  152.     *puch_data=(uint8_t) ch_i2c_data;
  153.     return 1;
  154.   }
  155.   else
  156.     return 0;
  157. }

  158. uint8_t maxim_max30102_init()
  159. /**
  160. * \brief        Initialize the MAX30102
  161. * \par          Details
  162. *               This function initializes the MAX30102
  163. *
  164. * \param        None
  165. *
  166. * \retval       true on success
  167. */
  168. {
  169.   if(!maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)) // INTR setting
  170.     return 0;
  171.   if(!maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x00))
  172.     return 0;
  173.   if(!maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00))  //FIFO_WR_PTR[4:0]
  174.     return 0;
  175.   if(!maxim_max30102_write_reg(REG_OVF_COUNTER,0x00))  //OVF_COUNTER[4:0]
  176.     return 0;
  177.   if(!maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00))  //FIFO_RD_PTR[4:0]
  178.     return 0;
  179.   if(!maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f))  //sample avg = 1, fifo rollover=false, fifo almost full = 17
  180.     return 0;
  181.   if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x03))   //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
  182.     return 0;
  183.   if(!maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27))  // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)
  184.     return 0;
  185.   
  186.   if(!maxim_max30102_write_reg(REG_LED1_PA,0x24))   //Choose value for ~ 7mA for LED1
  187.     return 0;
  188.   if(!maxim_max30102_write_reg(REG_LED2_PA,0x24))   // Choose value for ~ 7mA for LED2
  189.     return 0;
  190.   if(!maxim_max30102_write_reg(REG_PILOT_PA,0x7f))   // Choose value for ~ 25mA for Pilot LED
  191.     return 0;
  192.   return 1;  
  193. }

  194. uint8_t maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
  195. /**
  196. * \brief        Read a set of samples from the MAX30102 FIFO register
  197. * \par          Details
  198. *               This function reads a set of samples from the MAX30102 FIFO register
  199. *
  200. * \param[out]   *pun_red_led   - pointer that stores the red LED reading data
  201. * \param[out]   *pun_ir_led    - pointer that stores the IR LED reading data
  202. *
  203. * \retval       true on success
  204. */
  205. {
  206.   uint32_t un_temp;
  207.   unsigned char uch_temp;
  208.   *pun_red_led=0;
  209.   *pun_ir_led=0;
  210.   char ach_i2c_data[6];
  211.   
  212.   //read and clear status register
  213.   maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
  214.   maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);
  215.   
  216.   ach_i2c_data[0]=REG_FIFO_DATA;
  217.   if(I2C_write(I2C_WRITE_ADDR, ach_i2c_data, 1, 1)!=0)
  218.     return 0;
  219.   if(I2C_read(I2C_READ_ADDR, ach_i2c_data, 6, 0)!=0)
  220.   {
  221.     return 0;
  222.   }
  223.   un_temp=(unsigned char) ach_i2c_data[0];
  224.   un_temp<<=16;
  225.   *pun_red_led+=un_temp;
  226.   un_temp=(unsigned char) ach_i2c_data[1];
  227.   un_temp<<=8;
  228.   *pun_red_led+=un_temp;
  229.   un_temp=(unsigned char) ach_i2c_data[2];
  230.   *pun_red_led+=un_temp;
  231.   
  232.   un_temp=(unsigned char) ach_i2c_data[3];
  233.   un_temp<<=16;
  234.   *pun_ir_led+=un_temp;
  235.   un_temp=(unsigned char) ach_i2c_data[4];
  236.   un_temp<<=8;
  237.   *pun_ir_led+=un_temp;
  238.   un_temp=(unsigned char) ach_i2c_data[5];
  239.   *pun_ir_led+=un_temp;
  240.   *pun_red_led&=0x03FFFF;  //Mask MSB [23:18]
  241.   *pun_ir_led&=0x03FFFF;  //Mask MSB [23:18]
  242.   
  243.   
  244.   return 1;
  245. }

  246. uint8_t maxim_max30102_reset()
  247. /**
  248. * \brief        Reset the MAX30102
  249. * \par          Details
  250. *               This function resets the MAX30102
  251. *
  252. * \param        None
  253. *
  254. * \retval       true on success
  255. */
  256. {
  257.     if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x40))
  258.         return 0;
  259.     else
  260.         return 1;   
  261. }
复制代码
移植过程中,其实难点在于将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语言编写的

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

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




回复

使用道具 举报

3

TA的帖子

2

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2017-9-23 18:01 | 显示全部楼层
楼主,能发一份工程吗,邮箱:3139927868@qq.com,万分感谢

点评

发你,这可是呕心沥血的作品,你先发给ipad过来吧 哈哈  详情 回复 发表于 2017-9-23 18:46


回复

使用道具 举报

113

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

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

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


回复

使用道具 举报

3

TA的帖子

2

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2017-9-23 23:07 | 显示全部楼层
楼主  帮忙看看  输出不是很稳定,是啥原因,谢谢了  Ipad已备好哈

stm32 max30102心率传感器.rar

2.51 MB, 下载次数: 398

点评

先寄过来 哈哈  详情 回复 发表于 2017-9-23 23:23


回复

使用道具 举报

113

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

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

先寄过来 哈哈

点评

楼主的ipad拿到了吗,程序可以开源了  详情 回复 发表于 2018-3-9 15:39


回复

使用道具 举报

45

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2018-3-9 15:39 | 显示全部楼层

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


回复

使用道具 举报

430

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2018-3-13 14:35 | 显示全部楼层
路过看看
充放电数显全套方案,双口快充慢充检测电流电压,两线三线直流电压表,配套三个8尺寸15*8MM带AV电流电压单位专利数码屏,资料QQ2981074992 邮箱同上


回复

使用道具 举报

1

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2018-3-19 19:41 | 显示全部楼层
楼主  能麻烦发一份心率和血氧计算算法吗   不知道我现在手里的算法对不对  谢谢楼主了

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

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


回复

使用道具 举报

1

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2018-4-15 19:13 | 显示全部楼层
楼主,可以给我一份文件么,最近电设做这个题目,一直没有头绪
1083557165@qq.com


回复

使用道具 举报

1

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2018-8-25 13:50 | 显示全部楼层
楼主我的q2649558793,可以加上交流一下吗!


回复

使用道具 举报

1

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2019-2-13 18:41 | 显示全部楼层
请问Com.h文件在哪找的?

点评

自己编写的  详情 回复 发表于 2019-2-14 08:46


回复

使用道具 举报

113

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2019-2-14 08:46 | 显示全部楼层
time_opp 发表于 2019-2-13 18:41
请问Com.h文件在哪找的?

自己编写的


回复

使用道具 举报

1

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2019-3-16 22:48 | 显示全部楼层
大佬,能发一份工程吗,邮箱:1536760015@qq.com,万分感谢


回复

使用道具 举报

1

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2019-3-22 15:08 | 显示全部楼层
楼主,跪求一份工程,毕设因为这个模块卡了很久,万分感谢!!!
邮箱:978460447@qq.com


回复

使用道具 举报

2

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2019-4-14 09:49 | 显示全部楼层
楼主可以发一下工程文件吗?邮箱1197421427@qq.com 万分感谢!


回复

使用道具 举报

2

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2019-4-14 10:55 | 显示全部楼层
早起的 发表于 2017-9-23 23:07
楼主  帮忙看看  输出不是很稳定,是啥原因,谢谢了  Ipad已备好哈

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


回复

使用道具 举报

885

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2019-4-14 15:15 | 显示全部楼层
楼主威武,强烈支持……


回复

使用道具 举报

1

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2019-4-17 17:32 | 显示全部楼层
楼主,跪求一份工程,万分感谢!!!
邮箱:2366299515@qq.com


回复

使用道具 举报

1

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2019-7-1 17:02 | 显示全部楼层

楼主  能否加个qq:1148543046  想请教



回复

使用道具 举报

1

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2019-8-3 16:20 | 显示全部楼层

我用nrf53832能接收到MAX30102心率血氧数据后就没搞了,不知楼主研究到什么程度了



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

关闭

站长推荐上一条 1/6 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-3-29 23:16 , Processed in 0.573543 second(s), 19 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表