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

Justice_Gao   2017-9-21 21:49 楼主
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. n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
  46. //read the first 500 samples, and determine the signal range
  47. for(i=0;i<n_ir_buffer_length;i++)
  48. {
  49. //while(INT.read()==1); //wait until the interrupt pin asserts
  50. maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i)); //read from MAX30102 FIFO
  51. if(un_min>aun_red_buffer[i])[/i]
  52. [i] un_min=aun_red_buffer; //update signal min[/i]
  53. [i] if(un_max<aun_red_buffer)[/i]
  54. [i] un_max=aun_red_buffer; //update signal max[/i]
  55. [i] printf("red=");[/i]
  56. [i] printf("%i", aun_red_buffer);[/i]
  57. [i] printf(", ir=");[/i]
  58. [i] printf("%i\n\r", aun_ir_buffer);[/i]
  59. [i] }[/i]
  60. [i] un_prev_data=aun_red_buffer;[/i]
  61. [i] //calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)[/i]
  62. [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]
  63. [i] //Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every 1 second[/i]
  64. [i] while(1)[/i]
  65. [i] {[/i]
  66. [i] i=0;[/i]
  67. [i] un_min=0x3FFFF;//???[/i]
  68. [i] un_max=0;[/i]
  69. [i] //dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top[/i]
  70. [i] for(i=100;i<500;i++)[/i]
  71. [i] {[/i]
  72. [i] aun_red_buffer[i-100]=aun_red_buffer;[/i]
  73. [i] aun_ir_buffer[i-100]=aun_ir_buffer;[/i]
  74. [i] //update the signal min and max[/i]
  75. [i] if(un_min>aun_red_buffer)[/i]
  76. [i] un_min=aun_red_buffer;[/i]
  77. [i] if(un_max<aun_red_buffer)[/i]
  78. [i] un_max=aun_red_buffer;[/i]
  79. [i] }[/i]
  80. [i] //take 100 sets of samples before calculating the heart rate.[/i]
  81. [i] for(i=400;i<500;i++)[/i]
  82. [i] {[/i]
  83. [i] un_prev_data=aun_red_buffer[i-1];[/i]
  84. [i] // while(INT.read()==1);[/i]
  85. [i] maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));[/i]
  86. [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]
  87. [i] {[/i]
  88. [i] f_temp=aun_red_buffer-un_prev_data;[/i]
  89. [i] f_temp/=(un_max-un_min);[/i]
  90. [i] f_temp*=MAX_BRIGHTNESS;[/i]
  91. [i] n_brightness-=(int)f_temp;[/i]
  92. [i] if(n_brightness<0)[/i]
  93. [i] n_brightness=0;[/i]
  94. [i] }[/i]
  95. [i] else[/i]
  96. [i] {[/i]
  97. [i] f_temp=un_prev_data-aun_red_buffer;[/i]
  98. [i] f_temp/=(un_max-un_min);[/i]
  99. [i] f_temp*=MAX_BRIGHTNESS;[/i]
  100. [i] n_brightness+=(int)f_temp;[/i]
  101. [i] if(n_brightness>MAX_BRIGHTNESS)[/i]
  102. [i] n_brightness=MAX_BRIGHTNESS;[/i]
  103. [i] }[/i]
  104. [i] //led.write(1-(float)n_brightness/256);//pwm control led brightness[/i]
  105. [i] //send samples and calculation result to terminal program through UART[/i]
  106. [i] printf("red=");[/i]
  107. [i] printf("%i", aun_red_buffer);[/i]
  108. [i] printf(", ir=");[/i]
  109. [i] printf("%i", aun_ir_buffer);[/i]
  110. [i] printf(", HR=%i, ", n_heart_rate); [/i]
  111. [i] printf("HRvalid=%i, ", ch_hr_valid);[/i]
  112. [i] printf("SpO2=%i, ", n_sp02);[/i]
  113. [i] printf("SPO2Valid=%i\n\r", ch_spo2_valid);[/i]
  114. [i] }[/i]
  115. [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]
  116. [i] }[/i]
  117. [i]}[/i]
  118. [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. if(I2C_write(I2C_WRITE_ADDR, ach_i2c_data, 2, 0)==0)
  129. return 1;
  130. else
  131. return 0;
  132. }
  133. uint8_t maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)
  134. /**
  135. * \brief Read a MAX30102 register
  136. * \par Details
  137. * This function reads a MAX30102 register
  138. *
  139. * \param[in] uch_addr - register address
  140. * \param[out] puch_data - pointer that stores the register data
  141. *
  142. * \retval true on success
  143. */
  144. {
  145. char ch_i2c_data;
  146. ch_i2c_data=uch_addr;
  147. if(I2C_write(I2C_WRITE_ADDR, &ch_i2c_data, 1, 1)!=0)
  148. return 0;
  149. if(I2C_read(I2C_READ_ADDR, &ch_i2c_data, 1, 0)==0)
  150. {
  151. *puch_data=(uint8_t) ch_i2c_data;
  152. return 1;
  153. }
  154. else
  155. return 0;
  156. }
  157. uint8_t maxim_max30102_init()
  158. /**
  159. * \brief Initialize the MAX30102
  160. * \par Details
  161. * This function initializes the MAX30102
  162. *
  163. * \param None
  164. *
  165. * \retval true on success
  166. */
  167. {
  168. if(!maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)) // INTR setting
  169. return 0;
  170. if(!maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x00))
  171. return 0;
  172. if(!maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00)) //FIFO_WR_PTR[4:0]
  173. return 0;
  174. if(!maxim_max30102_write_reg(REG_OVF_COUNTER,0x00)) //OVF_COUNTER[4:0]
  175. return 0;
  176. if(!maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00)) //FIFO_RD_PTR[4:0]
  177. return 0;
  178. if(!maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f)) //sample avg = 1, fifo rollover=false, fifo almost full = 17
  179. return 0;
  180. if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x03)) //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
  181. return 0;
  182. if(!maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27)) // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)
  183. return 0;
  184. if(!maxim_max30102_write_reg(REG_LED1_PA,0x24)) //Choose value for ~ 7mA for LED1
  185. return 0;
  186. if(!maxim_max30102_write_reg(REG_LED2_PA,0x24)) // Choose value for ~ 7mA for LED2
  187. return 0;
  188. if(!maxim_max30102_write_reg(REG_PILOT_PA,0x7f)) // Choose value for ~ 25mA for Pilot LED
  189. return 0;
  190. return 1;
  191. }
  192. uint8_t maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
  193. /**
  194. * \brief Read a set of samples from the MAX30102 FIFO register
  195. * \par Details
  196. * This function reads a set of samples from the MAX30102 FIFO register
  197. *
  198. * \param[out] *pun_red_led - pointer that stores the red LED reading data
  199. * \param[out] *pun_ir_led - pointer that stores the IR LED reading data
  200. *
  201. * \retval true on success
  202. */
  203. {
  204. uint32_t un_temp;
  205. unsigned char uch_temp;
  206. *pun_red_led=0;
  207. *pun_ir_led=0;
  208. char ach_i2c_data[6];
  209. //read and clear status register
  210. maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
  211. maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);
  212. ach_i2c_data[0]=REG_FIFO_DATA;
  213. if(I2C_write(I2C_WRITE_ADDR, ach_i2c_data, 1, 1)!=0)
  214. return 0;
  215. if(I2C_read(I2C_READ_ADDR, ach_i2c_data, 6, 0)!=0)
  216. {
  217. return 0;
  218. }
  219. un_temp=(unsigned char) ach_i2c_data[0];
  220. un_temp<<=16;
  221. *pun_red_led+=un_temp;
  222. un_temp=(unsigned char) ach_i2c_data[1];
  223. un_temp<<=8;
  224. *pun_red_led+=un_temp;
  225. un_temp=(unsigned char) ach_i2c_data[2];
  226. *pun_red_led+=un_temp;
  227. un_temp=(unsigned char) ach_i2c_data[3];
  228. un_temp<<=16;
  229. *pun_ir_led+=un_temp;
  230. un_temp=(unsigned char) ach_i2c_data[4];
  231. un_temp<<=8;
  232. *pun_ir_led+=un_temp;
  233. un_temp=(unsigned char) ach_i2c_data[5];
  234. *pun_ir_led+=un_temp;
  235. *pun_red_led&=0x03FFFF; //Mask MSB [23:18]
  236. *pun_ir_led&=0x03FFFF; //Mask MSB [23:18]
  237. return 1;
  238. }
  239. uint8_t maxim_max30102_reset()
  240. /**
  241. * \brief Reset the MAX30102
  242. * \par Details
  243. * This function resets the MAX30102
  244. *
  245. * \param None
  246. *
  247. * \retval true on success
  248. */
  249. {
  250. if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x40))
  251. return 0;
  252. else
  253. return 1;
  254. }
移植过程中,其实难点在于将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,可以说非常准确。 本帖最后由 Justice_Gao 于 2017-9-21 21:55 编辑

回复评论 (33)

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

发你,这可是呕心沥血的作品,你先发给ipad过来吧 哈哈
点赞  2017-9-23 18:46
楼主  帮忙看看  输出不是很稳定,是啥原因,谢谢了  Ipad已备好哈

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

先寄过来 哈哈
点赞  2017-9-23 23:23
引用: Justice_Gao 发表于 2017-9-23 23:23
先寄过来 哈哈

楼主的ipad拿到了吗,程序可以开源了
点赞  2018-3-9 15:39
路过看看
充放电数显全套方案,双口快充慢充检测电流电压,两线三线直流电压表,配套三个8尺寸15*8MM带AV电流电压单位专利数码屏,资料QQ2981074992 邮箱同上
点赞  2018-3-13 14:35
楼主  能麻烦发一份心率和血氧计算算法吗   不知道我现在手里的算法对不对  谢谢楼主了

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

补充内容 (2018-4-2 12:35):
楼主我用的是和你一样的测量算法,现在测量结果出来饱和度是正确的,但是心率结果一会维持一个数值,过一会又发生变化,请问你的也是这种情况吗?还是一直稳定在一个数值?
点赞  2018-3-19 19:41
楼主,可以给我一份文件么,最近电设做这个题目,一直没有头绪
1083557165@qq.com
点赞  2018-4-15 19:13
楼主我的q2649558793,可以加上交流一下吗!
点赞  2018-8-25 13:50
请问Com.h文件在哪找的?
点赞  2019-2-13 18:41
引用: time_opp 发表于 2019-2-13 18:41
请问Com.h文件在哪找的?

自己编写的
点赞  2019-2-14 08:46
大佬,能发一份工程吗,邮箱:1536760015@qq.com,万分感谢
点赞  2019-3-16 22:48
楼主,跪求一份工程,毕设因为这个模块卡了很久,万分感谢!!!
邮箱:978460447@qq.com
点赞  2019-3-22 15:08
楼主可以发一下工程文件吗?邮箱1197421427@qq.com 万分感谢!
点赞  2019-4-14 09:49
引用: 早起的 发表于 2017-9-23 23:07
楼主  帮忙看看  输出不是很稳定,是啥原因,谢谢了  Ipad已备好哈

你好,请问你对这个压缩包里的代码进行了改动吗?我从串口输出的数据是乱码
点赞  2019-4-14 10:55
楼主威武,强烈支持……
点赞  2019-4-14 15:15
楼主,跪求一份工程,万分感谢!!!
邮箱:2366299515@qq.com
点赞  2019-4-17 17:32

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

点赞  2019-7-1 17:02

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

点赞  2019-8-3 16:20
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复