目录
一、设计背景和意义
1.1设计背景
本课题的立意根植于一个普遍而严峻的临床现实:传统静脉输液的监护模式因其高度依赖人力,正日益成为医疗安全链条上的脆弱一环。护士需要不间断地巡查,凭借肉眼判断滴速、估算余液、感知药液温度,这种模式不仅极大地增加了医护人员的劳动负荷,更因不可避免的疲劳与疏忽,潜藏着液空回血、滴速失控、药液冷刺激等诸多风险,直接关乎患者的生命安全。尽管市场上已有高端智能输液泵产品,但其令人望而却步的成本和操作复杂性,如同一道数字鸿沟,将其牢牢禁锢于重症监护室,无法惠及普通病房与基层医疗场景。因此,本研究的核心意义在于发起一场对传统输液监护模式的普惠式革新,它不仅仅是一个技术项目,更是一次对智慧医疗"落地难"问题的务实回应。
1.2设计意义
我们致力于打造的不仅是一台冰冷的机器,更是一位不知疲倦的"智能护士"。它通过精确的自动化监护与控制,将医护人员从机械重复的劳动中解放出来,使其能更专注于更高价值的诊疗决策;它通过及时可靠的报警与远程监控功能,构筑起一道坚实的安全屏障,极大提升了患者的治疗体验与安全感。更重要的是,本设计所坚持的低成本、易用性原则,旨在打破高端医疗技术的应用壁垒,使其能够真正下沉到社区医院、乡镇卫生院乃至家庭病床,这对于促进医疗资源的公平可及、推动"全民健康"目标的实现,具有深远而积极的社会意义。
二、实物效果展示
2.1实物图片

2.2实物演示视频
【开源】基于STM32的智能点滴输液系统
三、硬件功能简介
3.1项目功能详解
- 传感器检测:M03非接触式液位检测,DS18B20检测药液温度,红外对管检测药液滴速。
- 数据显示:0.96OLED屏幕显示全部的传感器数据以及传感器的阈值等数据。
- 执行机构:通过继电器控制加热片,步进电机控制滴速。
- 连接蓝牙APP:系统通过JW01蓝牙模块连接手机蓝牙APP,实现数据上传。
- App远程监控:通过App远程监控全部传感器数据。
- 阈值数据设定:系统通过按键设定阈值。
- 自动模式:根据设定的滴速上下限、温度阈值判断。当检测到的滴速低于下限,步进电机正转加快滴速同时蜂鸣器报警提醒,当检测到滴速高于上限,步进电机反转减缓滴速同时蜂鸣器报警提醒;当检测到到温度低于设定阈值,自动打开加热片对药液进行加热同时蜂鸣器报警提醒;非接触式液位传感器检测到药液为无时,蜂鸣器报警提醒。
3.2元器件清单
- STM32F103C8T6主控
- 0.96OLED 显示屏幕
- JDY-31蓝牙模块
- M03非接触式液位传感器
- 红外对管滴速检测
- DS18B20温度检测
- 蜂鸣器声光报警
- 加热片
- 步进电机
- 按键
四、主框图与软件流程图
主框图

流程图

五、硬件PCB展示


六、软件程序设计
cpp
#include "sys.h"
#include "delay.h"
#include "gpio.h"
#include "OLED_I2C.h"
#include "ds18b20.h"
#include "timer.h"
#include "usart1.h"
#include "exti.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "adc.h"
#define STM32_RX1_BUF Usart1RecBuf
#define STM32_Rx1Counter RxCounter
#define STM32_RX1BUFF_SIZE USART1_RXBUFF_SIZE
#define Coil_8B_A {A=1;B=0;C=0;D=0;}//A相通电,其他相断电
#define Coil_8B_AB {A=1;B=1;C=0;D=0;}//AB相通电,其他相断电
#define Coil_8B_B {A=0;B=1;C=0;D=0;}//B相通电,其他相断电
#define Coil_8B_BC {A=0;B=1;C=1;D=0;}//BC相通电,其他相断电
#define Coil_8B_C {A=0;B=0;C=1;D=0;}//C相通电,其他相断电
#define Coil_8B_CD {A=0;B=0;C=1;D=1;}//CD相通电,其他相断电
#define Coil_8B_D {A=0;B=0;C=0;D=1;}//D相通电,其他相断电
#define Coil_8B_DA {A=1;B=0;C=0;D=1;}//DA相通电,其他相断电
#define Coil_OFF {A=0;B=0;C=0;D=0;}//全部断电
int flag = 0;
int PulseCount = 0; //记录脉冲
int Speed = 0; //滴速
int speed_min = 60; //滴速下限
int speed_max = 180; //滴速上限
float temperature=0.0; //温度
float set_tempval=10.0; //温度设置值
u8 shuaxin = 0; //刷新标志
u8 setFlag = 0; //设置标志
u8 NoWater = 0; //缺水标志
u8 shanshuo = 0; //shanshuo
u8 direction = 0;//方向标志
char display[16];
void Usart1RxBufClear(void) //清除串口接收缓存
{
memset(STM32_RX1_BUF, 0, STM32_RX1BUFF_SIZE);//清除缓存
STM32_Rx1Counter = 0;
}
void InitDisplay(void) //初始化显示
{
unsigned char i=0;
for(i=0;i<6;i++)OLED_ShowCN(i*16+16,0,i+8,0);//显示中文:智能点滴系统
for(i=0;i<2;i++)OLED_ShowCN(i*16,2,i+0,0);//显示中文:滴速
for(i=0;i<2;i++)OLED_ShowCN(i*16,4,i+2,0);//显示中文:温度
for(i=0;i<2;i++)OLED_ShowCN(i*16,6,i+4,0);//显示中文:药水
OLED_ShowChar(32,6,':',2,0);
}
void displaySetValue(void) //显示设置的值
{
if(setFlag == 1 || setFlag == 2)
{
sprintf(display,"%003d",(int)speed_min);
OLED_ShowStr(40, 4, (u8*)display, 2,setFlag+1-1);//显示滴速下限
sprintf(display,"%003d",(int)speed_max);
OLED_ShowStr(40, 6, (u8*)display, 2,setFlag+1-2);//显示滴速上限
}
if(setFlag == 3)
{
sprintf(display,"%4.1fC",set_tempval);
OLED_ShowStr(40, 4, (u8*)display, 2,setFlag+1-3);//显示温度
}
}
void keyscan(void) //按键扫描
{
unsigned char i=0;
if(KEY1 == 0 || strstr(STM32_RX1_BUF,"k1") != NULL) //设置键
{
delay_ms(20);
if(KEY1 == 0 || strstr(STM32_RX1_BUF,"k1") != NULL)
{
Usart1RxBufClear();
while(KEY1 == 0);
setFlag ++;
if(setFlag == 1)
{
OLED_CLS(); //清屏
for(i=0;i<4;i++)OLED_ShowCN(i*16+32,0,i+14,0);//显示中文:设置滴速
for(i=0;i<2;i++)OLED_ShowCN(i*16,4,i+22,0);//显示中文:下限
for(i=0;i<2;i++)OLED_ShowCN(i*16,6,i+24,0);//显示中文:上限
OLED_ShowChar(32,4,':',2,0);
OLED_ShowChar(32,6,':',2,0);
OLED_ShowStr(62, 4, "/min", 2,0);
OLED_ShowStr(62, 6, "/min", 2,0);
// displaySetValue();
}
if(setFlag == 3)
{
OLED_CLS(); //清屏
for(i=0;i<4;i++)OLED_ShowCN(i*16+32,0,i+18,0);//显示中文:设置温度
}
if(setFlag >= 4)
{
setFlag = 0;
OLED_CLS(); //清屏
InitDisplay();
if(NoWater==0)
OLED_ShowCN(56,6,7,1);//显示中文:无
else
OLED_ShowCN(56,6,6,1);//显示中文:有
// displaySetValue();
}
displaySetValue(); //显示没有设置值
}
}
if(KEY2 == 0 || strstr(STM32_RX1_BUF,"k2") != NULL ||get_flag ==1) //加键
{
delay_ms(100);
if(KEY2 == 0 || strstr(STM32_RX1_BUF,"k2") != NULL ||get_flag ==1)
{
get_flag = 0;
Usart1RxBufClear();
if(setFlag == 1)
{
if(speed_max-speed_min>1)speed_min++;
}
if(setFlag == 2)
{
if(speed_max<999)speed_max++;
}
if(setFlag == 3)
{
if(set_tempval<99.9)set_tempval+=0.1;
}
displaySetValue(); //显示没有设置值
}
}
if(KEY3 == 0 || strstr(STM32_RX1_BUF,"k3") != NULL) //减键
{
delay_ms(100);
if(KEY3 == 0 || strstr(STM32_RX1_BUF,"k3") != NULL)
{
Usart1RxBufClear();
if(setFlag == 1)
{
if(speed_min>0)speed_min--;
}
if(setFlag == 2)
{
if(speed_max-speed_min>1)speed_max--;
}
if(setFlag == 3)
{
if(set_tempval>0)set_tempval-=0.1;
}
displaySetValue(); //显示没有设置值
}
}
}
void Usart1SendData(void) //串口发送
{
printf("滴速:%d\r\n",Speed);
printf("液位:%d\r\n",NoWater);
printf("温度:%0.1f\r\n",temperature);
}
int main(void)
{
delay_init(); //延时函数初始化
NVIC_Configuration(); //中断优先级配置
I2C_Configuration(); //IIC初始化
delay_ms(200);
OLED_Init(); //OLED液晶初始化
OLED_CLS(); //清屏
InitDisplay();
KEY_GPIO_Init(); //按键引脚初始化
MOTOR_GPIO_Init(); //步进电机初始化
DS18B20_GPIO_Init();
EXTIX_Init();
DS18B20_Init(); //初始化显示
uart1_init(9600);
TIM3_Init(99,719); //定时器初始化
Adc_Init();
while(1)
{
keyscan(); //按键扫描
if(setFlag == 0) //不在设置状态下
{
// Get_Water_Value(&Water_Value);
if((Speed!=0)&&((Speed<speed_min)||(Speed>speed_max))&&shanshuo) //滴速不在范围,闪烁显示
{
OLED_ShowStr(32, 2,": ", 2,0); //显示空白
}
else
{
sprintf(display,": %003d/min ",(int)Speed);
OLED_ShowStr(32, 2, (u8*)display, 2,0);//显示滴速
}
if(Speed!=0)
{
if(Speed<speed_min) direction=1; //滴速过慢,电机正转,模拟放开调节阀
else if(Speed>speed_max) direction=2; //滴速过快,电机反转,模拟收紧调节阀
else direction=0; //在正常滴速范围,电机停止
}
else
{
direction=0; //停止
}
if(shuaxin == 1)
{
shuaxin = 0;
temperature=ReadTemperature(); //读取温度
if(temperature < set_tempval)relay = 1; //温度低于设置值,开启加热
else relay = 0; //温度达到设置值,关闭加热
Usart1SendData(); //数据1秒发送一次
}
if(temperature<set_tempval && shanshuo) //温度不在范围,闪烁显示
{
OLED_ShowStr(32, 4,": ", 2,0); //显示空白
}
else
{
sprintf(display,": %4.1fC",temperature);
OLED_ShowStr(32, 4, (u8*)display, 2,0);//显示温度
}
if(water == 1) //无药水
{
if(NoWater==0)
OLED_ShowCN(56,6,7,1);//显示中文:无
NoWater = 0; //缺水标志
}
else
{
if(NoWater==1)
OLED_ShowCN(56,6,6,1);//显示中文:有
NoWater = 1;
}
}
delay_ms(10);
}
}
void EXTI0_IRQHandler(void)
{
PulseCount++;
EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0线路挂起位
}
void TIM3_IRQHandler(void)//定时器3中断服务程序,用于记录时间
{
static u16 timeCount1 = 1000;
static u16 timeCount2 = 4000;
static u16 timeCount3 = 0;
static u8 index = 0;
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除中断标志位
timeCount1 ++;
timeCount2 ++;
timeCount3 ++;
if(timeCount1>=1000) //1s
{
timeCount1 = 0;
shuaxin = 1;
}
if(timeCount2 >= 1000) //1s
{
timeCount2 = 0;
Speed = PulseCount * 60; //获取计数值,转化为滴/每分钟
PulseCount = 0;
}
if(timeCount3>=300) //300ms
{
timeCount3 = 0;
shanshuo = !shanshuo;
if(!setFlag)
{
if(NoWater==0) //无药水,蜂鸣器一直报警
{
beep = 1;
LED1_ON;
LED2_ON;
}
else
{
if(((Speed!=0)&&((Speed<speed_min)||(Speed>speed_max)))||temperature<set_tempval) //滴速温度不在范围,蜂鸣器报警
{
beep = ~beep;
if(flag == 0)
{
flag = 1;
LED1_ON;
LED2_OFF;
}
else
{
LED1_OFF;
LED2_ON;
flag = 0;
}
}
else
{
beep = 0;
}
}
}
else
{
beep = 0;
}
}
if(direction == 0) //步进电机停止
{
Coil_OFF ;
}
else if(direction == 1) //步进电机正转
{
switch(index)
{
case 0:Coil_8B_A;break;
case 1:Coil_8B_AB;break;
case 2:Coil_8B_B; break;
case 3:Coil_8B_BC;break;
case 4:Coil_8B_C; break;
case 5:Coil_8B_CD;break;
case 6:Coil_8B_D; break;
case 7:Coil_8B_DA;break;
}
index ++;
if(index == 8) index = 0;
}
else if(direction == 2) //步进电机反转
{
switch(index)
{
case 0:Coil_8B_DA;break;
case 1:Coil_8B_D; break;
case 2:Coil_8B_CD; break;
case 3:Coil_8B_C; break;
case 4:Coil_8B_BC; break;
case 5:Coil_8B_B; break;
case 6:Coil_8B_AB; break;
case 7:Coil_8B_A; break;
}
index ++;
if(index == 8) index = 0;
}
}
}
七、项目资料包内容
