当前位置:   article > 正文

STM32学习值传感器篇——max30102心率血氧传感器_max10302 stm32

max10302

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • \retval None
    */
    {

    int32_t i, j, n_old_npks, n_dist;

    /* Order peaks from large to small */
    maxim_sort_indices_descend( pn_x, pn_locs, *pn_npks );

    for ( i = -1; i < *pn_npks; i++ ){
    n_old_npks = *pn_npks;
    *pn_npks = i+1;
    for ( j = i+1; j < n_old_npks; j++ ){
    n_dist = pn_locs[j] - ( i == -1 ? -1 : pn_locs[i] ); // lag-zero peak of autocorr is at index -1
    if ( n_dist > n_min_distance || n_dist < -n_min_distance )
    pn_locs[(*pn_npks)++] = pn_locs[j];
    }
    }

    // Resort indices longo ascending order
    maxim_sort_ascend( pn_locs, *pn_npks );
    }

void maxim_sort_ascend(int32_t pn_x,int32_t n_size)
/
*

  • \brief Sort array
  • \par Details
  •           Sort array in ascending order (insertion sort algorithm)
    
    • 1
  • \retval None
    */
    {
    int32_t i, j, n_temp;
    for (i = 1; i < n_size; i++) {
    n_temp = pn_x[i];
    for (j = i; j > 0 && n_temp < pn_x[j-1]; j–)
    pn_x[j] = pn_x[j-1];
    pn_x[j] = n_temp;
    }
    }

void maxim_sort_indices_descend(int32_t pn_x, int32_t pn_indx, int32_t n_size)
/

  • \brief Sort indices
  • \par Details
  •           Sort indices according to descending order (insertion sort algorithm)
    
    • 1
  • \retval None
    */
    {
    int32_t i, j, n_temp;
    for (i = 1; i < n_size; i++) {
    n_temp = pn_indx[i];
    for (j = i; j > 0 && pn_x[n_temp] > pn_x[pn_indx[j-1]]; j–)
    pn_indx[j] = pn_indx[j-1];
    pn_indx[j] = n_temp;
    }
    }

 ,max30102驱动代码


max30102.h



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

#ifndef __MAX30102_H
#define __MAX30102_H
#include “stm32l1xx_hal.h”
#include “max_iic.h”
//

#define MAX30102_INT PBin(9)

#define I2C_WR 0 /* 写控制bit /
#define I2C_RD 1 /
读控制bit */

#define max30102_WR_address 0xAE

#define I2C_WRITE_ADDR 0xAE
#define I2C_READ_ADDR 0xAF

//register addresses
#define REG_INTR_STATUS_1 0x00
#define REG_INTR_STATUS_2 0x01
#define REG_INTR_ENABLE_1 0x02
#define REG_INTR_ENABLE_2 0x03
#define REG_FIFO_WR_PTR 0x04
#define REG_OVF_COUNTER 0x05
#define REG_FIFO_RD_PTR 0x06
#define REG_FIFO_DATA 0x07
#define REG_FIFO_CONFIG 0x08
#define REG_MODE_CONFIG 0x09
#define REG_SPO2_CONFIG 0x0A
#define REG_LED1_PA 0x0C
#define REG_LED2_PA 0x0D
#define REG_PILOT_PA 0x10
#define REG_MULTI_LED_CTRL1 0x11
#define REG_MULTI_LED_CTRL2 0x12
#define REG_TEMP_INTR 0x1F
#define REG_TEMP_FRAC 0x20
#define REG_TEMP_CONFIG 0x21
#define REG_PROX_INT_THRESH 0x30
#define REG_REV_ID 0xFE
#define REG_PART_ID 0xFF

void max30102_init(void);
void max30102_reset(void);
uint8_t max30102_Bus_Write(uint8_t Register_Address, uint8_t Word_Data);
uint8_t max30102_Bus_Read(uint8_t Register_Address);
void max30102_FIFO_ReadWords(uint8_t Register_Address,uint16_t Word_Data[][2],uint8_t count);
void max30102_FIFO_ReadBytes(uint8_t Register_Address,uint8_t* Data);

void maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data);
void maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data);
void maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led);
#endif


max30102.c



  • 1
  • 2
  • 3
  • 4
  • 5

#include “max30102.h”

uint8_t max30102_Bus_Write(uint8_t Register_Address, uint8_t Word_Data)
{

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

/* 第1步:发起I2C总线启动信号 */
I2C_Start();

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

/* 第3步:发送ACK */
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}

/* 第4步:发送字节地址 */
I2C_SendByte(Register_Address);
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}

/* 第5步:开始写入数据 */
I2C_SendByte(Word_Data);

/* 第6步:发送ACK */
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}

/* 发送I2C总线停止信号 */
I2C_Stop();
return 1;	/* 执行成功 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

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

uint8_t max30102_Bus_Read(uint8_t Register_Address)
{
uint8_t data;

/* 第1步:发起I2C总线启动信号 */
I2C_Start();

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

/* 第3步:发送ACK */
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}

/* 第4步:发送字节地址, */
I2C_SendByte((uint8_t)Register_Address);
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}


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

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

/* 第8步:发送ACK */
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}

/* 第9步:读取数据 */
{
	data = I2C_ReceiveByte(0);	/* 读1个字节 */

	I2C_NoAck();	/* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
}
/* 发送I2C总线停止信号 */
I2C_Stop();
return data;	/* 执行成功 返回data值 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

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

void max30102_FIFO_ReadWords(uint8_t Register_Address,uint16_t Word_Data[][2],uint8_t count)
{
uint8_t i=0;
uint8_t no = count;
uint8_t data1, data2;
/* 第1步:发起I2C总线启动信号 */
I2C_Start();

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

/* 第3步:发送ACK */
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}

/* 第4步:发送字节地址, */
I2C_SendByte((uint8_t)Register_Address);
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}


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

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

/* 第8步:发送ACK */
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}

/* 第9步:读取数据 */
while (no)
{
	data1 = I2C_ReceiveByte(0);	
	I2C_Ack();
	data2 = I2C_ReceiveByte(0);
	I2C_Ack();
	Word_Data[i][0] = (((uint16_t)data1 << 8) | data2);  //

	
	data1 = I2C_ReceiveByte(0);	
	I2C_Ack();
	data2 = I2C_ReceiveByte(0);
	if(1==no)
		I2C_NoAck();	/* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
	else
		I2C_Ack();
	Word_Data[i][1] = (((uint16_t)data1 << 8) | data2); 

	no--;	
	i++;
}
/* 发送I2C总线停止信号 */
I2C_Stop();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

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

void max30102_FIFO_ReadBytes(uint8_t Register_Address,uint8_t* Data)
{
max30102_Bus_Read(REG_INTR_STATUS_1);
max30102_Bus_Read(REG_INTR_STATUS_2);

/* 第1步:发起I2C总线启动信号 */
I2C_Start();

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

/* 第3步:发送ACK */
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}

/* 第4步:发送字节地址, */
I2C_SendByte((uint8_t)Register_Address);
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}


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

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

/* 第8步:发送ACK */
if (I2C_WaitAck() != 0)
{
	goto cmd_fail;	/* EEPROM器件无应答 */
}

/* 第9步:读取数据 */
Data[0] = I2C_ReceiveByte(1);	
Data[1] = I2C_ReceiveByte(1);	
Data[2] = I2C_ReceiveByte(1);	
Data[3] = I2C_ReceiveByte(1);
Data[4] = I2C_ReceiveByte(1);	
Data[5] = I2C_ReceiveByte(0);
/* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */
/* 发送I2C总线停止信号 */
I2C_Stop();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

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

void max30102_init(void)
{

max30102_reset();

if(max30102_Bus_Write(REG_INTR_ENABLE_1,0xc0)==0)
{
	printf("1");
}		                                        // INTR setting
HAL_Delay(10);
if(max30102_Bus_Write(REG_INTR_ENABLE_2,0x00)==0)
{
	printf("2");
}		
HAL_Delay(10);
if(max30102_Bus_Write(REG_FIFO_WR_PTR,0x00)==0)
{
	printf("3");
}		                                          	//FIFO_WR_PTR[4:0]
HAL_Delay(10);
if(max30102_Bus_Write(REG_OVF_COUNTER,0x00)==0)  	//OVF_COUNTER[4:0]
{
	printf("4");
}		
HAL_Delay(10);
if(max30102_Bus_Write(REG_FIFO_RD_PTR,0x00)==0)  	//FIFO_RD_PTR[4:0]
{
	printf("5");
}		
HAL_Delay(10);
if(max30102_Bus_Write(REG_FIFO_CONFIG,0x0f)==0)  	//sample avg = 1, fifo rollover=false, fifo almost full = 17
{
	printf("6");
}		
HAL_Delay(10);
if(max30102_Bus_Write(REG_MODE_CONFIG,0x03)==0)  	//0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
{
	printf("7");
}		
HAL_Delay(10);
if(max30102_Bus_Write(REG_SPO2_CONFIG,0x27)==0)  	// SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS) 
{
	printf("8");
}		
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

HAL_Delay(10);
if(max30102_Bus_Write(REG_LED1_PA,0x24)==0) //Choose value for ~ 7mA for LED1
{
printf(“9”);
}
HAL_Delay(10);
if(max30102_Bus_Write(REG_LED2_PA,0x24)==0) // Choose value for ~ 7mA for LED2
{
printf(“10”);
}
HAL_Delay(10);
if(max30102_Bus_Write(REG_PILOT_PA,0x7f)==0) // Choose value for ~ 25mA for Pilot LED
{
printf(“11”);
}
HAL_Delay(10);
}

void max30102_reset(void)
{
max30102_Bus_Write(REG_MODE_CONFIG,0x40);
max30102_Bus_Write(REG_MODE_CONFIG,0x40);
}

void maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)
{
IIC_Write_One_Byte(I2C_WRITE_ADDR,uch_addr,uch_data);
}

void maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)
{

IIC_Read_One_Byte(I2C_WRITE_ADDR,uch_addr,puch_data);
  • 1

}

void maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
{
uint32_t un_temp;
unsigned char uch_temp;
char ach_i2c_data[6];
*pun_red_led=0;
*pun_ir_led=0;

//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);

IIC_ReadBytes(I2C_WRITE_ADDR,REG_FIFO_DATA,(uint8_t *)ach_i2c_data,6);

un_temp=(unsigned char) ach_i2c_data[0];
un_temp<<=16;
*pun_red_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data[1];
un_temp<<=8;
*pun_red_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data[2];
*pun_red_led+=un_temp;

un_temp=(unsigned char) ach_i2c_data[3];
un_temp<<=16;
*pun_ir_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data[4];
un_temp<<=8;
*pun_ir_led+=un_temp;
un_temp=(unsigned char) ach_i2c_data[5];
*pun_ir_led+=un_temp;
*pun_red_led&=0x03FFFF; //Mask MSB [23:18]
*pun_ir_led&=0x03FFFF; //Mask MSB [23:18]
}


iic驱动代码


max\_iic.h



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

#ifndef _MAX_IIC_H
#define _MAX_IIC_H

#include “stm32l1xx_hal.h”
#include “stdint.h”
#include “main.h”

#define SCL_H HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET)
#define SCL_L HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET)

#define SDA_H HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET)
#define SDA_L HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_RESET)
#define MAX_INT_H HAL_GPIO_WritePin(MAX_INT_GPIO_Port, MAX_INT_Pin, GPIO_PIN_SET)
#define SCL_read HAL_GPIO_ReadPin(SCL_GPIO_Port,SCL_Pin)
#define SDA_read HAL_GPIO_ReadPin(SDA_GPIO_Port,SDA_Pin)
#define MAX_INT_read HAL_GPIO_ReadPin(MAX_INT_GPIO_Port,MAX_INT_Pin)
#define bool int
#define TRUE 1
#define FALSE 0

void I2C_delay(void);
bool I2C_Start(void);
void I2C_Stop(void) ;
void I2C_Ack(void);
void I2C_NoAck(void);
uint8_t I2C_WaitAck(void);
void I2C_SendByte(uint8_t SendByte);
uint8_t I2C_ReceiveByte(uint8_t ack);
bool I2C_Write(uint8_t dev,uint8_t WriteAddr,uint8_t WriteData);
bool I2C_Write2(uint8_t WriteAddr,uint8_t WriteData);
uint8_t I2C_Read(uint8_t dev,uint8_t WriteAddr);
uint8_t I2C_Read2(uint8_t WriteAddr) ;
void I2C_DevRead(uint8_t devaddr,uint8_t addr,uint8_t len,uint8_t rbuf);
void I2C_DevWrite(uint8_t devaddr,uint8_t addr,uint8_t len,uint8_t wbuf);
void IIC_WriteBytes(uint8_t WriteAddr,uint8_t
data,uint8_t dataLength);
void IIC_ReadBytes(uint8_t deviceAddr, uint8_t writeAddr,uint8_t
data,uint8_t dataLength);
void IIC_Read_One_Byte(uint8_t daddr,uint8_t addr,uint8_t* data);
void IIC_Write_One_Byte(uint8_t daddr,uint8_t addr,uint8_t data);
#endif


 max\_iic.c



  • 1
  • 2
  • 3
  • 4
  • 5

#include “max_iic.h”

void I2C_delay(void)
{
uint16_t i=160; //Set delay time value
while(i)
{
i–;
}
}
/**

  • @brief I2C Start
  • @param None
  • @retval None
    /
    bool I2C_Start(void)
    {
    SDA_H;
    I2C_delay();
    SCL_H;
    I2C_delay();
    if(!SDA_read)return FALSE; //SDA Always low return FALSE
    SDA_L;
    I2C_delay();
    if(SDA_read) return FALSE; //SDA Always high return FALSE
    SCL_L;
    I2C_delay();
    return TRUE;
    }
    /
    *
  • @brief I2C Stop
  • @param None
  • @retval None
    /
    void I2C_Stop(void)
    {
    SCL_L;
    I2C_delay();
    SDA_L;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SDA_H;
    I2C_delay();
    }
    /
    *
  • @brief I2C Ack
  • @param None
  • @retval None
    */
    void I2C_Ack(void)
    {
    SCL_L;
    I2C_delay();
    SDA_L;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SCL_L;
    I2C_delay();

}
/**

  • @brief I2C No Ack
  • @param None
  • @retval None
    /
    void I2C_NoAck(void)
    {
    SCL_L;
    I2C_delay();
    SDA_H;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SCL_L;
    I2C_delay();
    }
    /
    *
  • @brief Wait Ack
  • @param None
  • @retval bool FALSE:1—>no ACK
  •          TRUE :0--->ACK
    
    • 1

/
uint8_t I2C_WaitAck(void)
{
uint8_t re;
SCL_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
re=1;
}
else re=0;
SCL_L;
return re;
}
/
*

  • @brief Send one Byte
  • @param uint8_t SendByte
  • @retval None
    */
    void I2C_SendByte(uint8_t SendByte)
    {
    uint8_t i=8;

while(i–)
{
SCL_L;
I2C_delay();
if((SendByte&0x80))
{
SDA_H;
}
else
{
SDA_L;
}
SendByte<<=1;
I2C_delay();
SCL_H;
I2C_delay();

}
SCL_L;
}
/**

  • @brief Receive one Byte
  • @param uint8_t ack
  • @retval receive receive one byte
    /
    uint8_t I2C_ReceiveByte(uint8_t ack)
    {
    unsigned char i=8,receive=0;
    SDA_H;
    while(i–)
    {
    receive<<=1;
    SCL_L;
    I2C_delay();
    SCL_H;
    I2C_delay();
    if(SDA_read)
    {
    receive|=0x01;
    }
    }
    SCL_L;
    if (!ack)
    I2C_NoAck(); //Send Nack
    else
    I2C_Ack(); //Send ack
    return receive;
    }
    /
    *
  • @brief Write a Byte to the device
  • @param uint8_t WriteAddr,uint8_t WriteData
  • @retval bool FALSE: 0
  •          TRUE : 1
    
    • 1

*/
bool I2C_Write(uint8_t dev,uint8_t WriteAddr,uint8_t WriteData)
{
I2C_Start();
I2C_SendByte(dev); //Send write cmd
I2C_WaitAck();
I2C_SendByte(WriteAddr); //Send addr
I2C_WaitAck();
I2C_SendByte(WriteData); //Send data
I2C_WaitAck();
I2C_Stop(); //iic stop
return TRUE;
}
/********************************************************************/
bool I2C_Write2(uint8_t WriteAddr,uint8_t WriteData)
{
if (!I2C_Start()) return FALSE;
I2C_SendByte(0x10);//设置器件地址+段地址
if (!I2C_WaitAck())
{
I2C_Stop();
return FALSE;
}
I2C_SendByte(WriteAddr); //设置段内地址
I2C_WaitAck();

	I2C_SendByte(WriteData); 
	I2C_WaitAck(); 
	I2C_Stop(); 

	return TRUE; 
  • 1
  • 2
  • 3
  • 4
  • 5

}
/**********************************************************************/
/

  • @brief Read a byte from the device

  • @param uint8_t WriteAddr

  • @retval temp Return the read byte
    */
    uint8_t I2C_Read(uint8_t dev,uint8_t WriteAddr)
    {
    uint8_t temp=0;
    I2C_Start();
    I2C_SendByte(dev); //Send write cmd
    I2C_WaitAck();
    I2C_SendByte(WriteAddr); //Send addr
    I2C_WaitAck();

    I2C_Start();
    I2C_SendByte(dev|1); //Send read cmd
    I2C_WaitAck();
    temp=I2C_ReceiveByte(0);
    I2C_Stop();
    return temp;
    }
    /*********************************************************************************/
    //读出1串数据
    uint8_t I2C_Read2(uint8_t WriteAddr)
    {
    uint8_t tempDat=0;
    if (!I2C_Start()) return FALSE;
    I2C_SendByte(0x77);//设置器件地址+段地址

if (!I2C_WaitAck())
{
I2C_Stop();
return FALSE;
}
I2C_SendByte(WriteAddr); //设置低起始地址
I2C_WaitAck();
I2C_Start();
I2C_SendByte(0x77 | 0x01);
I2C_WaitAck();
tempDat = I2C_ReceiveByte(0);
I2C_Stop();

	return tempDat; 
  • 1

}
/**

  • @brief Read continuously

  • @param uint8_t devaddr device addr

  •    uint8_t addr     Start addr 
    
    • 1
  •    uint8_t len      read data length
    
    • 1
  •    uint8_t *rbuf    read data buf 
    
    • 1
  • @retval None
    */
    void I2C_DevRead(uint8_t devaddr,uint8_t addr,uint8_t len,uint8_t *rbuf)
    {
    int i=0;
    I2C_Start();
    I2C_SendByte(devaddr);
    if(!I2C_WaitAck())
    {
    I2C_Stop();
    return ;
    }
    I2C_SendByte(addr); //address ++
    if(!I2C_WaitAck())
    {
    I2C_Stop();
    return ;
    }
    I2C_Start();
    I2C_SendByte(devaddr|0x01);
    if(!I2C_WaitAck())
    {
    I2C_Stop();
    return ;
    }
    for(i=0; i<len; i++)
    {

    if(i==len-1)
    {
    	rbuf[i]=I2C_ReceiveByte(0);  //The last byte does not answer
    }
    else
    	rbuf[i]=I2C_ReceiveByte(1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    }
    I2C_Stop( );
    }

/**

  • @brief Write continuously
  • @param uint8_t devaddr device addr
  •    uint8_t addr     Start addr 
    
    • 1
  •    uint8_t len      read data length
    
    • 1
  •    uint8_t *rbuf    read data buf 
    
    • 1
  • @retval None
    */
    void I2C_DevWrite(uint8_t devaddr,uint8_t addr,uint8_t len,uint8_t *wbuf)
    {
    int i=0;
    I2C_Start();
    I2C_SendByte(devaddr);
    I2C_WaitAck();
    I2C_SendByte(addr); //address ++
    I2C_WaitAck();
    for(i=0; i<len; i++)
    {
    I2C_SendByte(wbuf[i]);
    I2C_WaitAck();
    }
    I2C_Stop( );
    }

//==========================================================

void IIC_WriteBytes(uint8_t WriteAddr,uint8_t* data,uint8_t dataLength)
{
uint8_t i;
I2C_Start();

I2C_SendByte(WriteAddr);	    //发送写命令
I2C_WaitAck();

for(i=0;i<dataLength;i++)
{
	I2C_SendByte(data[i]);
	I2C_WaitAck();
}				    	   
I2C_Stop();//产生一个停止条件 
I2C_delay(); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

}

void IIC_ReadBytes(uint8_t deviceAddr, uint8_t writeAddr,uint8_t* data,uint8_t dataLength)
{
uint8_t i;
I2C_Start();

I2C_SendByte(deviceAddr);	    //发送写命令
I2C_WaitAck();
I2C_SendByte(writeAddr);
I2C_WaitAck();
I2C_SendByte(deviceAddr|0X01);//进入接收模式			   
I2C_WaitAck();

for(i=0;i<dataLength-1;i++)
{
	data[i] = I2C_ReceiveByte(1);
}		
data[dataLength-1] = I2C_ReceiveByte(0);	
I2C_Stop();//产生一个停止条件 
I2C_delay();	 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

}

void IIC_Read_One_Byte(uint8_t daddr,uint8_t addr,uint8_t* data)
{
I2C_Start();

I2C_SendByte(daddr);	   //发送写命令
I2C_WaitAck();
I2C_SendByte(addr);//发送地址
I2C_WaitAck();		 
I2C_Start();  	 	   
I2C_SendByte(daddr|0X01);//进入接收模式			   
I2C_WaitAck();	 
*data = I2C_ReceiveByte(0);		   
I2C_Stop();//产生一个停止条件	    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

}

void IIC_Write_One_Byte(uint8_t daddr,uint8_t addr,uint8_t data)
{
I2C_Start();

I2C_SendByte(daddr);	    //发送写命令
I2C_WaitAck();
I2C_SendByte(addr);//发送地址
I2C_WaitAck();	   	 										  		   
I2C_SendByte(data);     //发送字节							   
I2C_WaitAck();  		    	   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

I2C_Stop();//产生一个停止条件
I2C_delay();
}


main.c  



  • 1
  • 2
  • 3
  • 4
  • 5

/* Includes ------------------------------------------------------------------*/
#include “main.h”
#include “stm32l1xx_hal.h”
#include “usart.h”
#include “gpio.h”

/* USER CODE BEGIN Includes /
#include “max30102.h”
#include “algorithm.h”
/
USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV /
/
Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/* USER CODE BEGIN PFP /
/
Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */
uint32_t aun_ir_buffer[500]; //IR LED sensor data
uint16_t n_ir_buffer_length; //data length
uint32_t aun_red_buffer[500]; //Red LED sensor data
int16_t n_sp02; //SPO2 value
int8_t ch_spo2_valid; //indicator to show if the SP02 calculation is valid
int16_t n_heart_rate; //heart rate value
int8_t ch_hr_valid; //indicator to show if the heart rate calculation is valid

#define MAX_BRIGHTNESS 255

/* USER CODE END 0 */

int main(void)
{

/* USER CODE BEGIN 1 /
uint32_t un_min, un_max;
int i;
uint8_t temp[6];
uint8_t dis_hr=0,dis_spo2=0;
/
USER CODE END 1 */

/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();

/* USER CODE BEGIN 2 /
printf(“System Running\r\n”);
/
USER CODE END 2 */

/* Infinite loop /
/
USER CODE BEGIN WHILE */
MAX_INT_H;
max30102_init();

printf("\r\n MAX30102  init  \r\n");
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(MAX_INT_read==1);   //wait until the interrupt pin asserts
    
	max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
	aun_ir_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
	aun_red_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

// aun_ir_buffer[i]
//maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i)); //read from MAX30102 FIFO
if(un_min>aun_red_buffer[i])
un_min=aun_red_buffer[i]; //update signal min
if(un_max<aun_red_buffer[i])
un_max=aun_red_buffer[i]; //update signal max
printf(“red=”);
printf(“%i”, aun_red_buffer[i]);
printf(“, ir=”);
printf(“%i\n\r”, aun_ir_buffer[i]);
}
// un_prev_data=aun_red_buffer[i];
//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);

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[i-100]=aun_red_buffer[i];
        aun_ir_buffer[i-100]=aun_ir_buffer[i];
        
        //update the signal min and max
        if(un_min>aun_red_buffer[i])
        un_min=aun_red_buffer[i];
        if(un_max<aun_red_buffer[i])
        un_max=aun_red_buffer[i];
    }
	//take 100 sets of samples before calculating the heart rate.
    for(i=400;i<500;i++)
    {
        while(MAX_INT_read==1);
        max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
		aun_ir_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
	aun_red_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
		//send samples and calculation result to terminal program through UART
		if(ch_hr_valid == 1 && ch_spo2_valid ==1 && (n_heart_rate-100)<120 && n_sp02<101 && n_heart_rate>140)//**/ ch_hr_valid == 1 && ch_spo2_valid ==1 && (n_heart_rate-100)<120 && n_sp02<101
		{
			dis_hr = n_heart_rate-100;   //这个-100我加的
			dis_spo2 = n_sp02;
			printf("HR=%i, ", dis_hr); 
			printf("HRvalid=%i, ", ch_hr_valid);
			printf("SpO2=%i, ", dis_spo2);
			printf("SPO2Valid=%i\r\n", ch_spo2_valid);
		}
		else
		{
			dis_hr = 0;
			dis_spo2 = 0;
		}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

ber
aun_red_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5]; // Combine values to get the actual number
//send samples and calculation result to terminal program through UART
if(ch_hr_valid == 1 && ch_spo2_valid ==1 && (n_heart_rate-100)<120 && n_sp02<101 && n_heart_rate>140)//**/ ch_hr_valid == 1 && ch_spo2_valid ==1 && (n_heart_rate-100)<120 && n_sp02<101
{
dis_hr = n_heart_rate-100; //这个-100我加的
dis_spo2 = n_sp02;
printf("HR=%i, ", dis_hr);
printf("HRvalid=%i, ", ch_hr_valid);
printf("SpO2=%i, ", dis_spo2);
printf(“SPO2Valid=%i\r\n”, ch_spo2_valid);
}
else
{
dis_hr = 0;
dis_spo2 = 0;
}

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
[外链图片转存中…(img-SkKlSbXv-1715793481344)]
[外链图片转存中…(img-nyjZQEBG-1715793481344)]

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/1020338
推荐阅读
相关标签
  

闽ICP备14008679号