欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
STM32F103單片機使用MAX30102測量心率血氧源程序
[打印本頁]
作者:
嗡嗡嗡頂頂頂
時間:
2024-4-28 10:15
標題:
STM32F103單片機使用MAX30102測量心率血氧源程序
單片機源程序如下:
#include "stm32f10x.h" // Device header
#include "software_IIC.h"
#include "MAX30102.h"
#include "MAX30102_algorithm.h"
#include "OLED.h"
#include "Key.h"
#include "Delay.h"
#define MAX_BRIGHTNESS 255
uint16_t fifo_red;
uint16_t fifo_ir;
void MAX30102_Init(void)
{
IIC_GPIO_Init(); //先初始化底層的I2C
/*MAX30102寄存器初始化,需要對照MAX30102手冊的寄存器描述配置,此處僅配置了部分重要的寄存器*/
IIC_WriteReg(MAX30102_ADDRESS,REG_MODE_CONFIG, 0x40); //將RESET位設置為1,所有配置、閾值和數據寄存器通過上電復位復位復位到其上電狀態。
IIC_WriteReg(MAX30102_ADDRESS,REG_INTR_ENABLE_1, 0x00); //不使用中斷
IIC_WriteReg(MAX30102_ADDRESS,REG_INTR_ENABLE_2, 0x00);
IIC_WriteReg(MAX30102_ADDRESS,REG_FIFO_WR_PTR,0x00); //FIFO寫入指針為0
IIC_WriteReg(MAX30102_ADDRESS,REG_OVF_COUNTER,0x00); //溢出數據計數器為0
IIC_WriteReg(MAX30102_ADDRESS,REG_FIFO_RD_PTR,0x00); //FIFO讀取指針為0
IIC_WriteReg(MAX30102_ADDRESS,REG_FIFO_CONFIG,0x0f); //0x0f設置平均取樣為4,當FIFO完全充滿數據時,FIFO地址滾動到零并且FIFO繼續填充新數據。
IIC_WriteReg(MAX30102_ADDRESS,REG_MODE_CONFIG,0x03); //SpO2模式
IIC_WriteReg(MAX30102_ADDRESS,REG_SPO2_CONFIG,0x27); //0x45ADC量程為8192,采樣率為100/s,LED占空比118us,對應采樣精度16bit
IIC_WriteReg(MAX30102_ADDRESS,REG_LED1_PA,0x20);
IIC_WriteReg(MAX30102_ADDRESS,REG_LED2_PA,0x20);
IIC_WriteReg(MAX30102_ADDRESS,REG_PILOT_PA,0x7F);
}
void MAX30102_IIC_ReadReg(uint8_t slave_ID,uint8_t RegAddress) //讀取6個字節
{
fifo_red=0;
fifo_ir=0;
uint16_t Data1,Data2,Data3,Data4,Data5,Data6;
IIC_Start(); //I2C起始
IIC_SendByte(slave_ID); //發送從機地址,讀寫位為0,表示即將寫入
IIC_ReceiveAck(); //接收應答
IIC_SendByte(RegAddress); //發送寄存器地址
IIC_ReceiveAck(); //接收應答
IIC_Start(); //I2C重復起始
IIC_SendByte(slave_ID | 0x01); //發送從機地址,讀寫位為1,表示即將讀取
IIC_ReceiveAck(); //接收應答
Data1 = IIC_ReceiveByte(); //接收指定寄存器的數據
IIC_SendAck(0); //發送應答,給從機非應答,終止從機的數據輸出
Data2 = IIC_ReceiveByte();
IIC_SendAck(0);
Data3 = IIC_ReceiveByte();
IIC_SendAck(0);
Data4 = IIC_ReceiveByte(); //接收指定寄存器的數據
IIC_SendAck(0); //發送應答,給從機非應答,終止從機的數據輸出
Data5 = IIC_ReceiveByte();
IIC_SendAck(0);
Data6 = IIC_ReceiveByte();
IIC_SendAck(1);
IIC_Stop();
//I2C終止
Data1 <<= 14;
fifo_red+=Data1;
Data2 <<= 6;
fifo_red+=Data2;
Data3 >>= 2;
fifo_red+=Data3;
Data4 <<= 14;
fifo_ir+=Data4;
Data5 <<= 6;
fifo_ir+=Data5;
Data6 >>= 2;
fifo_ir+=Data6;
if(fifo_ir<=10000)
{
fifo_ir=0;
}
if(fifo_red<=10000)
{
fifo_red=0;
}
}
int8_t menu_Back_event(void)//菜單返回
{
return Key_Back_Get();; //返回鍵接到PA2;
}
void SPO2_function(void)
{
OLED_Clear();
OLED_ShowChinese(46,0,"血");
OLED_ShowChinese(62,0,"氧");
OLED_ShowChinese(78,0,"檢");
OLED_ShowChinese(94,0,"測");
MAX30102_Init(); //初始化MAX30102
OLED_ShowImage(0,0,22,8,qipaoup); //顯示左上方固定的石頭塊
OLED_ShowImage(0,56,22,8,qipaodown); //顯示左下方固定的石頭塊
OLED_Update();
uint8_t j=128; //定義魚的起始X坐標
uint8_t ave_Count = 1; //為了獲取10個最終得到的血氧值,設置計數器,(可以更改,值越大測量時間越長,獲取數據越多)
uint16_t cal_ave[10]; //定義長度為10的數組存儲10個檢測數據
uint16_t ave_Sum = 0; //存儲10個數據的和
uint8_t cal_Sum_lock = 0; //總和計算器鎖
while(1)
{
/*-------------------------移動氣泡的程序邏輯------------------------------*/
uint8_t i;
for(i = 0;i <= 16;i++)
{
OLED_ClearArea(0,8,22,48);
OLED_ShowImage(1,49-i,7,7,qipao);
OLED_ShowImage(1,33-i,7,7,qipao);
if(i<17)
{
OLED_ShowImage(1,17-i,7,7,qipao);
OLED_ShowImage(0,0,22,8,qipaoup);
}
OLED_ShowImage(13,56-i,7,7,qipao);
OLED_ShowImage(13,40-i,7,7,qipao);
OLED_ShowImage(13,24-i,7,7,qipao);
/*-------------------------移動魚的程序邏輯------------------------------*/
if(j<=0)
{
j = 128;
OLED_ClearArea(22,49,106,15); //清除小魚游過后的全屏尾跡
}
OLED_ShowImage(j,49,15,15,Fish);
OLED_ClearArea(j+15,49,106,15); //解除注釋可以實時清除小魚尾跡
OLED_ShowImage(0,56,22,8,qipaodown); //刷新左下角石頭塊,讓小魚從石頭快后邊游過,注釋后會從石頭塊前方游過
j--;
Delay_ms(5); //控制動畫移動速度
OLED_Update();
}
if(ave_Count<=10)
{
blood_Loop();
if(SPO2dataResult != 0)
{
OLED_ClearArea(22,16,106,32);
OLED_ShowChinese(54,17,"檢");
OLED_ShowChinese(70,17,"測");
OLED_ShowChinese(86,17,"中");
cal_ave[ave_Count-1] = SPO2dataResult;
ave_Count++;
}else{
OLED_ClearArea(22,16,106,32);
OLED_ShowChinese(54,16,"請");
OLED_ShowChinese(70,16,"正");
OLED_ShowChinese(86,16,"確");
OLED_ShowChinese(54,32,"佩");
OLED_ShowChinese(70,32,"戴");
OLED_ShowChar(90,32,'!',OLED_8X16);
}
}else
{
ave_Count = 11; //得到10個數據后將計數器值固定到11防止溢出
uint8_t i;
uint16_t min;
for(i = 0;i<9;i++) //取出最小值
{
if(i == 0){min = cal_ave[0];} //
if(cal_ave[i+1]<min)
{
min = cal_ave[i+1];
}
}
if(cal_Sum_lock == 0)
{
for(i = 0;i<10;i++)
{
ave_Sum += cal_ave[i]; //計算0個數據的和
}
cal_Sum_lock = 1; //和計算一次后打開鎖,防止多次累加
}
OLED_ClearArea(22,17,106,32);
OLED_ShowNum(49,17,(ave_Sum-min)/9 + 3,3,OLED_15X24); //顯示最終結果
OLED_ShowChar(96,17,0x3A,OLED_15X24);
}
if(menu_Back_event()) //檢測按鍵按下
{
break;
}
}
}
void Heart_function(void)
{
OLED_Clear();
OLED_ShowChinese(32,0,"心");
OLED_ShowChinese(48,0,"率");
OLED_ShowChinese(64,0,"檢");
OLED_ShowChinese(80,0,"測");
OLED_Update();
MAX30102_Init();
uint8_t ave_Count = 1; //為了獲取10個最終得到的心率,設置計數器
uint16_t cal_ave[10]; //定義長度為10的數組存儲測量的10個心率數據
uint16_t ave_Sum = 0; //存儲10個數據的和
uint8_t cal_Sum_lock = 0; //總和計算器鎖
while(1)
{
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart1);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart2);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart3);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart4);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart5);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart6);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart7);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart8);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart7);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart6);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart5);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart4);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart3);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart2);
OLED_Update();
Delay_ms(10);
OLED_ClearArea(0,20,64,44);
OLED_ShowImage(0,20,54,49,Heart1);
OLED_Update();
//blood_Loop();
OLED_ClearArea(64,20,64,44);
if(ave_Count<=10)
{
blood_Loop();
if(SPO2dataResult != 0)
{
OLED_ClearArea(64,16,64,44);
OLED_ShowChinese(64,17,"測");
OLED_ShowChinese(80,17,"量");
OLED_ShowChinese(96,17,"中");
//OLED_ShowNum(64,17,HeartdataResult,3,OLED_13X24);
cal_ave[ave_Count-1] = HeartdataResult;
ave_Count++;
}
else
{
OLED_ClearArea(64,16,64,44);
OLED_ShowChinese(64,16,"請");
OLED_ShowChinese(80,16,"正");
OLED_ShowChinese(96,16,"確");
OLED_ShowChinese(64,32,"佩");
OLED_ShowChinese(80,32,"戴");
OLED_ShowChar(100,32,'!',OLED_8X16);
}
}
else
{
ave_Count = 11; //得到10個數據后將計數器固定到11防止溢出
uint8_t i;
uint16_t max;
for(i = 0;i<9;i++) //取出最大值
{
if(i == 0){max = cal_ave[0];} //
if(cal_ave[i+1]>max)
{
max = cal_ave[i+1];
}
}
if(cal_Sum_lock == 0)
{
for(i = 0;i<10;i++)
{
ave_Sum += cal_ave[i]; //計算10個數據的和
}
cal_Sum_lock = 1; //和計算一次后打開鎖,防止多次計算
}
OLED_ClearArea(22,17,106,32);
OLED_ShowNum(64,17,(ave_Sum-max)/9,3,OLED_15X24); //顯示最終結果
Delay_ms(200);
}
if(menu_Back_event()) //檢測按鍵按下
{
break;
}
}
}
復制代碼
原理圖: 無
仿真: 無
代碼:
心率血氧檢測.7z
(198.14 KB, 下載次數: 30)
2024-4-28 14:42 上傳
點擊文件名下載附件
程序源碼
下載積分: 黑幣 -5
歡迎光臨 (http://m.raoushi.com/bbs/)
Powered by Discuz! X3.1