本设计的硬件构成:
STM32F103C8T6单片机最小系统板,MAX30102血氧传感器、OLED12864显示屏模块、按键、蜂鸣器、蓝牙模块构成;
功能介绍:
1、采用MAX30102血氧检测模块(可同步检测心率)。,OLED显示屏显示当前的血氧饱和度、心率频率,以及显示当前的检测状态。
2、当检测到血氧饱和度低于设定值时,蜂鸣器发出报警。
3、当检测到心率频率高于设定值时,蜂鸣器发出报警。
4、按键可以调整血氧饱和度、心率的报警值。按键1:设定键;按键2:加一键;按键3:减一键。
5、可以通过蓝牙模块连接APP,手机实时显示血氧饱和度和心率,并可调整报警值;当血氧饱和度或心率超过报警值时,对应的数据会变为红色,以示血氧或心率异常。
主要物料清单及型号:
显示屏:OLED12864;
单片机:STM32F103C8T6;
血氧传感器:MAX30102;
部分程序源码:
/**
* @brief The application entry point.
*
* @retval None
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t un_min, un_max, un_prev_data;
int i;
int32_t n_brightness;
float f_temp;
// u8 temp_num=0;
u8 temp[6];
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM4_Init();
uart_init(9600); //初始化串口
TIM3_Init(500-1,7200-1); //定时器3初始化,定时器时钟为72M,分频系数为7200-1,
KEY_Init();
delay_init();
max30102_init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
LCD_Refresh();
delay_ms(500);
beep_on;
delay_ms(500);
beep_off;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
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(MAX30102_INT==1); //wait until the interrupt pin asserts
max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
aun_red_buffer[i] = (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2]; // Combine values to get the actual number
aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5]; // Combine values to get the actual number
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
}
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);
LCD_Refresh();
key=0;
while (1)
{
KEY_Handle(key);
key=0;
APP_Command_Handle();
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++)
{
if(set!=0||(revFlag!=0))
break;
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++)
{
if(set!=0||(revFlag!=0))
break;
un_prev_data=aun_red_buffer[i-1];
while(MAX30102_INT==1);
max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
aun_red_buffer[i] = (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2]; // Combine values to get the actual number
aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5]; // Combine values to get the actual number
if(aun_red_buffer[i]>un_prev_data)
{
f_temp=aun_red_buffer[i]-un_prev_data;
f_temp/=(un_max-un_min);
f_temp*=MAX_BRIGHTNESS;
n_brightness-=(int)f_temp;
if(n_brightness<0)
n_brightness=0;
}
else
{
f_temp=un_prev_data-aun_red_buffer[i];
f_temp/=(un_max-un_min);
f_temp*=MAX_BRIGHTNESS;
n_brightness+=(int)f_temp;
if(n_brightness>MAX_BRIGHTNESS)
n_brightness=MAX_BRIGHTNESS;
}
dis_hr = n_heart_rate;
dis_spo2 = n_sp02;
}
if(t_5ms>=20)
{
APP_Update();
if(set==0)
LCD_Refresh();
t_5ms=0;
}
if(set==0)
{
if(((dis_hr>heart_alarm)&&(dis_hr<=200)) )
{
alarm_type=2;
alarm_time++;
if(alarm_time>=2)
{
if(alarm_state==0)
alarm_state=1;
}
}
else if(((n_sp02 < spo2_alarm)&&(n_sp02>=80)))
{
alarm_type=1;
alarm_time++;
if(alarm_time>=2)
{
if(alarm_state==0)
alarm_state=1;
}
}
else
{
alarm_type=0;
alarm_state=0;
alarm_time=0;
}
if(alarm_state>0)
{
alarm_state++;
if(alarm_state%2==0 && alarm_en==1)
beep_on;
else
beep_off;
}
else
beep_off;
}
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);
if(n_heart_rate<0)
n_heart_rate=0;
else if(n_sp02<0)
n_sp02=0;
}
/* USER CODE END 3 */
}