MAX30102的STM32驱动程序
效果演示:

CSDN演示专用 MAX30102

程序实现心率计算,心率波形显示,血氧计算。
下载文件中包含程序源码和PCB工程文件,PCB工程文件成品如演示视频,除基本功能外加入锂电池供电和充电功能。
源码过多,只展示了部分,全部源码下载链接:
CSDN:
https://download.csdn.net/download/qq_19534483/20368390
百度云:
链接:https://pan.baidu.com/s/1SFQCT1Nd2H6Dm05Rs2tHQA 提取码:hss2
github:
https://github.com/ahukl1/MAX30102.git

部分源码如下:
MAX30102.c:

int maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data){HAL_I2C_Mem_Write(&hi2c1, I2C_WRITE_ADDR,uch_addr, I2C_MEMADD_SIZE_8BIT,&uch_data,1, 1000);
}int maxim_max30102_reset()
{maxim_max30102_write_reg(REG_MODE_CONFIG,0x40);maxim_max30102_write_reg(REG_MODE_CONFIG,0x03);
maxim_max30102_write_reg(REG_INTR_ENABLE_1,0x40); // INTR settingmaxim_max30102_write_reg(REG_INTR_ENABLE_2,0x50);maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00); //FIFO_WR_PTR[4:0]maxim_max30102_write_reg(REG_OVF_COUNTER,0x00);  //OVF_COUNTER[4:0]maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00) ; //FIFO_RD_PTR[4:0]maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f);  //sample avg = 1, fifo rollover=false, fifo almost full = 17
maxim_max30102_write_reg(REG_MODE_CONFIG,0x03)  ; //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LEDmaxim_max30102_write_reg(REG_SPO2_CONFIG,0x27);  // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)
maxim_max30102_write_reg(REG_LED1_PA,0x24) ;  //Choose value for ~ 7mA for LED1
maxim_max30102_write_reg(REG_LED2_PA,0x24) ;  // Choose value for ~ 7mA for LED2
maxim_max30102_write_reg(REG_PILOT_PA,0x7f) ;  // Choose value for ~ 25mA for Pilot LEDmaxim_max30102_write_reg(0x03,0x00);maxim_max30102_write_reg(0x21,0x01);}

MAX30102.h:

#define I2C_WRITE_ADDR 0xAE
#define I2C_READ_ADDR 0xAF
#include "main.h"
//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
extern I2C_HandleTypeDef hi2c1;
int maxim_max30102_reset();
#endif

oled.c:

struct oled_pot * start_pot[8];
void write(unsigned char data,int type){switch(type){case 0:HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);break;case 1:HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);break;}HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1,&data,1,1000);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
}
void OLED_WrCmd(uint8_t command){write(command,0);
}
void OLED_WrData(uint8_t data){write(data,1);
}
void OLED_Init(){HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);HAL_Delay(100);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);unsigned int a;for(a=0;a<5000;a++);OLED_WrCmd(0xAE);//--turn off oled panelOLED_WrCmd(0x00);//---set low column addressOLED_WrCmd(0x10);//---set high column addressOLED_WrCmd(0x40);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)OLED_WrCmd(0xB0);OLED_WrCmd(0x81);//--set contrast control registerOLED_WrCmd(0xFF); // Set SEG Output Current BrightnessOLED_WrCmd(0xa1);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常OLED_WrCmd(0xc8);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常OLED_WrCmd(0xa6);//--set normal displayOLED_WrCmd(0xa8);//--set multiplex ratio(1 to 64)OLED_WrCmd(0x3f);//--1/64 duty``OLED_WrCmd(0xd3);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)OLED_WrCmd(0x00);//-not offsetOLED_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequencyOLED_WrCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/SecOLED_WrCmd(0xd9);//--set pre-charge periodOLED_WrCmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 ClockOLED_WrCmd(0xda);//--set com pins hardware configurationOLED_WrCmd(0x12);OLED_WrCmd(0xdb);//--set vcomhOLED_WrCmd(0x40);//Set VCOM Deselect LevelOLED_WrCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)OLED_WrCmd(0x02);//OLED_WrCmd(0x8d);//--set Charge Pump enable/disableOLED_WrCmd(0x14);//--set(0x10) disableOLED_WrCmd(0xa4);// Disable Entire Display On (0xa4/0xa5)OLED_WrCmd(0xa6);// Disable Inverse Display On (0xa6/a7)OLED_WrCmd(0xaf);//--turn on oled panelOLED_Clear();//OLED清屏
}
void OLED_Clear(void){
unsigned char i,n;for(i=0; i<8; i++){OLED_WrCmd(0xb0+i); //设置页地址(0~7)OLED_WrCmd(0x00); //设置显示位置—列低地址OLED_WrCmd(0x10); //设置显示位置—列高地址for(n=0; n<128; n++) OLED_WrData(0x00); //写0x00到屏幕寄存器上}
}
void OLED_Start(void){unsigned char i,n;for(i=0; i<8; i++){OLED_WrCmd(0xb0+i); //设置页地址(0~7)OLED_WrCmd(0x00); //设置显示位置—列低地址OLED_WrCmd(0x10); //设置显示位置—列高地址for(n=0; n<128; n++)   OLED_WrData(start[i][n]); //写0x00到屏幕寄存器上}
}
void OLED_Close_page(void){unsigned char i,n;for(i=0; i<8; i++){OLED_WrCmd(0xb0+i); //设置页地址(0~7)OLED_WrCmd(0x00); //设置显示位置—列低地址OLED_WrCmd(0x10); //设置显示位置—列高地址for(n=0; n<128; n++)  OLED_WrData(close_img[i][n]); //写0x00到屏幕寄存器上}
}
void OLED_page2(void){
unsigned char i,n;for(i=0; i<8; i++){OLED_WrCmd(0xb0+i); //设置页地址(0~7)OLED_WrCmd(0x00); //设置显示位置—列低地址OLED_WrCmd(0x10); //设置显示位置—列高地址for(n=0; n<128; n++) OLED_WrData(page_2[i][n]); //写0x00到屏幕寄存器上}
}
void OLED_SetPos(uint8_t x, uint8_t y){WriteCmd(0xb0+y);WriteCmd(((x&0xf0)>>4)|0x10);WriteCmd(x&0x0f);
}
void OLED_DrawPoint(unsigned char x,unsigned char y)
{unsigned char pos,bx,temp=0;if(x>127||y>63)return;//超出范围了.pos=7-y/8;bx=y%8;temp=1<<(7-bx);OLED_SetPos(x,pos);OLED_WrData(temp);}
void OLED_ON(void){WriteCmd(0X8D);  //设置电荷泵WriteCmd(0X14);  //开启电荷泵WriteCmd(0XAF);  //OLED唤醒}
void OLED_OFF(void){WriteCmd(0X8D);  //设置电荷泵WriteCmd(0X10);  //关闭电荷泵WriteCmd(0XAE);  //OLED休眠
}
void OLED_ShowChar(int x,int y,char txt[]){int i,j;y=y*8;OLED_WrCmd(0xb0+2*x);OLED_WrCmd(0x10|((0xf0&y)>>4));OLED_WrCmd(0x00|(0x0f&y));for(i=0;txt[i]!='\0';i++){if(txt[i]-' '<0||txt[i]-' '>94) continue;for(j=0;j<8;j++){OLED_WrData(asc2_1206[txt[i]-' '][j]);}}OLED_WrCmd(0xb0+2*x+1);OLED_WrCmd(0x10|((0xf0&y)>>4));OLED_WrCmd(0x00|(0x0f&y));for(i=0;txt[i]!='\0';i++){if(txt[i]-' '<0||txt[i]-' '>94) continue;for(j=0;j<8;j++){OLED_WrData(asc2_1206[txt[i]-' '][j+8]);}}
}
void OLED_ShowWord(int x,int y,int f){int i,j;y=y*8;OLED_WrCmd(0xb0+2*x);OLED_WrCmd(0x10|((0xf0&y)>>4));OLED_WrCmd(0x00|(0x0f&y));for(i=0;i<16;i++){OLED_WrData(word[f][i]);}OLED_WrCmd(0xb0+2*x+1);OLED_WrCmd(0x10|((0xf0&y)>>4));OLED_WrCmd(0x00|(0x0f&y));for(i=0;i<16;i++){OLED_WrData(word[f][i+16]);}
}
void OLED_ShowNum(int y,int x,int num)
{int j;x=x*8;OLED_WrCmd(0xb0+2*y);OLED_WrCmd(0x10|((0xf0&x)>>4));OLED_WrCmd(0x00|(0x0f&x));for(j=0;j<8;j++){OLED_WrData(font_num[num][j]);}OLED_WrCmd(0xb0+2*y+1);OLED_WrCmd(0x10|((0xf0&x)>>4));OLED_WrCmd(0x00|(0x0f&x));for(j=0;j<8;j++){OLED_WrData(font_num[num][j+8]);}
}
void OLED_ShowNums(int y,int x,int num,int len)
{int i;int dat;dat=num;for (i=0;i<len;i++){OLED_ShowNum(y,x+len-i-1,dat%10);dat=dat/10;}
}

main.c:

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under Ultimate Liberty license* SLA0044, the "License"; You may not use this file except in compliance with* the License. You may obtain a copy of the License at:*                             www.st.com/SLA0044********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"
#include "MAX30102.h"
#include "stdio.h"
#include "oled.h"
char data_save;
int heart;
int red_reg[200];
int led_reg[200];
int heart_reg;
char online=1;
int reg_num=0;
int reg_heart=1;
unsigned char pData[8];
float spo2;
int flag=3;
unsigned char char_show=0;
I2C_HandleTypeDef hi2c1;SPI_HandleTypeDef hspi1;UART_HandleTypeDef huart1;osThreadId_t defaultTaskHandle;
#ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printfset to 'Yes') calls __io_putchar() */#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{/* Place your implementation of fputc here *//* e.g. write a character to the USART */huart1.Instance->DR = (uint8_t) ch;/* Loop until the end of transmission */while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET){}return ch;
}
const osThreadAttr_t defaultTask_attributes = {.name = "defaultTask",.priority = (osPriority_t) osPriorityNormal,.stack_size = 128 * 4
};
osThreadId_t myTask02Handle;
const osThreadAttr_t myTask02_attributes = {.name = "myTask02",.priority = (osPriority_t) osPriorityLow,.stack_size = 128 * 6
};
osThreadId_t myTask03Handle;
const osThreadAttr_t myTask03_attributes = {.name = "myTask03",.priority = (osPriority_t) osPriorityLow,.stack_size = 128 * 4
};
osThreadId_t myTask04Handle;
const osThreadAttr_t myTask04_attributes = {.name = "myTask04",.priority = (osPriority_t) osPriorityLow,.stack_size = 128 * 4
};
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_SPI1_Init(void);
static void MX_USART1_UART_Init(void);
void StartDefaultTask(void *argument);
void StartTask02(void *argument);
void StartTask03(void *argument);
void StartTask04(void *argument);int main(void)
{/* USER CODE BEGIN 1 *//* 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_I2C1_Init();MX_SPI1_Init();MX_USART1_UART_Init();OLED_Init();osKernelInitialize();defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);myTask02Handle = osThreadNew(StartTask02, NULL, &myTask02_attributes);myTask03Handle = osThreadNew(StartTask03, NULL, &myTask03_attributes);myTask04Handle = osThreadNew(StartTask04, NULL, &myTask04_attributes);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS *//* Start scheduler */maxim_max30102_reset();osKernelStart();/* We should never get here as control is now taken by the scheduler *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage*/__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV2;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK){Error_Handler();}
}static void MX_I2C1_Init(void)
{/* USER CODE BEGIN I2C1_Init 0 *//* USER CODE END I2C1_Init 0 *//* USER CODE BEGIN I2C1_Init 1 *//* USER CODE END I2C1_Init 1 */hi2c1.Instance = I2C1;hi2c1.Init.ClockSpeed = 100000;hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;hi2c1.Init.OwnAddress1 = 0;hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;hi2c1.Init.OwnAddress2 = 0;hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;if (HAL_I2C_Init(&hi2c1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN I2C1_Init 2 *//* USER CODE END I2C1_Init 2 */}static void MX_SPI1_Init(void)
{/* USER CODE BEGIN SPI1_Init 0 *//* USER CODE END SPI1_Init 0 *//* USER CODE BEGIN SPI1_Init 1 *//* USER CODE END SPI1_Init 1 *//* SPI1 parameter configuration*/hspi1.Instance = SPI1;hspi1.Init.Mode = SPI_MODE_MASTER;hspi1.Init.Direction = SPI_DIRECTION_2LINES;hspi1.Init.DataSize = SPI_DATASIZE_8BIT;hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;hspi1.Init.NSS = SPI_NSS_SOFT;hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi1.Init.TIMode = SPI_TIMODE_DISABLE;hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi1.Init.CRCPolynomial = 10;if (HAL_SPI_Init(&hspi1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN SPI1_Init 2 *//* USER CODE END SPI1_Init 2 */}static void MX_USART1_UART_Init(void)
{/* USER CODE BEGIN USART1_Init 0 *//* USER CODE END USART1_Init 0 *//* USER CODE BEGIN USART1_Init 1 *//* USER CODE END USART1_Init 1 */huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN USART1_Init 2 *//* USER CODE END USART1_Init 2 */}static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);/*Configure GPIO pin : PC13 */GPIO_InitStruct.Pin = GPIO_PIN_13;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);/*Configure GPIO pin : PC13 */GPIO_InitStruct.Pin = GPIO_PIN_0;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);/*Configure GPIO pin : PC13 */GPIO_InitStruct.Pin = GPIO_PIN_1;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}void StartDefaultTask(void *argument)
{float r;float red;float led;int red_last=0;int led_last=0;int cha=0;int reg_num1=0;int reg_num2=0;int pot_i=0;while (1){HAL_I2C_Mem_Read(&hi2c1,I2C_READ_ADDR,REG_FIFO_DATA,I2C_MEMADD_SIZE_8BIT,(unsigned char *)pData,8,1000);red=(red+(((pData[3]&0x03)<<16)|(pData[4]<<8)|(pData[5])))/2;led=(led+(((pData[0]&0x03)<<16)|(pData[1]<<8)|(pData[2])))/2;if(red>5000){     //判断采集状态if(flag!=1) {OLED_Clear();flag=1;}online=1;cha=(cha+red-red_last)/2;  //求导if(cha<-10){data_save=data_save<<1|0;}else data_save=data_save<<1|1;r=red/led;spo2=-45.060*r*r+30.354*r + 94.845;if(pot_i<128){                                                         //波形图显示OLED_DrawPoint(++pot_i,25-cha/6);}      //波形显示过大可把12调大,波形过小可调小12else {OLED_Clear();pot_i=0;}}else {if(flag!=0) {OLED_Clear();flag=0;OLED_Clear();pot_i=0;data_save=0xff;heart=0;online=0;reg_heart=0;reg_num=0;spo2=0;}OLED_ShowChar(1,2,"No FINGER!");}printf("a:%d,%d,%f,%f\n",cha,heart,red,spo2);red_last=red;maxim_max30102_write_reg(0x21,0x01);vTaskDelay(10);}
}
void StartTask02(void *argument)
{while(1){if(char_show==0){OLED_ShowChar(3,0,"H:");OLED_ShowNums(3,2,heart,3);OLED_ShowChar(3,6,"Spo2:");OLED_ShowNums(3,11,spo2,3);vTaskDelay(10);}}
}
void StartTask03(void *argument)
{int last;int now;int c;int num=1;while(1){if((data_save&0xf0)==0x00){now=HAL_GetTick();if(now<last){c=(0xffffffff-last+now);}else c=(now-last);if(c>=300){heart=60000/c;last=now;reg_heart=(reg_heart*reg_num+heart)/(reg_num+1);if(reg_num==30){heart_reg=reg_heart;reg_num=0;reg_heart=0;}elsereg_num++;}}}
}
void StartTask04(void *argument)
{for(;;){osDelay(1);}}
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state *//* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

源码过多,只展示了部分,全部源码下载链接:
https://download.csdn.net/download/qq_19534483/20368390

MAX30102的STM32驱动程序相关推荐

  1. stm32 2.4寸 TFT 触摸屏STM32驱动程序 2.4inch Arduino Display

    stm32 2.4寸 TFT 触摸屏STM32驱动程序 2.4inch Arduino Display 今日为准备一项比赛,选购了一款2.4寸 8位并口通信的TFT触摸屏,此屏幕原本是专为arduin ...

  2. ADS1015使用指南及STM32驱动程序

    ADS1015使用指南及驱动程序 ADS1015使用指南 简介 ADS1015的引脚介绍 ADS1015的寄存器介绍 寄存器相关配置 驱动程序 ADS1015使用指南 由于网上关于TI公司的ADS10 ...

  3. (标准库)直流无刷电机驱动(1)——简介及STM32驱动程序

    有朋友想看部分讲解可以(标准库)直流无刷电机驱动(2)--霍尔传感器定时器初始化 (标准库)直流无刷电机驱动(3)--霍尔传感器状态获取 ------------------------------- ...

  4. ADS8685/ADS8681/ADS8689的stm32驱动程序

    我在做ad的八路采集模块,用的是多路复用器配合芯片ads8685实现的,但在驱动ads8685芯片的时候费了不少时间,我把自己研究的驱动代码分享给大家,希望能够帮助大家做开发!

  5. AM2302+STM32驱动程序

    AM2302是一款通过数字信号输出来测量空气温湿度的传感器,可测量0~99.9%RH范围内的湿度,精度为±2%RH,分辨度为0.1 RH:可测量-40℃~80℃范围内的温度,精度为±0.5℃,分辨度为 ...

  6. STM32+ MAX30102通过指尖测量心率+血氧饱和度

    一.前言 重要的事情放在最前面:max30102只适用于指尖手指测量,不适用与手腕手指测量,如需做成可穿戴样式选择传感器的小伙伴请pass掉他,因为他只有红光和红外2种光,不够充足的数据源去运算. 由 ...

  7. 基于STM32的GPS模块驱动(AIR530)

    一.概述 由于做项目要用到GPS定位,于是在某宝购买了这款GPS模块.项目采用的MCU是STM32.废话少说,进入正题. 二.GPS模块简介 Air530 模块是一款高性能.高集成度的多模卫星定位导航 ...

  8. STM32驱动4寸ST7796S LCD-TFT屏

    STM32驱动4寸ST7796S LCD-TFT屏 简介 屏幕与STM32F103RCT6开发板接线 屏幕原理图 STM32驱动程序 屏幕显示效果 简介 屏幕驱动芯片ST7796S最大支持320*48 ...

  9. 第1讲、Cadence Allergo绘制小马哥DragonFly四轴飞行器PCB四层板教程简介

    初学者在学习单片机的时候大多都没有很明确的学习目的,所以往往学了很多课程之后,还是不能独立开发一个比较简单的项目,甚至不能完成一个简单项目的单独软件或者硬件部分的开发.这是因为大多数人是被动的.没有目 ...

  10. 2020年TI杯大学生电子设计大赛 无线运动传感器节点 备赛、参赛实录(历时一个月)

    转载请标明转载自:https://blog.csdn.net/weixin_44578655/article/details/109020022 9.5 清单已经出了一段时间了.买的少部分元器件也到了 ...

最新文章

  1. 错误:Error #2032解决方案
  2. K - FatMouse and Cheese
  3. WIN5语音ic注意事项
  4. 基于Python的应用程序的虚拟环境
  5. 数据管理的3种方法,看完后感叹:数字化转型、数据中台真不难
  6. 还争什么流量场景,罗振宇已经用时间挣钱了!
  7. 转载Docker in production: An history of failure
  8. 216.组合总和III
  9. 浅谈Linux操作系统基础知识
  10. docker 删除镜像
  11. 沙雕动画资源素材大全/小白零基础快速入门沙雕动画/三天快速上手开始制作沙雕动画/
  12. mysql 复制表结构或创建新表
  13. 名帖90 蔡襄 楷书《临锺繇帖卷》
  14. 分享137个ASP源码,总有一款适合您
  15. **Python 复数计算会丢失虚部的问题**ComplexWarning: Casting complex values to real discards the imaginary part
  16. chrome添加右键菜单收藏CSDN文章到我的博客
  17. Charles4.6.3解决乱码问题
  18. 2019年丰巢科技Java面试题
  19. unimrcp 实现阿里云的plugin
  20. As4741G安装WindowsXP后的驱动安装方法

热门文章

  1. 计算机术语宏是什么意思,宏(计算机术语)
  2. 关于印发国家测绘地理信息局2013年立法工作计划的通知
  3. ADB 环境变量配置教学
  4. 左程云基础班——排序算法
  5. SSM项目实战:学生学籍管理系统
  6. python下载包图网图片_Python爬虫 包图网case
  7. C语言 三角函数 时钟周期,三角函数的周期公式
  8. Linux搭建局域网邮箱服务器,菜鸟搭建开源的局域网邮件服务器-windows linux均适用...
  9. 找不到该项目(无法删除文件)
  10. distpicker插件使用自定义数据