基于物联网技术的智慧病房管理系统
目錄
- 前言
- 一、功能設(shè)計
- 二、基本配置
- 1.選擇芯片型號
- 2.RCC配置
- 3.SYS配置
- 4.USART1 與 DMA 配置
- 5.I2C配置
- 6.TIME3配置
- 7.DMA配置
- 8.TIM2 與 PWM 配置
- 9.NVIC配置
- 10.GPIO配置
- 11.時鐘配置
- 12.引腳配置
- 三、RTOS 與模塊驅(qū)動、代碼配置
- RTOS 配置
- 四、RTOS、AHT20 與 按鈕功能實現(xiàn)
- 1.溫濕度獲取代碼設(shè)計
- 2.RTOS 進(jìn)程設(shè)計
- 3.按鈕的使用與消抖
- 五、定時開關(guān)燈與信息獲取
- 1.定時開關(guān)燈
- 六、總結(jié)
前言
設(shè)計一個基于物聯(lián)網(wǎng)技術(shù)的智慧病房管理系統(tǒng)。假設(shè)醫(yī)院住院部的一層病房(走廊兩邊病房平行分布),病房數(shù)量最多60間,每間病房3個床位,編號從1~180號。每間病房可采用的設(shè)備如下:STM32F103開發(fā)板1塊,房間溫濕度采集模塊1套(I2C接口,AHT20模塊),房間自動燈光開關(guān)控制器(以PWM方式控制,每天早上7點漸亮,晚上22點漸滅),病人脈搏&血氧檢測儀3套(UART接口輸出脈搏+血氧的數(shù)字值),床頭緊急呼叫按鍵開關(guān)3個(按下呼叫)。
每間病房的STM32F103開發(fā)板通過UART轉(zhuǎn)485接口,以mobus組網(wǎng)方式,連接到護士監(jiān)控室的PC電腦上(上位機)。PC電腦上可接收每間病房的溫濕度數(shù)據(jù)(周期為5分鐘)、床頭緊急呼叫信號、病人脈搏血氧數(shù)據(jù)(正常狀態(tài)下30分鐘一次采集;當(dāng)脈搏超過120或血氧值低于90時切換到危重狀態(tài)下,實時采集),顯示在屏幕上并且保存到MySQL數(shù)據(jù)庫里。
一、功能設(shè)計
1.使用 I2C 讀取 AHT20 模塊
2.TIM 定時器與 PWM 呼吸燈
3.按鍵信息接收與消抖
4.UART 轉(zhuǎn) 485 接口與 modbus 通信
5.MAX30102 模塊心率與血氧測量
二、基本配置
1.選擇芯片型號
2.RCC配置
3.SYS配置
4.USART1 與 DMA 配置
5.I2C配置
6.TIME3配置
7.DMA配置
8.TIM2 與 PWM 配置
9.NVIC配置
10.GPIO配置
11.時鐘配置
12.引腳配置
三、RTOS 與模塊驅(qū)動、代碼配置
RTOS 配置
選擇引入 RT-Thread 輕量便捷 :
外部按鈕配置
四、RTOS、AHT20 與 按鈕功能實現(xiàn)
1.溫濕度獲取代碼設(shè)計
首先我們需要引入溫濕度驅(qū)動頭文件:
#include "AHT20.h"然后我們需要在進(jìn)程中對溫濕度傳感器進(jìn)行初始化,這里在初始化之后,不能立即獲取溫濕度,需要等待 2 秒或以上,確保數(shù)據(jù)正確性:
MX_GPIO_Init(); MX_I2C1_Init(); MX_USART1_UART_Init(); uint32_t CT_data[2]={0,0}; // 用于獲取溫濕度數(shù)據(jù) volatile int c1,t1; rt_thread_delay(50); AHT20_Init(); rt_thread_delay(2500);然后我們需要獲取經(jīng)過 CRC 驗證的溫濕度數(shù)據(jù),這里直接調(diào)用驅(qū)動函數(shù)即可:
while(1){AHT20_Read_CTdata_crc(CT_data); //經(jīng)過CRC校驗,讀取AHT20的溫度和濕度數(shù)據(jù) 推薦每隔大于1S讀一次c1 = CT_data[0]*1000/1024/1024; //計算得到濕度值c1(放大了10倍)t1 = CT_data[1]*2000/1024/1024-500;//計算得到溫度值t1(放大了10倍)printf("正在檢測");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");printf("\r\n");printf("溫度:%d%d.%d",t1/100,(t1/10)%10,t1%10); // 這里需要對溫度進(jìn)行計算后才能得到我們需要的溫度值printf("濕度:%d%d.%d",c1/100,(c1/10)%10,c1%10); // 這里同樣需要對適度進(jìn)行計算printf("\r\n");printf("等待");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");printf("\r\n");}2.RTOS 進(jìn)程設(shè)計
首先新建 app_rt_thread.c 文件,然后引入頭文件:
#include "rtthread.h" #include "main.h" #include "i2c.h" #include "usart.h" #include "gpio.h" #include "stdio.h" #include "AHT20.h"然后我們需要設(shè)計進(jìn)程,這里主進(jìn)程先設(shè)置為串口發(fā)送,子進(jìn)程設(shè)置兩個,一個是獲取溫度參數(shù),另一個是控制 PC13 引腳上的板載 LED ,后續(xù)會根據(jù)系統(tǒng)進(jìn)程對進(jìn)行設(shè)計:
//初始化線程函數(shù) void MX_RT_Thread_Init(void) {//初始化LED1線程rt_thread_init(&led1_thread,"led1",led1_task_entry,RT_NULL,&rt_led1_thread_stack[0],sizeof(rt_led1_thread_stack),3,20);//開啟線程調(diào)度rt_thread_startup(&led1_thread);//初始化USART1線程rt_thread_init(&usart1_thread,"usart1",usart1_task_entry,RT_NULL,&rt_usart1_thread_stack[0],sizeof(rt_usart1_thread_stack),3,20);//開啟線程調(diào)度rt_thread_startup(&usart1_thread); }//主任務(wù) void MX_RT_Thread_Process(void) {printf("Hello RT_Thread!!!\r\n");rt_thread_delay(2000); }//LED1任務(wù) void led1_task_entry(void *parameter) {while(1){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13, GPIO_PIN_RESET);rt_thread_delay(500);HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13, GPIO_PIN_SET);rt_thread_delay(500);} } //讀取溫度任務(wù) void usart1_task_entry(void *parameter) {MX_GPIO_Init();MX_I2C1_Init();MX_USART1_UART_Init();uint32_t CT_data[2]={0,0}; //volatile int c1,t1;rt_thread_delay(50);AHT20_Init();rt_thread_delay(2500);while(1){AHT20_Read_CTdata_crc(CT_data); //經(jīng)過CRC校驗,讀取AHT20的溫度和濕度數(shù)據(jù) 推薦每隔大于1S讀一次c1 = CT_data[0]*1000/1024/1024; //計算得到濕度值c1(放大了10倍)t1 = CT_data[1]*2000/1024/1024-500;//計算得到溫度值t1(放大了10倍)printf("正在檢測");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");printf("\r\n");printf("溫度:%d%d.%d",t1/100,(t1/10)%10,t1%10); // 這里需要對溫度進(jìn)行計算后才能得到我們需要的溫度值printf("濕度:%d%d.%d",c1/100,(c1/10)%10,c1%10); // 這里同樣需要對適度進(jìn)行計算printf("\r\n");printf("等待");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");rt_thread_delay(100);printf(".");printf("\r\n");} }點擊查看完整 app_rt_thread.c 代碼
然后我們在主函數(shù)中引入 RT-Thread 必要的頭文件并引用函數(shù):
最后我們直接在主函數(shù)中對進(jìn)程進(jìn)行初始化,并運行即可,這里直接給出完整主函數(shù):
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_DMA_Init();MX_I2C1_Init();MX_TIM3_Init();MX_USART1_UART_Init();MX_TIM2_Init();/* USER CODE BEGIN 2 */MX_RT_Thread_Init(); // 初始化線程/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){MX_RT_Thread_Process(); // 執(zhí)行主進(jìn)程/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */ }3.按鈕的使用與消抖
首先我們設(shè)計按鈕在 PA3 引腳,然后在設(shè)置 PA4 引腳上外接一個 LED ,這里先令按鈕按下反轉(zhuǎn) PA4 引腳電平,即按下小燈泡點亮,再次按下,小燈泡熄滅,這里直接設(shè)計為一個新進(jìn)程:
struct rt_thread btnclick_thread; rt_uint8_t rt_btnclick_thread_stack[128]; void btnclick_task_entry(void *parameter);void btnclick_task_entry(void *parameter){while(1){switch(KEY_Scan(0)){ case KEY1_PRES: HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_4);break;default:break;}} }初始化線程:
//初始化線程 rt_thread_init(&btnclick_thread,"btnclick",btnclick_task_entry,RT_NULL,&rt_btnclick_thread_stack[0],sizeof(rt_btnclick_thread_stack),3,20); //開啟線程調(diào)度 rt_thread_startup(&btnclick_thread);但是我們不進(jìn)行按鍵消抖,這里按鍵非常容易誤觸,所以這里進(jìn)行按鍵消抖:
#define KEY1 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_3) //讀取按鍵1 #define KEY1_PRES 1 //KEY1按下 uint8_t KEY_Scan(uint8_t mode) {static uint8_t key_up=1;//按鍵松開標(biāo)志位if(key_up&&(KEY1==0)){HAL_Delay(10);//去抖動key_up=0;if(KEY1==0)return KEY1_PRES;}else if(KEY1==1)key_up=1;return 0;//無按鍵按下 }五、定時開關(guān)燈與信息獲取
這里我們主要實現(xiàn)能夠定時開關(guān)燈,并且能夠獲取如下信息:
病人按下緊急呼叫信號
定時獲取病人脈搏血氧數(shù)據(jù)
1.定時開關(guān)燈
這里要求我們能夠?qū)崿F(xiàn)在早上 7 點開燈,晚上 22 點滅燈,所以我們就要設(shè)計 RTC 系統(tǒng)時間與日歷讀取,確定我們當(dāng)前的時間與日期,然后判斷時間數(shù),最終通過 PWM 實現(xiàn)燈的漸亮與漸滅
這里首先我們需要配置 RTC:
這里先設(shè)置兩個變量用于獲取時間和日期:
然后我們可以通過時間進(jìn)行判斷從而實現(xiàn)開關(guān)燈的效果:
void ledauto_task_entry(void *parameter){HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);while(1){HAL_RTC_GetTime(&hrtc,&Time,RTC_FORMAT_BIN);if(Time.Hours == 7&&Time.Minutes == 0&&Time.Seconds == 0){printf("開燈!");for(uint16_t i=1;i<500;i++){htim2.Instance->CCR2 = i;rt_thread_delay(5);}}else if(Time.Hours == 22&&Time.Minutes == 0&&Time.Seconds == 0){printf("關(guān)燈!");for(uint16_t i=499;i>=1;i--){htim2.Instance->CCR2 = i;rt_thread_delay(5);}}} }前面在博客中已經(jīng)介紹了如何通過 RTC 讀取日歷和時間:
RTC時間讀取(可查看我之前博客)
這里我們只需要照做就可以,但是,由于開發(fā)板掉電,時間會重置,所以這里設(shè)計時間掉電保存,如果使用外接 RTC 并有電池,則會在掉電后繼續(xù)計時,這里我設(shè)計將代碼直接寫道 RTC 初始化的函數(shù)中即可,完整初始化代碼如下:
然后我們需要在運行時,實時獲取一次時間:
void getRealTime(void) {HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);HAL_RTC_GetDate(&hrtc, &datebuff, RTC_FORMAT_BIN);HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, (uint16_t)datebuff.Year);HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, (uint16_t)datebuff.Month);HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, (uint16_t)datebuff.Date);HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, (uint16_t)datebuff.WeekDay); }void HAL_RTCEx_RTCEventCallback(RTC_HandleTypeDef *hrtc) {if(hrtc->Instance == RTC){getRealTime(); } }六、總結(jié)
智慧病房是以院內(nèi)物聯(lián)網(wǎng)為基礎(chǔ)的輔助診療及智能護理一體化解決方案。以智能改造醫(yī)院病房,通過先進(jìn)的物聯(lián)網(wǎng)技術(shù),讓患者與醫(yī)務(wù)人員、智能醫(yī)療設(shè)備緊密聯(lián)接。
通過對臨床數(shù)據(jù)采集、篩選、整合,形成醫(yī)療大數(shù)據(jù),為臨床診療、護理提供智能輔助決策。
提高醫(yī)療資源的利用率,更好地保障醫(yī)療安全,更好地以患者為中心,提供有品質(zhì)的醫(yī)療服務(wù)。
總結(jié)
以上是生活随笔為你收集整理的基于物联网技术的智慧病房管理系统的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 幼儿园宝宝培训计划
- 下一篇: 基于物联网技术的智慧病房管理系统(三)—