找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7006|回复: 15
打印 上一主题 下一主题
收起左侧

STM32单片机+MAX30102心率血氧检测代码

  [复制链接]
跳转到指定楼层
楼主
ID:1022289 发表于 2022-5-15 09:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近在做心率血氧检测,用的是C8T6最小系统板和MAX30102代码发送给大家
STM32F103-30102:
    VCC<->3.3V
    GND<->GND
    SCL<->PB7
    SDA<->PB8
    IM<->PB9
0.96inch OLED :
    VCC<->3.3V
    GND<->GND
    SCL<->PA5
    SDA<->PA6
    RST<->PA3
    DC<->PA4
    CS<->PA2
USB-TTL:
    5V<->5V
    GND<->GND
    RXD<->PA9
    TXD<->PA10
单片机源程序如下:
  1. #include "max30102.h"
  2. #include "myiic.h"
  3. #include "delay.h"

  4. u8 max30102_Bus_Write(u8 Register_Address, u8 Word_Data)
  5. {

  6.         /* 采用串行EEPROM随即读取指令序列,连续读取若干字节 */

  7.         /* 第1步:发起I2C总线启动信号 */
  8.         IIC_Start();

  9.         /* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  10.         IIC_Send_Byte(max30102_WR_address | I2C_WR);        /* 此处是写指令 */

  11.         /* 第3步:发送ACK */
  12.         if (IIC_Wait_Ack() != 0)
  13.         {
  14.                 goto cmd_fail;        /* EEPROM器件无应答 */
  15.         }

  16.         /* 第4步:发送字节地址 */
  17.         IIC_Send_Byte(Register_Address);
  18.         if (IIC_Wait_Ack() != 0)
  19.         {
  20.                 goto cmd_fail;        /* EEPROM器件无应答 */
  21.         }
  22.         
  23.         /* 第5步:开始写入数据 */
  24.         IIC_Send_Byte(Word_Data);

  25.         /* 第6步:发送ACK */
  26.         if (IIC_Wait_Ack() != 0)
  27.         {
  28.                 goto cmd_fail;        /* EEPROM器件无应答 */
  29.         }

  30.         /* 发送I2C总线停止信号 */
  31.         IIC_Stop();
  32.         return 1;        /* 执行成功 */

  33. cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
  34.         /* 发送I2C总线停止信号 */
  35.         IIC_Stop();
  36.         return 0;
  37. }



  38. u8 max30102_Bus_Read(u8 Register_Address)
  39. {
  40.         u8  data;


  41.         /* 第1步:发起I2C总线启动信号 */
  42.         IIC_Start();

  43.         /* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  44.         IIC_Send_Byte(max30102_WR_address | I2C_WR);        /* 此处是写指令 */

  45.         /* 第3步:发送ACK */
  46.         if (IIC_Wait_Ack() != 0)
  47.         {
  48.                 goto cmd_fail;        /* EEPROM器件无应答 */
  49.         }

  50.         /* 第4步:发送字节地址, */
  51.         IIC_Send_Byte((uint8_t)Register_Address);
  52.         if (IIC_Wait_Ack() != 0)
  53.         {
  54.                 goto cmd_fail;        /* EEPROM器件无应答 */
  55.         }
  56.         

  57.         /* 第6步:重新启动I2C总线。下面开始读取数据 */
  58.         IIC_Start();

  59.         /* 第7步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  60.         IIC_Send_Byte(max30102_WR_address | I2C_RD);        /* 此处是读指令 */

  61.         /* 第8步:发送ACK */
  62.         if (IIC_Wait_Ack() != 0)
  63.         {
  64.                 goto cmd_fail;        /* EEPROM器件无应答 */
  65.         }

  66.         /* 第9步:读取数据 */
  67.         {
  68.                 data = IIC_Read_Byte(0);        /* 读1个字节 */

  69.                 IIC_NAck();        /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
  70.         }
  71.         /* 发送I2C总线停止信号 */
  72.         IIC_Stop();
  73.         return data;        /* 执行成功 返回data值 */

  74. cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
  75.         /* 发送I2C总线停止信号 */
  76.         IIC_Stop();
  77.         return 0;
  78. }


  79. void max30102_FIFO_ReadWords(u8 Register_Address,u16 Word_Data[][2],u8 count)
  80. {
  81.         u8 i=0;
  82.         u8 no = count;
  83.         u8 data1, data2;
  84.         /* 第1步:发起I2C总线启动信号 */
  85.         IIC_Start();

  86.         /* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  87.         IIC_Send_Byte(max30102_WR_address | I2C_WR);        /* 此处是写指令 */

  88.         /* 第3步:发送ACK */
  89.         if (IIC_Wait_Ack() != 0)
  90.         {
  91.                 goto cmd_fail;        /* EEPROM器件无应答 */
  92.         }

  93.         /* 第4步:发送字节地址, */
  94.         IIC_Send_Byte((uint8_t)Register_Address);
  95.         if (IIC_Wait_Ack() != 0)
  96.         {
  97.                 goto cmd_fail;        /* EEPROM器件无应答 */
  98.         }
  99.         

  100.         /* 第6步:重新启动I2C总线。下面开始读取数据 */
  101.         IIC_Start();

  102.         /* 第7步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  103.         IIC_Send_Byte(max30102_WR_address | I2C_RD);        /* 此处是读指令 */

  104.         /* 第8步:发送ACK */
  105.         if (IIC_Wait_Ack() != 0)
  106.         {
  107.                 goto cmd_fail;        /* EEPROM器件无应答 */
  108.         }

  109.         /* 第9步:读取数据 */
  110.         while (no)
  111.         {
  112.                 data1 = IIC_Read_Byte(0);        
  113.                 IIC_Ack();
  114.                 data2 = IIC_Read_Byte(0);
  115.                 IIC_Ack();
  116.                 Word_Data[i][0] = (((u16)data1 << 8) | data2);  //

  117.                
  118.                 data1 = IIC_Read_Byte(0);        
  119.                 IIC_Ack();
  120.                 data2 = IIC_Read_Byte(0);
  121.                 if(1==no)
  122.                         IIC_NAck();        /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
  123.                 else
  124.                         IIC_Ack();
  125.                 Word_Data[i][1] = (((u16)data1 << 8) | data2);

  126.                 no--;        
  127.                 i++;
  128.         }
  129.         /* 发送I2C总线停止信号 */
  130.         IIC_Stop();

  131. cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
  132.         /* 发送I2C总线停止信号 */
  133.         IIC_Stop();
  134. }

  135. void max30102_FIFO_ReadBytes(u8 Register_Address,u8* Data)
  136. {        
  137.         max30102_Bus_Read(REG_INTR_STATUS_1);
  138.         max30102_Bus_Read(REG_INTR_STATUS_2);
  139.         
  140.         /* 第1步:发起I2C总线启动信号 */
  141.         IIC_Start();

  142.         /* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  143.         IIC_Send_Byte(max30102_WR_address | I2C_WR);        /* 此处是写指令 */

  144.         /* 第3步:发送ACK */
  145.         if (IIC_Wait_Ack() != 0)
  146.         {
  147.                 goto cmd_fail;        /* EEPROM器件无应答 */
  148.         }

  149.         /* 第4步:发送字节地址, */
  150.         IIC_Send_Byte((uint8_t)Register_Address);
  151.         if (IIC_Wait_Ack() != 0)
  152.         {
  153.                 goto cmd_fail;        /* EEPROM器件无应答 */
  154.         }
  155.         

  156.         /* 第6步:重新启动I2C总线。下面开始读取数据 */
  157.         IIC_Start();

  158.         /* 第7步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
  159.         IIC_Send_Byte(max30102_WR_address | I2C_RD);        /* 此处是读指令 */

  160.         /* 第8步:发送ACK */
  161.         if (IIC_Wait_Ack() != 0)
  162.         {
  163.                 goto cmd_fail;        /* EEPROM器件无应答 */
  164.         }

  165.         /* 第9步:读取数据 */
  166.         Data[0] = IIC_Read_Byte(1);        
  167.         Data[1] = IIC_Read_Byte(1);        
  168.         Data[2] = IIC_Read_Byte(1);        
  169.         Data[3] = IIC_Read_Byte(1);
  170.         Data[4] = IIC_Read_Byte(1);        
  171.         Data[5] = IIC_Read_Byte(0);
  172.         /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
  173.         /* 发送I2C总线停止信号 */
  174.         IIC_Stop();

  175. cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
  176.         /* 发送I2C总线停止信号 */
  177.         IIC_Stop();

  178. //        u8 i;
  179. //        u8 fifo_wr_ptr;
  180. //        u8 firo_rd_ptr;
  181. //        u8 number_tp_read;
  182. //        //Get the FIFO_WR_PTR
  183. //        fifo_wr_ptr = max30102_Bus_Read(REG_FIFO_WR_PTR);
  184. //        //Get the FIFO_RD_PTR
  185. //        firo_rd_ptr = max30102_Bus_Read(REG_FIFO_RD_PTR);
  186. //        
  187. //        number_tp_read = fifo_wr_ptr - firo_rd_ptr;
  188. //        
  189. //        //for(i=0;i<number_tp_read;i++){
  190. //        if(number_tp_read>0){
  191. //                IIC_ReadBytes(max30102_WR_address,REG_FIFO_DATA,Data,6);
  192. //        }
  193.         
  194.         //max30102_Bus_Write(REG_FIFO_RD_PTR,fifo_wr_ptr);
  195. }

  196. void max30102_init(void)
  197. {
  198.         GPIO_InitTypeDef GPIO_InitStructure;

  199.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);        
  200.         GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_14;
  201.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  202.          GPIO_Init(GPIOB, &GPIO_InitStructure);
  203.         
  204.         IIC_Init();
  205.         
  206.         max30102_reset();
  207.         
  208. //        max30102_Bus_Write(REG_MODE_CONFIG, 0x0b);  //mode configuration : temp_en[3]      MODE[2:0]=010 HR only enabled    011 SP02 enabled
  209. //        max30102_Bus_Write(REG_INTR_STATUS_2, 0xF0); //open all of interrupt
  210. //        max30102_Bus_Write(REG_INTR_STATUS_1, 0x00); //all interrupt clear
  211. //        max30102_Bus_Write(REG_INTR_ENABLE_2, 0x02); //DIE_TEMP_RDY_EN
  212. //        max30102_Bus_Write(REG_TEMP_CONFIG, 0x01); //SET   TEMP_EN

  213. //        max30102_Bus_Write(REG_SPO2_CONFIG, 0x47); //SPO2_SR[4:2]=001  100 per second    LED_PW[1:0]=11  16BITS

  214. //        max30102_Bus_Write(REG_LED1_PA, 0x47);
  215. //        max30102_Bus_Write(REG_LED2_PA, 0x47);
  216.         
  217.         
  218.         
  219.         max30102_Bus_Write(REG_INTR_ENABLE_1,0xc0);        // INTR setting
  220.         max30102_Bus_Write(REG_INTR_ENABLE_2,0x00);
  221.         max30102_Bus_Write(REG_FIFO_WR_PTR,0x00);          //FIFO_WR_PTR[4:0]
  222.         max30102_Bus_Write(REG_OVF_COUNTER,0x00);          //OVF_COUNTER[4:0]
  223.         max30102_Bus_Write(REG_FIFO_RD_PTR,0x00);          //FIFO_RD_PTR[4:0]
  224.         max30102_Bus_Write(REG_FIFO_CONFIG,0x0f);          //sample avg = 1, fifo rollover=false, fifo almost full = 17
  225.         max30102_Bus_Write(REG_MODE_CONFIG,0x03);          //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
  226.         max30102_Bus_Write(REG_SPO2_CONFIG,0x27);          // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)  
  227.         max30102_Bus_Write(REG_LED1_PA,0x24);           //Choose value for ~ 7mA for LED1
  228.         max30102_Bus_Write(REG_LED2_PA,0x24);           // Choose value for ~ 7mA for LED2
  229.         max30102_Bus_Write(REG_PILOT_PA,0x7f);           // Choose value for ~ 25mA for Pilot LED


  230.         
  231. //        // Interrupt Enable 1 Register. Set PPG_RDY_EN (data available in FIFO)
  232. //        max30102_Bus_Write(0x2, 1<<6);

  233. //        // FIFO configuration register
  234. //        // SMP_AVE: 16 samples averaged per FIFO sample
  235. //        // FIFO_ROLLOVER_EN=1
  236. //        //max30102_Bus_Write(0x8,  1<<4);
  237. //        max30102_Bus_Write(0x8, (0<<5) | 1<<4);

  238. //        // Mode Configuration Register
  239. //        // SPO2 mode
  240. //        max30102_Bus_Write(0x9, 3);

  241. //        // SPO2 Configuration Register
  242. //        max30102_Bus_Write(0xa,
  243. //                        (3<<5)  // SPO2_ADC_RGE 2 = full scale 8192 nA (LSB size 31.25pA); 3 = 16384nA
  244. //                        | (1<<2) // sample rate: 0 = 50sps; 1 = 100sps; 2 = 200sps
  245. //                        | (3<<0) // LED_PW 3 = 411μs, ADC resolution 18 bits
  246. //        );

  247. //        // LED1 (red) power (0 = 0mA; 255 = 50mA)
  248. //        max30102_Bus_Write(0xc, 0xb0);

  249. //        // LED (IR) power
  250. //        max30102_Bus_Write(0xd, 0xa0);
  251.                                                                                        
  252. }

  253. void max30102_reset(void)
  254. {
  255.         max30102_Bus_Write(REG_MODE_CONFIG,0x40);
  256.         max30102_Bus_Write(REG_MODE_CONFIG,0x40);
  257. }






  258. void maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)
  259. {
  260. //  char ach_i2c_data[2];
  261. //  ach_i2c_data[0]=uch_addr;
  262. //  ach_i2c_data[1]=uch_data;
  263. //        
  264. //  IIC_WriteBytes(I2C_WRITE_ADDR, ach_i2c_data, 2);
  265.         IIC_Write_One_Byte(I2C_WRITE_ADDR,uch_addr,uch_data);
  266. }

  267. void maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)
  268. {
  269. //  char ch_i2c_data;
  270. //  ch_i2c_data=uch_addr;
  271. //  IIC_WriteBytes(I2C_WRITE_ADDR, &ch_i2c_data, 1);
  272. //        
  273. //  i2c.read(I2C_READ_ADDR, &ch_i2c_data, 1);
  274. //  
  275. //   *puch_data=(uint8_t) ch_i2c_data;
  276.         IIC_Read_One_Byte(I2C_WRITE_ADDR,uch_addr,puch_data);
  277. }

  278. void maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
  279. {
  280.         uint32_t un_temp;
  281.         unsigned char uch_temp;
  282.         char ach_i2c_data[6];
  283.         *pun_red_led=0;
  284.         *pun_ir_led=0;

  285.   
  286.   //read and clear status register
  287.   maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_temp);
  288.   maxim_max30102_read_reg(REG_INTR_STATUS_2, &uch_temp);
  289.   
  290.   IIC_ReadBytes(I2C_WRITE_ADDR,REG_FIFO_DATA,(u8 *)ach_i2c_data,6);
  291.   
  292.   un_temp=(unsigned char) ach_i2c_data[0];
  293.   un_temp<<=16;
  294.   *pun_red_led+=un_temp;
  295.   un_temp=(unsigned char) ach_i2c_data[1];
  296.   un_temp<<=8;
  297.   *pun_red_led+=un_temp;
  298.   un_temp=(unsigned char) ach_i2c_data[2];
  299.   *pun_red_led+=un_temp;
  300.   
  301.   un_temp=(unsigned char) ach_i2c_data[3];
  302.   un_temp<<=16;
  303.   *pun_ir_led+=un_temp;
  304.   un_temp=(unsigned char) ach_i2c_data[4];
  305.   un_temp<<=8;
  306.   *pun_ir_led+=un_temp;
  307.   un_temp=(unsigned char) ach_i2c_data[5];
  308.   *pun_ir_led+=un_temp;
  309.   *pun_red_led&=0x03FFFF;  //Mask MSB [23:18]
  310.   *pun_ir_led&=0x03FFFF;  //Mask MSB [23:18]
  311. }
复制代码

Keil5代码下载:
代码.7z (214.85 KB, 下载次数: 287)

评分

参与人数 2威望 +15 黑币 +80 收起 理由
wpppmlah + 15 + 30 共享资料的黑币奖励!
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏11 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:1039983 发表于 2022-8-19 17:09 | 只看该作者
7针OLED怎么改4针OLED啊
回复

使用道具 举报

板凳
ID:1043634 发表于 2022-10-13 16:44 | 只看该作者
这么好的帖子,必须顶起,支持楼主
回复

使用道具 举报

地板
ID:1043634 发表于 2022-10-30 15:16 | 只看该作者
这么好的帖子,必须顶起,支持楼主
回复

使用道具 举报

5#
ID:875451 发表于 2023-2-3 17:30 | 只看该作者
这个可以下载进C8T6吗
回复

使用道具 举报

6#
ID:504443 发表于 2023-3-8 07:38 | 只看该作者
请问定义的IM是接哪个引脚?
回复

使用道具 举报

7#
ID:291668 发表于 2023-3-8 13:34 | 只看该作者
辛苦了。顶起
回复

使用道具 举报

8#
ID:940352 发表于 2023-3-13 13:13 | 只看该作者
移植完成后 不出现心率值 一直显示----- 的原因是什么 求解
回复

使用道具 举报

9#
ID:1069607 发表于 2023-4-3 10:13 | 只看该作者
请问这个代码下载了是不是直接能用了?
回复

使用道具 举报

10#
ID:1069607 发表于 2023-4-3 12:26 | 只看该作者
543545 发表于 2022-8-19 17:09
7针OLED怎么改4针OLED啊

请问解决了吗
回复

使用道具 举报

11#
ID:291668 发表于 2023-4-3 13:51 | 只看该作者
好东西,顶起,太有帮助了
回复

使用道具 举报

12#
ID:1073560 发表于 2023-4-25 14:48 来自手机 | 只看该作者
请问有proteus仿真电路图吗?
回复

使用道具 举报

13#
ID:948914 发表于 2023-5-4 10:01 | 只看该作者
543545 发表于 2022-8-19 17:09
7针OLED怎么改4针OLED啊

好xd,改成功了么
回复

使用道具 举报

14#
ID:1074282 发表于 2023-5-10 14:22 | 只看该作者
悟道剑 发表于 2023-3-13 13:13
移植完成后 不出现心率值 一直显示----- 的原因是什么 求解

我也是一致显示----,兄弟解决了吗
回复

使用道具 举报

15#
ID:1073980 发表于 2023-11-22 14:24 | 只看该作者
带显示器吗
回复

使用道具 举报

16#
ID:1106925 发表于 2023-12-29 11:05 | 只看该作者
IM到底是什么引脚??
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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