一、項(xiàng)目功能要求
設(shè)計(jì)并制作一個生理監(jiān)測裝置,能夠?qū)崟r監(jiān)測人體的心電圖、呼吸和溫度,并在LCD液晶顯示屏上顯示相關(guān)數(shù)據(jù)。
隨著現(xiàn)代生活節(jié)奏的加快和環(huán)境的變化,人們對身體健康的關(guān)注程度越來越高。為了及時掌握自身的生理狀況,進(jìn)行健康管理和疾病預(yù)防,監(jiān)測身體的生理參數(shù)成為一種重要的需求。因此,設(shè)計(jì)一個能夠?qū)崟r監(jiān)測人體的心電圖、呼吸和溫度的生理監(jiān)測裝置具有重要的意義。
該生理監(jiān)測裝置主要用于個人健康管理和遠(yuǎn)程監(jiān)護(hù)等應(yīng)用場景。個人健康管理方面,用戶可以通過這個裝置了解自己的心電圖、呼吸和體溫等生理參數(shù),及時發(fā)現(xiàn)異常情況并采取相應(yīng)的措施,如調(diào)整生活習(xí)慣、咨詢醫(yī)生等。遠(yuǎn)程監(jiān)護(hù)方面,裝置可以將實(shí)時的生理參數(shù)數(shù)據(jù)傳輸到云端或其他設(shè)備,供醫(yī)生或家屬遠(yuǎn)程查看,以便及時干預(yù)和診斷。
與傳統(tǒng)的生理監(jiān)測設(shè)備相比,該裝置具有以下優(yōu)勢:
- 實(shí)時性:裝置能夠?qū)崟r監(jiān)測和顯示心電圖、呼吸和溫度等生理參數(shù),用戶可以隨時了解自己的身體狀況。
- 簡便性:裝置采用便攜式設(shè)計(jì),用戶可以隨身攜帶,方便隨時監(jiān)測。
- 實(shí)用功能:通過對采集到的數(shù)據(jù)進(jìn)行分析和判斷,裝置可以提供簡單的健康狀況提示,幫助用戶及時發(fā)現(xiàn)問題并采取措施。
- 擴(kuò)展性:裝置可以添加報(bào)警功能、存儲功能和無線通信功能等增強(qiáng)功能,滿足不同用戶的需求。
這個生理監(jiān)測裝置的設(shè)計(jì)和制作有助于提高個人健康管理的水平,為用戶提供及時、準(zhǔn)確的生理參數(shù)信息,以便更好地保護(hù)身體健康。同時,它也可以為醫(yī)生和家屬提供遠(yuǎn)程監(jiān)護(hù)的手段,幫助他們隨時了解病人的生理狀況。該裝置在現(xiàn)代健康管理和醫(yī)療保健領(lǐng)域具有廣闊的應(yīng)用前景和市場潛力。
二、基本要求
【1】心電信號監(jiān)測:
- 采用PulseSensor傳感器獲取心電信號。
- 進(jìn)行AD轉(zhuǎn)換,將模擬信號轉(zhuǎn)換為數(shù)字信號。
- 使用STM32F103C8T6單片機(jī)進(jìn)行數(shù)據(jù)處理。
- 在LCD顯示屏上顯示心電圖。
【2】呼吸信號監(jiān)測:
- 采用PulseSensor傳感器獲取呼吸信號。
- 進(jìn)行AD轉(zhuǎn)換,將模擬信號轉(zhuǎn)換為數(shù)字信號。
- 使用STM32F103C8T6單片機(jī)進(jìn)行數(shù)據(jù)處理。
- 在LCD顯示屏上顯示呼吸數(shù)據(jù)。
【3】溫度監(jiān)測:
- 采用MT70傳感器測量人體溫度。
- 進(jìn)行AD轉(zhuǎn)換,將模擬信號轉(zhuǎn)換為數(shù)字信號。
- 使用STM32F103C8T6單片機(jī)進(jìn)行數(shù)據(jù)處理。
- 在LCD顯示屏上顯示溫度數(shù)據(jù),測量精度不大于0.10℃。
【4】人體健康狀況判斷:
- 根據(jù)測量到的生理參數(shù)數(shù)據(jù),進(jìn)行簡單的健康狀況判斷。
- 使用STM32F103C8T6單片機(jī)進(jìn)行數(shù)據(jù)分析與判斷。
二、發(fā)揮部分
- 健康狀況判斷:
- 分析心電圖、呼吸和溫度等數(shù)據(jù),根據(jù)預(yù)設(shè)的閾值判斷是否存在異常情況。
- 在LCD顯示屏上顯示人體健康狀況的簡單提示信息。
- 其他增強(qiáng)功能:
- 可以添加報(bào)警功能,當(dāng)監(jiān)測到異常情況時,通過聲音或震動提醒用戶。
- 可以存儲和記錄歷史數(shù)據(jù),以便后續(xù)分析和參考。
- 可以添加無線通信模塊,將實(shí)時數(shù)據(jù)傳輸?shù)狡渌O(shè)備或云端進(jìn)行遠(yuǎn)程監(jiān)測。
三、設(shè)計(jì)方案
【1】主控芯片:
【2】顯示屏:
【3】傳感器:
- 心電信號采集使用PulseSensor傳感器輸出。
- 呼吸信號采集使用PulseSensor傳感器輸出。
- 溫度測量使用MT70傳感器。
【4】AD轉(zhuǎn)換:
【5】數(shù)據(jù)處理與顯示:
- 使用STM32F103C8T6單片機(jī)進(jìn)行數(shù)據(jù)處理和健康狀況判斷。
- 通過IIC接口將數(shù)據(jù)發(fā)送給OLED顯示屏進(jìn)行實(shí)時顯示。
【6】健康狀況判斷算法:
- 根據(jù)心電圖、呼吸和溫度數(shù)據(jù)的變化趨勢和預(yù)設(shè)的閾值進(jìn)行簡單的健康狀況判斷。
四、代碼實(shí)現(xiàn)
4.1 采集代碼
ADS1292模塊,進(jìn)行3路模擬信號采集轉(zhuǎn)換實(shí)現(xiàn)代碼。
#include "stm32f10x.h"
// 定義SPI接口引腳
#define ADS1292_SPI SPI1
#define ADS1292_CS_PIN GPIO_Pin_4
#define ADS1292_CS_PORT GPIOA
// 定義命令字節(jié)
#define ADS1292_CMD_SDATAC 0x11 // 停止連續(xù)數(shù)據(jù)傳輸命令
#define ADS1292_CMD_RREG 0x20 // 讀寄存器命令
#define ADS1292_CMD_WREG 0x40 // 寫寄存器命令
#define ADS1292_CMD_START 0x08 // 啟動數(shù)據(jù)轉(zhuǎn)換命令
// 函數(shù)聲明
void ADS1292_SPI_Config(void);
void ADS1292_Start_Conversion(void);
int main(void)
{
// 初始化系統(tǒng)時鐘、GPIO等
// ...
// 配置ADS1292的SPI接口
ADS1292_SPI_Config();
// 啟動ADS1292的數(shù)據(jù)轉(zhuǎn)換
ADS1292_Start_Conversion();
// 定義讀取數(shù)據(jù)的命令字節(jié)
#define ADS1292_CMD_RDATAC 0x10
// 定義數(shù)據(jù)緩沖區(qū)大小
#define BUFFER_SIZE 100
// 數(shù)據(jù)緩沖區(qū)
uint8_t dataBuffer[BUFFER_SIZE];
while (1)
{
// 啟動數(shù)據(jù)轉(zhuǎn)換
ADS1292_Start_Conversion();
// 等待一段時間,確保數(shù)據(jù)轉(zhuǎn)換完成
// 這里可以根據(jù)具體情況調(diào)整延時時間
Delay(100); // 假設(shè)延時100毫秒
// 讀取采集到的數(shù)據(jù)
GPIO_ResetBits(ADS1292_CS_PORT, ADS1292_CS_PIN);
SPI_SendData(ADS1292_SPI, ADS1292_CMD_RDATAC);
while (SPI_I2S_GetFlagStatus(ADS1292_SPI, SPI_I2S_FLAG_BSY) == SET);
for (int i = 0; i < BUFFER_SIZE; i++)
{
SPI_SendData(ADS1292_SPI, 0xFF); // 發(fā)送一個無關(guān)的字節(jié)以觸發(fā)數(shù)據(jù)傳輸
while (SPI_I2S_GetFlagStatus(ADS1292_SPI, SPI_I2S_FLAG_RXNE) == RESET);
dataBuffer[i] = SPI_ReceiveData(ADS1292_SPI); // 讀取接收到的數(shù)據(jù)
}
GPIO_SetBits(ADS1292_CS_PORT, ADS1292_CS_PIN);
// 處理采集到的數(shù)據(jù)
// ...
// 循環(huán)進(jìn)行其他操作
// ...
}
}
// 配置ADS1292的SPI接口
void ADS1292_SPI_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
// 使能SPI時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);
// 配置CS引腳為推挽輸出
GPIO_InitStructure.GPIO_Pin = ADS1292_CS_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADS1292_CS_PORT, &GPIO_InitStructure);
// 配置SPI引腳
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置SPI參數(shù)
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(ADS1292_SPI, &SPI_InitStructure);
// 使能SPI
SPI_Cmd(ADS1292_SPI, ENABLE);
}
// 啟動ADS1292的數(shù)據(jù)轉(zhuǎn)換
void ADS1292_Start_Conversion(void)
{
// 禁用ADS1292的連續(xù)數(shù)據(jù)傳輸模式
GPIO_ResetBits(ADS1292_CS_PORT, ADS1292_CS_PIN);
SPI_SendData(ADS1292_SPI, ADS1292_CMD_SDATAC);
while (SPI_I2S_GetFlagStatus(ADS1292_SPI, SPI_I2S_FLAG_BSY) == SET);
GPIO_SetBits(ADS1292_CS_PORT, ADS1292_CS_PIN);
// 發(fā)送啟動轉(zhuǎn)換命令
GPIO_ResetBits(ADS1292_CS_PORT, ADS1292_CS_PIN);
SPI_SendData(ADS1292_SPI, ADS1292_CMD_START);
while (SPI_I2S_GetFlagStatus(ADS1292_SPI, SPI_I2S_FLAG_BSY) == SET);
GPIO_SetBits(ADS1292_CS_PORT, ADS1292_CS_PIN);
}
代碼里調(diào)用ADS1292_Start_Conversion()
函數(shù)啟動數(shù)據(jù)轉(zhuǎn)換,等待一段時間確保數(shù)據(jù)轉(zhuǎn)換完成。通過發(fā)送ADS1292_CMD_RDATAC
命令并讀取數(shù)據(jù)緩沖區(qū),從ADS1292模塊中讀取采集到的數(shù)據(jù)。
4.2 OLED顯示屏驅(qū)動代碼
包含了基本的初始化、清屏、設(shè)置位置、顯示字符串、顯示數(shù)字和顯示浮點(diǎn)數(shù)等功能。
#include "stm32f10x.h"
#include "delay.h"
#include "i2c.h"
#define OLED_ADDRESS 0x78 // OLED顯示屏的I2C地址
// OLED緩存數(shù)組(128x64像素,每個字節(jié)代表8個像素)
unsigned char OLED_Buffer[128 * 8];
// 向OLED顯示屏發(fā)送命令
void OLED_WriteCmd(unsigned char cmd) {
I2C_Start();
I2C_SendByte(OLED_ADDRESS);
I2C_SendByte(0x00); // 發(fā)送命令標(biāo)志位
I2C_SendByte(cmd);
I2C_Stop();
}
// 向OLED顯示屏發(fā)送數(shù)據(jù)
void OLED_WriteData(unsigned char data) {
I2C_Start();
I2C_SendByte(OLED_ADDRESS);
I2C_SendByte(0x40); // 發(fā)送數(shù)據(jù)標(biāo)志位
I2C_SendByte(data);
I2C_Stop();
}
// 初始化OLED顯示屏
void OLED_Init() {
// 初始化I2C總線
I2C_Init();
// 初始化OLED顯示屏
OLED_WriteCmd(0xAE); // 關(guān)閉顯示
OLED_WriteCmd(0xD5); // 設(shè)置時鐘分頻因子
OLED_WriteCmd(0x80); // 默認(rèn)值
OLED_WriteCmd(0xA8); // 設(shè)置驅(qū)動路數(shù)
OLED_WriteCmd(0x3F); // 1/64 驅(qū)動
OLED_WriteCmd(0xD3); // 設(shè)置顯示偏移
OLED_WriteCmd(0x00); // 默認(rèn)值
OLED_WriteCmd(0x40); // 設(shè)置顯示開始行
OLED_WriteCmd(0x8D); // 設(shè)置電荷泵
OLED_WriteCmd(0x14); // 使能電荷泵
OLED_WriteCmd(0x20); // 設(shè)置內(nèi)存地址模式
OLED_WriteCmd(0x00); // 水平尋址模式
OLED_WriteCmd(0xA1); // 設(shè)置段重定義
OLED_WriteCmd(0xC8); // 設(shè)置COM掃描方向
OLED_WriteCmd(0xDA); // 設(shè)置COM硬件引腳配置
OLED_WriteCmd(0x12); // 默認(rèn)值
OLED_WriteCmd(0x81); // 設(shè)置對比度控制
OLED_WriteCmd(0xCF); // 默認(rèn)值
OLED_WriteCmd(0xD9); // 設(shè)置預(yù)充電周期
OLED_WriteCmd(0xF1); // 默認(rèn)值
OLED_WriteCmd(0xDB); // 設(shè)置VCOMH Deselect Level
OLED_WriteCmd(0x40); // 默認(rèn)值
OLED_WriteCmd(0xA4); // 設(shè)置全局顯示
OLED_WriteCmd(0xA6); // 設(shè)置顯示方式,默認(rèn)正常顯示
OLED_Clear(); // 清屏
OLED_WriteCmd(0xAF); // 打開顯示
}
// 清屏
void OLED_Clear() {
for (int i = 0; i < 8; i++) {
OLED_WriteCmd(0xB0 + i); // 設(shè)置頁地址
for (int j = 0; j < 128; j++) {
OLED_WriteCmd(0x00); // 清空數(shù)據(jù)
OLED_Buffer[j + i * 128] = 0x00;
}
}
}
// 設(shè)置顯示位置
void OLED_SetPos(unsigned char row, unsigned char column) {
OLED_WriteCmd(0xB0 + row); // 設(shè)置頁地址
OLED_WriteCmd(0x00 + (8 * column & 0x0F)); // 設(shè)置列低地址
OLED_WriteCmd(0x10 + ((8 * column >> 4) & 0x0F)); // 設(shè)置列高地址
}
// 顯示字符串
void OLED_ShowString(const char* str) {
while (*str) {
for (int i = 0; i < 8; i++) {
OLED_WriteData(font8x16[(*str - ' ')*16 + i]); // 顯示字體數(shù)據(jù)
OLED_Buffer[column + row * 128] = font8x16[(*str - ' ')*16 + i]; // 更新緩存
column++;
}
str++;
}
}
// 顯示數(shù)字
void OLED_ShowNum(int num, unsigned char digit) {
char str[10];
sprintf(str, "%d", num);
OLED_ShowString(str);
}
// 顯示浮點(diǎn)數(shù)
void OLED_ShowFloat(float num, unsigned char decimal) {
char str[10];
sprintf(str, "%.*f", decimal, num);
OLED_ShowString(str);
}
4.3 OLED顯示體溫、心率
#include "stm32f10x.h"
#include "delay.h"
#include "oled.h"
// 定義體溫值和心率值
float temperature = 37.6;
int heartRate = 90;
int main(void) {
// 初始化OLED顯示屏
OLED_Init();
// 清屏
OLED_Clear();
// 設(shè)置字體大小
OLED_SetFontSize(16);
// 設(shè)置顯示位置
OLED_SetPos(0, 0);
// 顯示體溫值
OLED_ShowString("Temperature: ");
OLED_ShowFloat(temperature, 1);
// 設(shè)置顯示位置
OLED_SetPos(2, 0);
// 顯示心率值
OLED_ShowString("Heart Rate: ");
OLED_ShowNum(heartRate, 0);
while (1) {
// 主循環(huán)
}
}
五、總結(jié)
本文章描述了生理監(jiān)測裝置整個項(xiàng)目的設(shè)計(jì)方案,設(shè)計(jì)過程;通過采集心電圖、呼吸和溫度數(shù)據(jù),并使用STM32F103C8T6單片機(jī)進(jìn)行數(shù)據(jù)處理和顯示,實(shí)現(xiàn)了實(shí)時監(jiān)測和顯示生理參數(shù)的功能。提出了健康狀況判斷和其他增強(qiáng)功能的設(shè)計(jì)思路。該裝置可以用于個人的健康監(jiān)測和遠(yuǎn)程監(jiān)護(hù)等場景,具有一定的實(shí)用性和擴(kuò)展性。