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>© 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