STM32学习值传感器篇——max30102心率血氧传感器_max10302 stm32,看完直接怼产品经理

103 阅读4分钟
        i++;
}

}

void maxim_remove_close_peaks(int32_t *pn_locs, int32_t pn_npks, int32_t pn_x, int32_t n_min_distance) /

  • \brief Remove peaks

  • \par Details

  •           Remove peaks separated by less than MIN_DISTANCE
    
  • \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)
    
  • \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)
    
  • \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



#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



#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;	/* 执行成功 */

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值 */

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

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

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");
}		

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

}

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



#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



#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
    

/ 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
    

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

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

  • @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; 

} /**

  • @brief Read continuously

  • @param uint8_t devaddr device addr

  •    uint8_t addr     Start addr 
    
  •    uint8_t len      read data length
    
  •    uint8_t *rbuf    read data buf 
    
  • @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);
    

    } I2C_Stop( ); }

/**

  • @brief Write continuously
  • @param uint8_t devaddr device addr
  •    uint8_t addr     Start addr 
    
  •    uint8_t len      read data length
    
  •    uint8_t *rbuf    read data buf 
    
  • @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(); 

}

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

}

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();//产生一个停止条件	    

}

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

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


main.c  



/* 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

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

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

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

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

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