一、項(xiàng)目介紹
當(dāng)前文章介紹基于STM32設(shè)計(jì)的人體健康檢測(cè)儀。設(shè)備采用STM32系列MCU作為主控芯片,配備血氧濃度傳感器(使用MAX30102血氧濃度檢測(cè)傳感器)、OLED屏幕和電池供電等外設(shè)模塊。設(shè)備可以廣泛應(yīng)用于醫(yī)療、健康等領(lǐng)域。可以幫助醫(yī)生和病人更好地了解病情變化,提高治療效果和生活質(zhì)量。設(shè)備也可以用于健康管理、運(yùn)動(dòng)監(jiān)測(cè)等場(chǎng)景,幫助用戶了解自己的身體狀況,保持健康的生活方式。
在項(xiàng)目中,使用了KEIL作為開發(fā)平臺(tái)和工具,通過血氧模塊采集人體的心跳和血氧濃度參數(shù),并通過OLED屏幕顯示現(xiàn)在的心跳和血氧濃度。同時(shí),通過指標(biāo)分析,提供采集到的數(shù)據(jù)與正常指標(biāo)比對(duì),分析被檢測(cè)人員的健康狀態(tài)。采集的數(shù)據(jù)可通過藍(lán)牙或者WIFI傳遞給手機(jī)APP進(jìn)行處理,方便用戶隨時(shí)了解自己的身體狀況。
本設(shè)計(jì)采用STM32為主控芯片,搭配血氧濃度傳感器和OLED屏幕,實(shí)現(xiàn)了人體健康數(shù)據(jù)的采集和展示,并對(duì)采集到的數(shù)據(jù)進(jìn)行分析,判斷被檢測(cè)人員的健康狀態(tài)。同時(shí),設(shè)計(jì)使用藍(lán)牙或WiFi將采集到的數(shù)據(jù)傳遞給手機(jī)APP進(jìn)行處理。
二、項(xiàng)目設(shè)計(jì)思路
2.1 硬件設(shè)計(jì)
(1)主控芯片:STM32系列MCU,負(fù)責(zé)驅(qū)動(dòng)其他外設(shè)模塊;
(2)血氧濃度傳感器:使用MAX30102血氧濃度檢測(cè)傳感器,用于采集人體的心跳和血氧濃度參數(shù);
(3)OLED屏:用于顯示現(xiàn)在的心跳和血氧濃度;
2.2 軟件設(shè)計(jì)
(1) 通過血氧模塊采集人體的心跳和血氧濃度參數(shù);
(2) 通過OLED屏顯示現(xiàn)在的心跳和血氧濃度;
(3) 對(duì)采集到的數(shù)據(jù)進(jìn)行指標(biāo)分析,將采集到的數(shù)據(jù)與正常指標(biāo)比對(duì),分析被檢測(cè)人員的健康狀態(tài);
(4) 采集的數(shù)據(jù)可通過藍(lán)牙或WiFi傳遞給手機(jī)APP進(jìn)行處理。
2.3 技術(shù)實(shí)現(xiàn)
(1)設(shè)計(jì)采用AD8232心電圖(ECG)模塊和MAX30102血氧模塊采集心跳和血氧濃度參數(shù),并通過I2C接口連接主控芯片STM32。
(2)OLED屏使用I2C接口與主控芯片STM32連接。
(3)采集到的數(shù)據(jù)通過算法進(jìn)行指標(biāo)分析,將采集到的數(shù)據(jù)與正常指標(biāo)比對(duì),判斷被檢測(cè)人員的健康狀態(tài)。
(4)設(shè)備通過藍(lán)牙或WiFi將采集到的數(shù)據(jù)傳遞給手機(jī)APP進(jìn)行處理。
三、代碼設(shè)計(jì)
3.1 MAX30102血氧模塊代碼
I2C協(xié)議代碼:
#define MAX30102_I2C_ADDR 0xAE
?
void MAX30102_I2C_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
?
/* Enable GPIOB clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* Enable I2C1 and I2C2 clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 | RCC_APB1Periph_I2C2, ENABLE);
?
// Configure I2C SCL and SDA pins
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // Open-drain output
GPIO_Init(GPIOB, &GPIO_InitStructure);
?
// Configure I2C parameters
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000; // 100KHz
I2C_Init(I2C1, &I2C_InitStructure);
?
// Enable I2C
I2C_Cmd(I2C1, ENABLE);
}
?
void MAX30102_I2C_WriteReg(uint8_t reg, uint8_t value)
{
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
?
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
?
I2C_Send7bitAddress(I2C1, MAX30102_I2C_ADDR, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
?
I2C_SendData(I2C1, reg);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
?
I2C_SendData(I2C1, value);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
?
I2C_GenerateSTOP(I2C1, ENABLE);
}
?
uint8_t MAX30102_I2C_ReadReg(uint8_t reg)
{
uint8_t value;
?
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
?
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
?
I2C_Send7bitAddress(I2C1, MAX30102_I2C_ADDR, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
?
I2C_SendData(I2C1, reg);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
?
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
?
I2C_Send7bitAddress(I2C1, MAX30102_I2C_ADDR, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
?
I2C_AcknowledgeConfig(I2C1, DISABLE);
value = I2C_ReceiveData(I2C1);
?
I2C_GenerateSTOP(I2C1, ENABLE);
?
return value;
}
?
void MAX30102_I2C_ReadArray(uint8_t reg, uint8_t* data, uint8_t len)
{
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
?
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
?
I2C_Send7bitAddress(I2C1, MAX30102_I2C_ADDR, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
?
I2C_SendData(I2C1, reg);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
?
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
?
I2C_Send7bitAddress(I2C1, MAX30102_I2C_ADDR, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
?
while(len > 1)
{
I2C_AcknowledgeConfig(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
*data++ = I2C_ReceiveData(I2C1);
len--;
}
?
I2C_AcknowledgeConfig(I2C1, DISABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
*data++ = I2C_ReceiveData(I2C1);
?
I2C_GenerateSTOP(I2C1, ENABLE);
}