基于单片机的智能药盒设计

人口老龄化是当今世界人口发展的趋势,这种人口年龄结构的变化正在广泛而深刻地影响着人类社会生活的各个方面。相关调查显示目前老年人产品逐渐增多,但还不能满足中国社会的需求,随着年龄的增长,老年人体能下降且容易生病,时常需要持续吃药,所以老年人智能药盒也受到广泛的关注。在现实生活中,老年人常常会出现记忆丧失或者遗忘的时候,难免会出现漏服的现象,而当今社会老年人的子女往往会因为工作等原因无法及时提醒老年人按时服药。为解决老年人按时服药困难的问题,设计一款提醒使用者按时服药的辅助用药类产品,能够有效地解决部分老年人的用药问题,同时方便使用者存储药物。

设计的基本条件:

本设计以单片机为主控芯片,采用红外传感器、按键模块、蜂鸣器模块、显示模块、GSM模块等构成较为完善的硬件模块,达成设计的基本条件。

设计依据:

(1)基于单片机的智能药盒设计是个实际项目,通过查阅相关的资料并认真研究与分析,制定科学的设计内容和技术路线,为设计确定了科学依据。
(2)对设计中使用的红外传感器、蜂鸣器模块、显示模块、GSM模块等等模块和单片机芯片有一定的了解,能够熟练地使用设计中用到的元器件,并对所用知识进行系统的学习,有深入的了解,为设计的完成提供了技术支撑。

主要内容如下:

(1)通过按键设置时钟的时间以及每个药物位置的服药次数;
(2)到达指定的服药时间,蜂鸣器发出警报;
(3)测量体温,并通过红外检测药物是否被拿起;
(4)通过GSM模块发送信息提醒监护人;
(5)通过显示屏显示当天该吃药物的位置、次数以及时间。

本设计欲达到的目的:

设计出一款智能药盒,使之能够通过按键设置时间以及每个药物位置的服药次数,在到达指定时间时会发出警报提醒服药,通过传感器检测体温,并通过红外检测药物是否被拿起,若十分钟内药物未被拿起则通过GSM模块发送信息提醒监护人,相关参数通过显示屏显示。

演示视频

单片机智能药盒

部分核心代码

/*******************************************************************************
--------------------------------------------------------------------------------
* 毕设名称		 : 基于STC15F2K60S2的智能药箱
* 作品说明       : 药物定时,吃药提醒,当日药物提示,未吃药短信提醒,LCD1602液晶显示
* 作    者		 : F9986858
*******************************************************************************/

//#include<STC15F2K60S2.h>
#include"lcd.h"
#include"ds1302.h"
#include"DS18B20.h"

#define yh 0x80      //液晶 第一行的初始位置
#define er 0x80+0x40 //     第二行的初始位置

uchar code tab0[]={"Medicine  Select"};	//字符串数组,用于液晶显示
uchar code tab1[]={"Choose :        "};
uchar code tab2[]={" Times   Select "};	
uchar code tab3[]={"       times/day"};
uchar code tab4[]={"Clock Setting / "};
uchar code tab5[]={"    End  Day    "};
uchar code tab6[]={"      :  :00    "};
uchar code tab7[]={"       -        "};
uchar code tab8[]={"Alarm Clock Work"};
uchar code tab9[]={"Today's medicine"};
uchar code tab10[]={"      None      "};
uchar code tab11[]={"Medicine      / "};
uchar idata clock[6][4][4];				//三维数组,用于保存闹钟盒子数,时分,截止日期
uchar idata clock_flag[6];				//闹钟使能
uchar idata beep_flag[6][4];			//蜂鸣器报警使能
uchar nian,yue,ri,week,shi,fen,miao;	//年月日时分秒
uchar temp,temp1,CLOCK_FUN,MEDICINE_FUN,FLAG_CLOCK,FLAG_MEDICINE,FLAG_auxiliary;		//temp,temp1临时变量保存,时钟功能,药盒功能,时钟设置标志,闹钟设置标志,辅助功能标志
uchar box_flag;	   //盒子保存变量
uchar times_flag;  //次数保存变量
uchar yao=1;					   //默认从第一个药盒开始
uchar times[6]={1,1,1,1,1,1}; 	   //默认次数为1
uchar idata chiyao_flag[6][4];	   //相应药物吃药标志,默认未吃
//按键引脚定义
sbit KEY1=P2^5;		//时钟功能++
sbit KEY2=P2^4;	    //时钟功能--
sbit KEY3=P2^3;		//数++
sbit KEY4=P2^2;		//数--
sbit KEY5=P2^1;		//闹钟功能--
sbit KEY6=P2^0;		//闹钟功能++
sbit KEY7=P3^6;		//吃药次数,时间点查询
sbit KEY8=P3^7;		//今天的药物查询
//红外引脚定义
sbit OUT1=P1^5;		
sbit OUT2=P1^6;
sbit OUT3=P1^7;
sbit OUT4=P3^4;
sbit OUT5=P3^3;
sbit OUT6=P3^2;

sbit BEEP=P3^5;
bit Display_Flag = 0;

bit Display_Flag1 = 0;
/*******************************************************************************
* 函数名         : write_sfm
* 函数功能		 : LCD显示时分秒函数
* 输入           : add,dat
* 输出         	 : 无
*******************************************************************************/
void write_sfm(uchar add,uchar dat)//写时分秒
{
	uchar gw,sw;
	gw=dat%10;
	sw=dat/10;
	LcdWriteCom(er+add);
	LcdWriteData(0x30+sw);
	LcdWriteData(0x30+gw);			
}
/*******************************************************************************
* 函数名         : write_nyr
* 函数功能		 : LCD显示年月日函数
* 输入           : add,dat
* 输出         	 : 无
*******************************************************************************/
void write_nyr(uchar add,uchar dat)//写年月日
{
	uchar gw,sw;
	gw=dat%10;
	sw=dat/10;
	LcdWriteCom(yh+add);
	LcdWriteData(0x30+sw);
	LcdWriteData(0x30+gw);	
}

void Uart1Init(void)		//9600bps@12.000MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器1时钟为Fosc,即1T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
	TL1 = 0xC7;		//设定定时初值
	TH1 = 0xFE;		//设定定时初值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}

void Uart1Send(unsigned char dat)
{
	SBUF=dat;
	while(!TI);     //等待发送完成信号
	TI=0;	
}

/*******************************************************************************
* 函数名         : Timer0Init
* 函数功能		 : 定时器0设置函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Timer0Init(void)		//50毫秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0xB0;		    //设置定时初值		50ms
	TH0 = 0x3C;		    //设置定时初值
	TF0 = 0;		    //清除TF0标志
	ET0 = 1;
	TR0 = 1;		//定时器0开始计时  	
	EA = 1;
}
/*******************************************************************************
* 函数名         : BCD_Decimal
* 函数功能		 : BCD码转换函数
* 输入           : bcd
* 输出         	 : 无
*******************************************************************************/
uchar BCD_Decimal(uchar bcd)			//BCD码转换
{
	 uchar Decimal;
	 Decimal=bcd>>4;
	 return(Decimal=Decimal*10+(bcd&=0x0F));
}
/*******************************************************************************
* 函数名         : clock_set
* 函数功能		 : 时钟设置函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void clock_set(void)
{
	if((KEY1==0)&&(FLAG_MEDICINE==0)&&(FLAG_auxiliary==0))		    //时钟设置功能++
	{
		Delaynms(20);										//延时消抖
		if((KEY1==0)&&(FLAG_MEDICINE==0)&&(FLAG_auxiliary==0))					//再次判断
		{									
			FLAG_CLOCK=1;									//时钟正在设置,药盒不能设定,辅助功能不能使用,只能设置时钟
			CLOCK_FUN++;									//时钟功能+1,功能分别为:秒,分,时,日,月,年
			switch(CLOCK_FUN)								//判断是什么功能
			{
				case 1:	TR0=0;								//定时器0关闭,不提取ds1302的时间,即液晶不会自动跳数字
						LcdWriteCom(er+0x07);				//指针移动到秒的个位
			            LcdWriteCom(0x0f);					//光标闪烁
						temp=(miao)/10*16+(miao)%10;		//转换
						Ds1302Write(0x8e,0x00);			    //关闭DS1302写保护,可写入
	   					Ds1302Write(0x80,0x80|temp);        //写入秒
	   					Ds1302Write(0x8e,0x80);				//打开写保护,不可写入
						break;
				case 2:	LcdWriteCom(er+0x04);				//光标移动到分个位
						break;
				case 3:	LcdWriteCom(er+0x01);				//光标移动到时个位
						break;
				case 4:	LcdWriteCom(yh+0x09);				//光标移动到日个位
						break;
				case 5:	LcdWriteCom(yh+0x06);			    //光标移动到月个位
						break;
				case 6:	LcdWriteCom(yh+0x03);				//光标移动到年个位
						break;
				case 7:	LcdWriteCom(0x0c);					//关闭光标闪烁
						CLOCK_FUN=0;						//时钟功能清零
						FLAG_CLOCK=0;						//时钟设置标志清零,药盒可设置
						temp=(miao)/10*16+(miao)%10;	    //再次写入秒
						Ds1302Write(0x8e,0x00);
	   					Ds1302Write(0x80,0x00|temp);
	   					Ds1302Write(0x8e,0x80);
						TR0=1;							   //打开定时器0,定时获取DS1302内部时间,显示到LDC
						break;							
			}
			while(KEY1==0);								    //等待按键松手
	    }
    }

	if((KEY2==0)&&(FLAG_MEDICINE==0)&&(FLAG_auxiliary==0))		    //时钟设置功能--
	{
		Delaynms(20);
		if((KEY2==0)&&(FLAG_MEDICINE==0)&&(FLAG_auxiliary==0))
		{
			if(FLAG_CLOCK==1)							    //若进入时钟设置,功能--才能使用
			{
				CLOCK_FUN--;
				if(CLOCK_FUN==0)							//功能范围控制,不能小于0
				{
					CLOCK_FUN=1;
				}
			}
			switch(CLOCK_FUN)								//同上
			{
				case 1:	TR0=0;
						LcdWriteCom(er+0x07);
			            LcdWriteCom(0x0f);
						temp=(miao)/10*16+(miao)%10;
						Ds1302Write(0x8e,0x00);
	   					Ds1302Write(0x80,0x80|temp);//miao
	   					Ds1302Write(0x8e,0x80);
						break;
				case 2:	LcdWriteCom(er+0x04);
						break;
				case 3:	LcdWriteCom(er+0x01);
						break;
				case 4:	LcdWriteCom(yh+0x09);
						break;
				case 5:	LcdWriteCom(yh+0x06);
						break;
				case 6:	LcdWriteCom(yh+0x03);
						break;							
			}
			while(KEY2==0);
	    }
    }	
}
/*******************************************************************************
* 函数名         : medicine_set
* 函数功能		 : 药物设定函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void medicine_set()
{
	if((KEY6==0)&&(FLAG_CLOCK==0)&&(FLAG_auxiliary==0))			//药盒功能++
	{
		Delaynms(20);
		if((KEY6==0)&&(FLAG_CLOCK==0)&&(FLAG_auxiliary==0))					  //再次判断按键按下,以及时钟没有在设置中
		{
			uchar num;									  //临时变量定义
			FLAG_MEDICINE=1;							  //建立药盒正在设置标志
			MEDICINE_FUN++;								  //药盒功能++
			switch(MEDICINE_FUN)						  //功能判断
			{
				case 1:	TR0=0;							  //功能若为1,关闭定时器
				        LcdWriteCom(yh);				  //LCD指针第一行
						for(num=0;num<16;num++)			  //刷一下固定显示字符串
							LcdWriteData(tab0[num]);
						LcdWriteCom(er);				  //LCD指针第二行
						for(num=0;num<16;num++)			  //刷一下固定显示字符串
							LcdWriteData(tab1[num]);
						LcdWriteCom(er+0x0c);			  //LCD第二行第十三
						LcdWriteData(yao+'0');			  //显示药盒变量
						LcdWriteCom(er+0x0c);			  //指针复位(与光标复位一个意思)
						LcdWriteCom(0x0f);				  //光标闪烁
						break;							  //执行完跳出switch语句
				case 2:	LcdWriteCom(yh);				  //功能2,药次数记录
						for(num=0;num<16;num++)
							LcdWriteData(tab2[num]);
						LcdWriteCom(er);
						for(num=0;num<16;num++)
							LcdWriteData(tab3[num]);
						LcdWriteCom(er+0x03);			  
						LcdWriteData(times[yao-1]+'0');	  //在LCD显示吃药次数
						LcdWriteCom(er+0x03);
						LcdWriteCom(0x0f);
						break;
				case 3: LcdWriteCom(yh);				  //第一次吃药的分
						for(num=0;num<16;num++)
							LcdWriteData(tab4[num]);
						LcdWriteCom(er);
						for(num=0;num<16;num++)
							LcdWriteData(tab6[num]);
						LcdWriteCom(yh+13);				  
						LcdWriteData(1+'0');			  //显示第一次
						LcdWriteCom(yh+15);
						LcdWriteData(times[yao-1]+'0');	  //显示次数总数 ,如1/3
						write_sfm(4,clock[yao-1][0][1]);  //在LCD显示第一次定时的分
						write_sfm(7,clock[yao-1][0][0]);  //在LCD显示第一次定时的时
						LcdWriteCom(er+0x08);
						break;
				case 4: LcdWriteCom(yh);				  //第一次吃药的时
						for(num=0;num<16;num++)
							LcdWriteData(tab4[num]);
						LcdWriteCom(er);
						for(num=0;num<16;num++)
							LcdWriteData(tab6[num]);
						LcdWriteCom(yh+13);
						LcdWriteData(1+'0');
						LcdWriteCom(yh+15);
						LcdWriteData(times[yao-1]+'0');
						write_sfm(4,clock[yao-1][0][1]);
						write_sfm(7,clock[yao-1][0][0]);
						LcdWriteCom(er+0x05);
						break;									  
				case 5: if(times[yao-1]>=2)				  //若次数大于2,设置第二次吃药的分		 
						{
						LcdWriteCom(yh);				 
						for(num=0;num<16;num++)
							LcdWriteData(tab4[num]);
						LcdWriteCom(er);
						for(num=0;num<16;num++)
							LcdWriteData(tab6[num]);
						LcdWriteCom(yh+13);
						LcdWriteData(2+'0');
						LcdWriteCom(yh+15);
						LcdWriteData(times[yao-1]+'0');
						write_sfm(4,clock[yao-1][1][1]);
						write_sfm(7,clock[yao-1][1][0]);
						LcdWriteCom(er+0x08);						
						}else	MEDICINE_FUN=10;		 //否者直接跳到设置截止日期
						break;
				case 6: LcdWriteCom(yh);				 //第2次吃药的时
						for(num=0;num<16;num++)
							LcdWriteData(tab4[num]);
						LcdWriteCom(er);
						for(num=0;num<16;num++)
							LcdWriteData(tab6[num]);
						LcdWriteCom(yh+13);
						LcdWriteData(2+'0');
						LcdWriteCom(yh+15);
						LcdWriteData(times[yao-1]+'0');
						write_sfm(4,clock[yao-1][1][1]);
						write_sfm(7,clock[yao-1][1][0]);
						LcdWriteCom(er+0x05);
						break;
				case 7: if(times[yao-1]>=3)				//若次数大于3,设置第三次吃药的分
						{
						LcdWriteCom(yh);				 
						for(num=0;num<16;num++)
							LcdWriteData(tab4[num]);
						LcdWriteCom(er);
						for(num=0;num<16;num++)
							LcdWriteData(tab6[num]);
						LcdWriteCom(yh+13);
						LcdWriteData(3+'0');
						LcdWriteCom(yh+15);
						LcdWriteData(times[yao-1]+'0');
						write_sfm(4,clock[yao-1][2][1]);
						write_sfm(7,clock[yao-1][2][0]);
						LcdWriteCom(er+0x08);						
						}else	MEDICINE_FUN=10;		 //否者直接跳到设置截止日期
						break;
				case 8: LcdWriteCom(yh);				 //第3次吃药的时
						for(num=0;num<16;num++)
							LcdWriteData(tab4[num]);
						LcdWriteCom(er);
						for(num=0;num<16;num++)
							LcdWriteData(tab6[num]);
						LcdWriteCom(yh+13);
						LcdWriteData(3+'0');
						LcdWriteCom(yh+15);
						LcdWriteData(times[yao-1]+'0');
						write_sfm(4,clock[yao-1][2][1]);
						write_sfm(7,clock[yao-1][2][0]);
						LcdWriteCom(er+0x05);
						break;
				case 9: if(times[yao-1]>=4)				//若次数大于4,设置第四次吃药的分
						{
						LcdWriteCom(yh);				 
						for(num=0;num<16;num++)
							LcdWriteData(tab4[num]);
						LcdWriteCom(er);
						for(num=0;num<16;num++)
							LcdWriteData(tab6[num]);
						LcdWriteCom(yh+13);
						LcdWriteData(4+'0');
						LcdWriteCom(yh+15);
						LcdWriteData(times[yao-1]+'0');
						write_sfm(4,clock[yao-1][3][1]);
						write_sfm(7,clock[yao-1][3][0]);
						LcdWriteCom(er+0x08);						
						}else	MEDICINE_FUN=10;		//否者直接跳到设置截止日期
						break;
				case 10: LcdWriteCom(yh);				//第4次吃药的时
						for(num=0;num<16;num++)
							LcdWriteData(tab4[num]);
						LcdWriteCom(er);
						for(num=0;num<16;num++)
							LcdWriteData(tab6[num]);
						LcdWriteCom(yh+13);
						LcdWriteData(4+'0');
						LcdWriteCom(yh+15);
						LcdWriteData(times[yao-1]+'0');
						write_sfm(4,clock[yao-1][3][1]);
						write_sfm(7,clock[yao-1][3][0]);
						LcdWriteCom(er+0x05);
						break;
				case 11: LcdWriteCom(yh);				  //截止日
						for(num=0;num<16;num++)
							LcdWriteData(tab5[num]);
						LcdWriteCom(er);
						for(num=0;num<16;num++)
							LcdWriteData(tab7[num]);
						write_sfm(5,clock[yao-1][0][3]);
						write_sfm(8,clock[yao-1][0][2]);
						LcdWriteCom(er+0x09);
						break;
				case 12: LcdWriteCom(yh);				  //截止月
						for(num=0;num<16;num++)
							LcdWriteData(tab5[num]);
						LcdWriteCom(er);
						for(num=0;num<16;num++)
							LcdWriteData(tab7[num]);
						write_sfm(5,clock[yao-1][0][3]);
						write_sfm(8,clock[yao-1][0][2]);
						LcdWriteCom(er+0x06);
						break;
				case 13: LcdWriteCom(yh);				 //时钟开关
						for(num=0;num<16;num++)
							LcdWriteData(tab8[num]);
						LcdWriteCom(er);				 //清屏
						for(num=0;num<16;num++)
							LcdWriteData(' ');
						if(clock_flag[yao-1]==1)		 //显示开
						{
						 	LcdWriteCom(er+0x06);
							LcdWriteData('O');
							LcdWriteData('N');
							LcdWriteData(' ');
						}else							 //显示关,默认关闭
						{
							LcdWriteCom(er+0x06);
							LcdWriteData('O');
							LcdWriteData('F');
							LcdWriteData('F');	
						}
						LcdWriteCom(0x0C);
						break;
				case 14:LcdWriteCom(yh);			//清屏 
						for(num=0;num<16;num++)
							LcdWriteData(' ');
						LcdWriteCom(er);			//清屏	  
						for(num=0;num<16;num++)
							LcdWriteData(' ');
						TR0=1;						//开定时器0
						FLAG_MEDICINE=0;			//药盒设置标志清零,表示药盒设定完毕
						MEDICINE_FUN=0;				//药盒功能清零
						break;					
			}			
		}
		while(KEY6==0);	
	}
	
	if((KEY5==0)&&(FLAG_CLOCK==0)&&(FLAG_auxiliary==0))			//药盒功能--
	{
		Delaynms(20);
		if((KEY5==0)&&(FLAG_CLOCK==0)&&(FLAG_auxiliary==0))
		{	
			uchar num;	
			if(FLAG_MEDICINE==1)
			{
				if(MEDICINE_FUN==1)					  //跳回时钟页面
				{
					LcdWriteCom(yh);				  //清屏
					for(num=0;num<16;num++)
						LcdWriteData(' ');
					LcdWriteCom(er);				  //清屏
					for(num=0;num<16;num++)
						LcdWriteData(' ');
					LcdWriteCom(0x0c);
					TR0=1;
					FLAG_MEDICINE=0;
					MEDICINE_FUN=0;
				}
				else								  //跳回药盒设置页面
				{
					MEDICINE_FUN=1;					  //药盒选择
		            TR0=0;
			        LcdWriteCom(yh);				
					for(num=0;num<16;num++)
						LcdWriteData(tab0[num]);
					LcdWriteCom(er);
					for(num=0;num<16;num++)
						LcdWriteData(tab1[num]);
					LcdWriteCom(er+0x0c);
					LcdWriteData(yao+'0');
					LcdWriteCom(er+0x0c);
					LcdWriteCom(0x0f);
				}									
			}			
		}
		while(KEY5==0);	
	}	
}
/*******************************************************************************
* 函数名         : main
* 函数功能		 : 主函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void main(void)
{
	BEEP=0;								    //禁止蜂鸣器
	IO_init();			//IO口初始化
	Uart1Init();		//串口1初始化
	LcdInit();			//LCD初始化
	Ds1302Init();		//DS1302初始化
	Delaynms(10);		//等待DS1302初始化完成
	Ds1302ReadTime();	//读取ds1302的时间
	LcdDisplay();		//显示
	Timer0Init();		//定时器0初始化
	clock[0][0][2]=clock[0][0][3]=1;		//截止日期默认1月1号
	clock[1][0][2]=clock[1][0][3]=1;
	clock[2][0][2]=clock[2][0][3]=1;
	clock[3][0][2]=clock[3][0][3]=1;
	clock[4][0][2]=clock[4][0][3]=1;
	clock[5][0][2]=clock[5][0][3]=1; 
	while(1)
	{
		clock_set();					  //时钟设置扫描
		medicine_set();					  //药盒设置扫描
		digital_change();				  //时钟/药盒数字有无改变扫描
		auxiliary();					  //辅助功能扫描
		clock_scan();					  //药盒闹钟扫描
		temp11=Ds18b20ReadTemp();		
		GetTemp();
		if((KEY8==0)&&(Key8Press==0))
		{
			Delaynms(20);
			if((KEY8==0)&&(Key8Press==0))
			{
				Display_Flag=~Display_Flag;
			}
			while(KEY8==0);
		}
	}		
}
#include<STC15F2K60S2.h>
#include<intrins.h>		//包括nop()函数	  

unsigned char temp;			  //保存药物号

sbit Pow = P3^6;

/*******************************************************************************
* 函数名         : Delay100ms
* 函数功能		 : 延时100ms
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Delay100ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 5;
	j = 144;
	k = 71;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

/*******************************************************************************
* 函数名         : Delay
* 函数功能		 : 延时 n*100ms
* 输入           : a
* 输出         	 : 无
*******************************************************************************/
void Delay(unsigned int a)
{
	unsigned int b; 
	for(b=a;b>0;b--)
	   Delay100ms();
}

/*******************************************************************************
* 函数名         : IO_init
* 函数功能		 : 配置I/O口
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void IO_init(void)
{
//所有I/O口全设为准双向,弱上拉模式
    P0M0=0x00;				
	P0M1=0x00;
	P1M0=0x00;
	P1M1=0x00;
	P2M0=0x00;      
	P2M1=0x00;
	P3M0=0x00;
	P3M1=0x00;
	P4M0=0x00;
	P4M1=0x00;
	P5M0=0x00;
	P5M1=0x00;
	P6M0=0x00;
	P6M1=0x00;
	P7M0=0x00;
	P7M1=0x00;
}

/*******************************************************************************
* 函数名         : Uart1Init
* 函数功能		 : 串口1设置
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Uart1Init(void)		//9600bps@12.000MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x01;		//串口1选择定时器2为波特率发生器
	AUXR |= 0x04;		//定时器2时钟为Fosc,即1T
	T2L = 0xC7;		    //设定定时初值
	T2H = 0xFE;		    //设定定时初值
	AUXR |= 0x10;		//启动定时器2
	ES=1;			//开串口1中断
	EA=1;		    //开总中断
}

/*******************************************************************************
* 函数名         : Uart1Send
* 函数功能		 : 字节发送
* 输入           : dat
* 输出         	 : 无
*******************************************************************************/
void Uart1Send(unsigned char dat)
{
	SBUF=dat;
	while(!TI);     //等待发送完成信号
	TI=0;	
}

/*******************************************************************************
* 函数名         : Uart1Sends
* 函数功能		 : 发送字符串
* 输入           : *str
* 输出         	 : 无
*******************************************************************************/
void Uart1Sends(unsigned char *str)
{
	while(*str!='\0')	//检测字符串结束符
	{
		SBUF=*str;
		while(!TI);//等待发送完成信号
		TI=0;
		str++;	   //指针+1
	}
}

/*******************************************************************************
* 函数名         : Messages
* 函数功能		 : 接收未按时吃药标志,发送相应短信
* 输入           : th
* 输出         	 : 无
*******************************************************************************/
void Messages(unsigned char th)
{
	if(th>0&&th<7)
	{
		P_SW1 |= 0x40;		                               //串口引脚转移1->2
		ES=0;											   //关闭串口1中断
		Uart1Sends("AT+CSCS=\"GSM\"\r\n");
		Delay(1);										   //延时3S
		Uart1Sends("AT+CMGF=1\r\n");					   //选择短信消息格式->文本模式
		Delay(1);
		Uart1Sends("AT+CSCA?\r\n");						   
		Delay(1);
		Uart1Sends("AT+CSMP=17,167,0,0\r\n");			   //无发送报告,保留时间24小时,通常为0,发送英文
		Delay(1);
		Uart1Sends("AT+CMGS=\"18888888888\"\r\n");		   //监护人号码
		
		Delay(1);
		Uart1Sends("The patient did not take medicine");   //短信内容前半部分
		switch(th)
		{
			case 0X01: Uart1Sends(" 1 on time!");break;	   //短信内容后半部分,发送对应的药号
			case 0X02: Uart1Sends(" 2 on time!");break;
			case 0X03: Uart1Sends(" 3 on time!");break;
			case 0X04: Uart1Sends(" 4 on time!");break;
			case 0X05: Uart1Sends(" 5 on time!");break;
			case 0X06: Uart1Sends(" 6 on time!");break;
		}
		Uart1Send(0x1a);								   //结束发送
		P_SW1 &= 0xbf;		                               //串口引脚转移2->1
		temp=0;											   //变量使用后清零
		ES=1;											   //开串口1中断,允许接收
	 }
}

/*******************************************************************************
* 函数名         : main
* 函数功能		 : 主函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void main(void)
{
	IO_init();											  //I/O口初始化
	Uart1Init();										  //串口1初始化
	//Delay(100);											  //等待GSM联网,10s
	temp=0;												  //变量清零
	Pow=1;Delay(1);
	Pow=0;Delay(45);
	Pow=1;
	while(1)
	{
		Messages(temp);
	}
}

/*******************************************************************************
* 函数名         : Uart1
* 函数功能		 : 串口1中断服务函数,接收数据
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Uart1 (void) interrupt 4					
{
	if(RI==1)				  //清收标志有效
	{
		RI=0;				  //接收标志清零
		temp=SBUF;	      //接收变量接收缓冲器数据
	}  
}


  • 5
    点赞
  • 117
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
智能药盒是一种将现代科技应用于医疗保健领域的产品。它能够准确地记录药品的服用情况,提醒患者按时服药,避免漏服或重复服用等问题,从而提高患者的生活质量和健康水平。本文将介绍一种基于单片机智能药盒设计与实现。 一、设计方案 1. 系统架构 本系统采用单片机作为控制核心,通过与药盒内部的传感器相连,实现对药品的监控和记录。同时,系统还配备了蓝牙模块,可以将数据传输到手机或电脑上,方便用户对药品的管理和监控。 2. 硬件设计 (1)单片机选择 本系统采用STM32F103C8T6单片机作为控制核心,其具有较高的性能和稳定性,并且容易进行程序开发和调试。 (2)传感器选择 本系统采用光电传感器进行药品的监测。当药盒内部的药品被取出时,药盒内部的光线强度会发生变化,传感器会检测到信号并向单片机发送数据。 (3)蓝牙模块选择 本系统采用HC-05蓝牙模块进行数据传输,该模块具有较高的稳定性和传输速度,可以方便地与手机或电脑进行连接。 (4)电源设计 本系统采用5V直流电源供电,可以通过USB接口或直流适配器进行供电。 3. 软件设计 (1)系统架构 本系统采用模块化设计,主要包括数据采集模块、数据处理模块、数据存储模块、蓝牙通信模块和显示模块等。 (2)数据采集 数据采集模块主要采用光电传感器进行药品的监测,当药品被取出时,传感器会向单片机发送数据。 (3)数据处理 数据处理模块主要对采集到的数据进行处理和分析,判断是否需要提醒用户服药,并将数据存储到内部存储器中。 (4)数据存储 数据存储模块主要将采集到的数据存储到内部存储器中,以便后续的数据分析和管理。 (5)蓝牙通信 蓝牙通信模块主要负责将存储在内部存储器中的数据传输到手机或电脑上,方便用户进行管理和监控。 (6)显示模块 显示模块主要负责向用户展示药品的服用情况和提醒信息,以便用户进行及时的服药。 二、实现步骤 1. 硬件连接 将单片机、光电传感器、HC-05蓝牙模块和显示器连接到一起,构成完整的系统。 2. 程序开发 按照设计方案中的模块进行程序开发,分别实现数据采集、数据处理、数据存储、蓝牙通信和显示等功能。 3. 调试测试 对系统进行调试测试,检查各个模块是否正常工作,并对系统进行优化和改进。 三、结论 本文介绍了一种基于单片机智能药盒设计与实现。该系统采用光电传感器进行药品的监测,配备了蓝牙模块,可以将数据传输到手机或电脑上,方便用户对药品的管理和监控。该系统具有较高的稳定性和可靠性,可以提高患者的生活质量和健康水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值