【STM32项目开源】STM32单片机医疗点滴控制系统

目录

一、设计背景和意义

1.1设计背景:

1.2设计意义:

二、实物展示

三、硬件功能介绍

[2.1 硬件清单:](#2.1 硬件清单:)

[2.2 功能介绍:](#2.2 功能介绍:)

四、软件设计流程图

五、硬件PCB展示

六、软件主函序展示

七、单片机实物资料

[资料获取 查看主页介绍:兆龙电子单片机设计](#资料获取 查看主页介绍:兆龙电子单片机设计)


一、设计背景和意义

1.1设计背景:

在医院病房、社区诊所及家庭护理的静脉输液场景中,点滴的精准控制、安全预警与便捷管理是核心需求。传统点滴系统存在明显局限:一方面,高端智能输液设备(如医用全自动输液泵、品牌定制化输液管理系统)功能虽全但成本高昂,安装调试复杂,依赖专业医护人员操作与特定品牌售后支持,难以普及到基层诊所、家庭护理等场景,且设备兼容性差,更换或升级成本高,无法灵活满足不同患者(如儿童、老人、重症患者)的输液速度需求;另一方面,普通简易点滴装置(如重力式输液器、手动调节滚轮型)虽操作简单,但功能单一,仅能通过人工观察滴速并手动调节,缺乏滴速精准控制、药液余量监测、气泡检测及异常报警等功能,无法满足现代化医疗场景下对输液安全、精准管理的需求。

现有点滴控制方案还存在功能割裂与集成度低的问题:部分高端输液设备虽具备多模式控制与安全监测功能,但依赖复杂的电路设计与专业维护,后期使用成本高,难以覆盖预算有限的基层医疗机构或家庭护理场景;而低成本点滴装置又在功能完整性与智能化上存在欠缺,无法实现输液数据与医护终端、移动端 APP 的联动,导致滴速偏差大、药液耗尽未及时处理、气泡进入血管等安全风险,无法为患者输液记录追溯及医护人员工作效率优化提供数据支撑。基于此,本设计以 STM32 单片机为核心,融合高精度参数采集模块(如红外滴速传感器、超声波液位传感器、气泡检测传感器、压力传感器)、LCD 显示模块、数据存储模块及电机控制与报警模块,构建低成本、高集成度的 STM32 单片机医疗点滴控制系统,以解决传统点滴设备功能单一、智能化程度低、安全风险高及管理效率低的问题。

1.2设计意义:

本设计通过整合 STM32 单片机的高效数据处理能力与多模块协同工作机制,在医疗输液管理领域具有多重实用价值,具体体现在以下三方面:

从使用体验与管理效率角度,该系统突破了传统点滴设备的局限:一是实现了多参数同步监测与多功能联动(如支持滴速、药液余量、联动步进电机调速模块、药液余量预警模块),无需医护人员频繁巡查或人工调节,减少人工操作繁琐性与失误率;二是配备OLED实时显示模块,直观呈现当前滴速(单位:滴 / 分钟)、药液剩余量、输液时长及运行模式,同时支持数据自动存储(可通过蓝牙或 WiFi 传输至医护终端 / 移动端 APP),方便医护人员长期追溯患者输液记录,为患者治疗方案优化及医护工作流程管理提供完整数据支撑;三是新增异常预警与自动调控功能,当监测到某项参数超出安全范围,系统自动触发声光报警(同时向医护终端发送预警信息),并联动电机停止输液、启动气泡排除程序或关闭输液通路,无需人工干预即可及时处理异常,大幅提升了输液管理的便捷性与安全性。

从技术实践与成本控制角度,本设计以 STM32 单片机为核心,充分利用其低功耗、高性价比的优势,搭配低成本的高精度参数传感器与通用外围模块,在保证数据精度(滴速测量误差可控制在 ±1 滴 / 分钟以内,药液余量检测误差可控制在 ±5mL 以内)的前提下,有效降低了系统整体成本,相比同功能的高端智能输液设备成本降低 40%-60%,更易普及到基层诊所、社区卫生服务中心及家庭护理等场景。同时,系统支持模块化扩展(如后续可新增语音交互模块、远程输液参数设置功能),为后续功能升级预留了空间,具备良好的灵活性与可扩展性。

从应用场景与行业价值角度,该系统可广泛适配多类输液场景:在医院病房中,可作为患者输液的智能管理终端,实时调控滴速、监测安全状态,减轻医护人员巡查压力;在高校医学工程、电子信息相关专业教学中,可作为单片机与医疗设备结合的实践案例,帮助学生理解嵌入式系统在医疗场景中的应用原理;在基层诊所或家庭护理场景中,可为患者提供低成本的安全输液方案,减少输液安全事故风险与医护人员工作负担。此外,本设计探索了 STM32 单片机在低成本医疗输液设备领域的应用方案,推动传统点滴装置从 "人工观察、手动调节" 向 "多参数监测、智能控制、自动预警" 升级,为低成本智能化医疗输液设备的开发提供了可参考的集成思路,具有较好的实践应用与行业推广价值。

**二、**实物展示

下方为实物演示视频

点击下方链接跳转演示视频https://www.bilibili.com/video/BV13PaczHEFZ/?spm_id_from=333.1387.upload.video_card.click&vd_source=2a672ca4e8794dca68cbe6d047b42ca5

下方为实物展示图片

三、硬件功能介绍

2.1 硬件清单:

  • STM32F103C8T6
  • OLED液晶显示
  • 滴速传感器
  • ULN2003步进电机驱动
  • 非接触式水位传感器
  • 声光报警电路
  • WIFI模块

2.2 功能介绍:

(1)点滴流速监测:光耦测速传感器实时检测点滴流速,当流速超过上限或低于下限报警,同时步进电机调整流速
(2)数据可视化:所有监测数据不仅在OLED屏幕上显示,还能通过WIFI模块上传至手机APP,实现远程监控
(3)按键设置:按键设置液体流速上限和下
(4)报警系统:当流速超过上限或低于下限蜂鸣器报警
(5)液位传感器:采用非接触式液位传感器实时检测剩余液体量
(6)手机APP交互:流速和液体有无可实时监控,阈值可以通过手机APP设置,提供便捷的用户交互体验

四、软件设计流程图

五、硬件PCB展示

六、软件主函序展示

复制代码
#include "sys.h"
#include "delay.h"
#include "gpio.h"
#include "OLED_I2C.h"
#include "timer.h"
#include "usart1.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#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;}//全部断电
#define  SampleNum       3    //取样数量
#define  SampleTimeout   15   //取样超时时间,单位(秒)

int PulseCount = 0;     //记录脉冲
int Speed = 0;          //滴速
int speed_min = 60;      //滴速下限
int speed_max = 180;     //滴速上限


u8 setFlag = 0;  //设置标志
u8 direction = 0;//方向标志

bool SendFlag = 0;
bool shanshuo = 0; //shanshuo
bool shuaxin = 0;  //刷新标志
bool NoWater = 0;  //缺水标志
char display[16];

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,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, 3, (u8*)display, 2,setFlag+1-1);//显示滴速下限
sprintf(display,"%003d",(int)speed_max);
OLED_ShowStr(40, 5, (u8*)display, 2,setFlag+1-2);//显示滴速上限
		}

}

void keyscan(void)   //按键扫描
{
	 unsigned char i=0;

	 if(KEY1 == 0) //设置键
	 {
delay_ms(15);
		  if(KEY1 == 0)
			{
while(KEY1 == 0);
				  setFlag ++;
				  if(setFlag == 1)
					{
OLED_CLS(0);    //清屏

						  OLED_Fill_Row(0xFF,0);   //填充白色
						  OLED_Fill_Row(0xFF,1);   //填充白色
						  /* 显示直线框 */
OLED_DrawHorizLine(63,0,127);
OLED_DrawVerticaLine(0,2,8);
OLED_DrawVerticaLine(127,2,8);

						  for(i=0;i<4;i++)OLED_ShowCN(i*16+32,0,i+14,1);//显示中文:设置滴速
						  for(i=0;i<2;i++)OLED_ShowCN(i*16,3,i+22,0);//显示中文:下限
for(i=0;i<2;i++)OLED_ShowCN(i*16,5,i+24,0);//显示中文:上限
						  OLED_ShowChar(32,3,':',2,0);
						  OLED_ShowChar(32,5,':',2,0);
						  OLED_ShowStr(62, 3, "/min", 2,0);
						  OLED_ShowStr(62, 5, "/min", 2,0);
					}

if(setFlag >= 3)
					{
						  setFlag = 0;
OLED_CLS(0);    //清屏
						  InitDisplay();
						  if(NoWater==1)
OLED_ShowCN(56,6,7,1);//显示中文:无
else
OLED_ShowCN(56,6,6,1);//显示中文:有  
					}
displaySetValue();   //显示没有设置值
			}
	 }
	 if(KEY2 == 0) //加键
	 {
delay_ms(100);
		  if(KEY2 == 0)
			{
				  if(setFlag == 1)
					{
if(speed_max-speed_min>1)speed_min++;
					}
if(setFlag == 2)
					{
if(speed_max<999)speed_max++;
					}

displaySetValue();   //显示没有设置值
			}
	 }
	 if(KEY3 == 0) //减键
	 {
delay_ms(100);
		  if(KEY3 == 0)
			{
				  if(setFlag == 1)
					{
if(speed_min>0)speed_min--;
					}
if(setFlag == 2)
					{
if(speed_max-speed_min>1)speed_max--;
					}

displaySetValue();   //显示没有设置值
			}
	 }
}


int main(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;  // 将变量声明移到函数开始处

    NVIC_Configuration();	   //中断优先级配置
    delay_ms(200); 
    I2C_Configuration();     //IIC初始化
    OLED_Init();             //OLED液晶初始化
    OLED_CLS(1);              //清屏
    OLED_ShowStr(0, 2, "   loading...   ", 2,1);
    delay_ms(1000);

    // 配置PB1为上拉输入模式(替代PA1)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  // 使能GPIOB时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;              // 选择PB1引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;          // 设置为上拉输入模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      // 设置IO口速度
    GPIO_Init(GPIOB, &GPIO_InitStructure);                 // 初始化PB1


    OLED_CLS(0);  
    InitDisplay();
    KEY_GPIO_Init();        //按键引脚初始化
    MOTOR_GPIO_Init();     //步进电机初始化

	  if(water==0)NoWater=1;
	  TIM3_Init(99,719);   //定时器初始化,定时1ms
//Tout = ((arr+1)*(psc+1))/Tclk ; 
//Tclk:定时器输入频率(单位MHZ)
//Tout:定时器溢出时间(单位us)

while(1)
		{ 
			   keyscan();  //按键扫描
			   if(setFlag == 0)   //不在设置状态下
				 {
					   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;

						 }


						 if(water == 1)   //无药水
						 {
if(NoWater==0)
OLED_ShowCN(56,6,7,0);//显示中文:无
									NoWater  = 1;    //缺水标志
						 }
						 else
						 {
								 if(NoWater==1)
								 OLED_ShowCN(56,6,6,0);//显示中文:有
								 NoWater  = 0;
						 }
				 }
			   delay_ms(10);
		}
}

unsigned long times=0;        //取样时间
unsigned long total_time=0;   //取样总时间
unsigned long timeout=0;      //取样超时时间 
bool start_flag=0;            //开始计时标志

void TIM3_IRQHandler(void)//定时器3中断服务程序,用于记录时间
{ 
	  static u16 timeCount1 = 1000;
	  static u16 timeCount2 = 4000;
	  static u16 timeCount3 = 0;
	  static u8 in_flag = 0;
	  static u8 index = 0;

if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
		{ 
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除中断标志位  

			  /********************************************  以下为滴速计算  *********************************************/
			  /* 方法:取N个脉冲,计算每个脉冲与脉冲直接的间隔时间,求出平均每个脉冲之间的时间间隔,最终转换为(滴/min) */

			  if(drop == 1)//高电平
				{
if(in_flag == 0)in_flag = 1;
if(start_flag) 
						{
								start_flag = 0;
								total_time += times;  //计算累计的时间
							  PulseCount ++;       //脉冲计数,由低电平到高电平的一个跳变才算一个
							  times = 0;
						}
				}
else
				{
					  if(in_flag == 1)
						{
								in_flag = 0;
							  start_flag = 1;
						}
				}
if(start_flag)
				{
						times ++;     //脉冲与脉冲之间的时间计数,单位ms
				}
// 无条件累加timeout,确保即使没有脉冲也能触发清零
				timeout++;

// 修改清零判断条件,直接比较毫秒数
if(timeout >= SampleTimeout*1000)  //取样时间太长了,取消计时
				{
/* 相关参数清0 */
						total_time = 0;
						PulseCount = 0;
						start_flag = 0;
						Speed = 0;
						timeout = 0;
						times = 0;
				}

if(PulseCount>=SampleNum)
				{
						PulseCount = 0;
						total_time = total_time / SampleNum; //计算平均每个取样脉冲之间的时间
						Speed = 60000 / total_time;         //转换为  滴/min

						total_time = 0;
					  timeout = 0;
				}
/********************************************   END    *********************************************/
/**************************************************************************************************/

				timeCount1 ++;
				timeCount2 ++;
				timeCount3 ++;

if(timeCount1>=1000)  //1s
				{
						timeCount1 = 0;
					  shuaxin = 1;
				}

if(timeCount3>=300)  //300ms
				{
						timeCount3 = 0;

					  shanshuo = !shanshuo;
					  if(!setFlag)
						{
if(NoWater==1)  //无药水,蜂鸣器一直报警
								{
										beep = 1;
								}
else
								{
if(((Speed!=0)&&((Speed<speed_min)||(Speed>speed_max))))//滴速温度心率血氧不在范围,蜂鸣器报警
										{
												beep = ~beep;
										}
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;
				}
	  }
}

七、单片机实物资料

资料获取 查看主页介绍:兆龙电子单片机设计

相关推荐
d111111111d12 分钟前
SPI通信协议--在STM32中介绍(学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习
说私域14 分钟前
开源AI大模型、AI智能名片与S2B2C商城小程序在互联网与传统行业融合中的应用与影响
人工智能·小程序·开源
up向上up2 小时前
基于STM32的电子钟万年历Proteus仿真设计_LCD1602显示
stm32·单片机·proteus
q***07143 小时前
SocketTool、串口调试助手、MQTT中间件基础
单片机·嵌入式硬件·中间件
新晨单片机设计3 小时前
【S001A】基于STM32单片机视力保护仪【Proteus仿真+Keil程序+报告+原理图】
stm32·单片机·proteus
爱吃程序猿的喵5 小时前
STM32嵌入式系统开发实战1:OLED显示、串口通信与GPIO控制
stm32·单片机·嵌入式硬件
ajassi20006 小时前
开源 Objective-C IOS 应用开发(十九)视频的播放
ios·开源·objective-c
up向上up7 小时前
【普中】基于普中51开发板单片机的8_8点阵滚动显示设计
单片机·51单片机·proteus
数字游名Tomda8 小时前
腾讯开源最新视频生成模型:仅8.3B,元宝已接入
人工智能·开源·开源软件
Bona Sun8 小时前
单片机手搓掌上游戏机(十二)—esp8266运行gameboy模拟器之编译上传
c语言·c++·单片机·游戏机