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年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!