c51实现老人跌倒,心率异常报警系统

简介: c51实现老人跌倒,心率异常报警系统

本设计硬件部分:由OLED液晶显示屏,ADXL345角度传感器,SIM800C短信模块,GPS定位模块。以及心形脉搏测量,以及蜂鸣器报警电路再加上按键电路组成。


设计可实现:


心率的测量,按键1,即可开始心率的测量,测量结束,数据会显示到OLED液晶上,若心率超过阈值,同时还会发送报警短信用以提醒。

可检测是否摔倒,如若摔倒,则液晶可显示摔倒提示。并产生报警提醒,同时会通过GSM模块获取经纬度信息,发送含有经纬度的报警短信到绑定的手机。如果摔倒后直立,则会发送直立提示短信。

同时还可以进行手动的取消摔倒报警,按下按键2,则可以取消本次的摔倒报警。

按下按键3,则可以发送含有当前具体经纬度的求助短信。

OLED液晶,可以显示出当前状态,心率数据,以及具体的经纬度数据。


发送短信的手机号,只需第一次使用时发送连接短信,单片机会自动将手机号进行保存。后期不需要再次进行发送。


器件选型:


mcu单片机: STC12C5A60S2

GSM/GPRS:  SIM800C

加速度模块: ADXL345

心率: PulseSensor


主程序代码:

#include <STC12C5A60S2.H>
#include "eeprom12.H"
#include "ADXL345.h"
#include "OLED.H"
#include "usercode.H"
#include "SIM800.H"
#include "key.H"
//=====================================================================================================================  保存经纬度
void Memory_data()
{
    IapEraseSector(0x0400);
    IapProgramByte(0x0401,jing_du/100000000%10);
    IapProgramByte(0x0402,jing_du/10000000%10);
    IapProgramByte(0x0403,jing_du/1000000%10);
    IapProgramByte(0x0404,jing_du/100000%10);
    IapProgramByte(0x0405,jing_du/10000%10);
    IapProgramByte(0x0406,jing_du/1000%10);
    IapProgramByte(0x0407,jing_du/100%10);
    IapProgramByte(0x0408,jing_du/10%10);
    IapProgramByte(0x0409,jing_du/1%10);
    IapProgramByte(0x0412,wei_du/10000000%10);
    IapProgramByte(0x0413,wei_du/1000000%10);
    IapProgramByte(0x0414,wei_du/100000%10);
    IapProgramByte(0x0415,wei_du/10000%10);
    IapProgramByte(0x0416,wei_du/1000%10);
    IapProgramByte(0x0417,wei_du/100%10);
    IapProgramByte(0x0418,wei_du/10%10);
    IapProgramByte(0x0419,wei_du/1%10);
    IapProgramByte(0x040A,SIM800_Heat);
}
void Read_data()
{
    jing_du = IapReadByte(0x0401)*100000000 + IapReadByte(0x0402)*10000000 + IapReadByte(0x0403)*1000000 + IapReadByte(0x0404)*100000 +
          IapReadByte(0x0405)*10000 + IapReadByte(0x0406)*1000 + IapReadByte(0x0407)*100 + IapReadByte(0x0408)*10 +
          IapReadByte(0x0409) ;
    wei_du = IapReadByte(0x0412)*10000000 + IapReadByte(0x0413)*1000000 + IapReadByte(0x0414)*100000 + IapReadByte(0x0415)*10000 + 
          IapReadByte(0x0416)*1000 + IapReadByte(0x0417)*100 + IapReadByte(0x0418)*10 + IapReadByte(0x0419) ;
    SIM800_Heat=IapReadByte(0x040A);
}
//=====================================================================================================================  读取角度数据,判断跌倒
/*****************************************************************************************************************
    角度判断跌倒函数:
      读取出角度数据后,然后去比较这个角度数据,有没有超过一定值,如果超过一定值则判定为跌倒。
*****************************************************************************************************************/
void Read_ADXL345()
{   
    static char cs=0; //-- 定义静态局部变量   角度连续5次数据判断
    if(Read_dat)
    {
        Read_dat=0;
        duqujiaodu();  
        if(Y_dat<=0)  Y_dat=0; //-- 平放时,避免角度出现0度以下
        if(Y_dat>=300)  Y_dat=0; //-- 保证数据合理性。
        if(Fall_Flag==0)
        {  //-- 未检测到摔倒情况时
            if(cs!=5)   
            {
                if(Y_dat<190 || Y_dat>300)  cs++;
                else            cs=0;
            }else //-- 连续5次数据都判定为摔倒,此时系统确定当前为摔倒状态
            {
                cs=0;
                Fall_Flag=1;
            }
        }else//-- 检测到摔倒情况时
        {
            if(cs!=5)   
            {
                if(Y_dat<300 && Y_dat>=190) cs++;
                else            cs=0;
            }else //-- 连续5次数据都判定为未摔倒,此时系统确定当前为正常状态
            {
                cs=0;
                Fall_Flag=0;
            }
        }
    }
}
//=====================================================================================================================  角度报警
void police_ADXL345()
{
    if(Fall_Flag)//-- 确认摔倒后       
    {
        Up_Time=0;
        if(Fall_Time!=Fall_Cnt)     
        {     //-- 摔倒一定时间内,可手动取消
            if(Hand_Close==0)   Fall_Time++;  //-- 没有手动取消时,计时++
            else          Fall_Time=0;  //-- 在摔倒一定时间内,手动取消报警,计时清零 
        }else   //-- 时间到,报警发短信
        {
            if(Beep_Flag==0)            //-- 计时时间到报警标志为1,产生报警
            {                   //-- 发送摔倒短信
                Beep_Flag=1;
                GSM_Send=1;
                GSM_Send_Num=1;
                GSM_Send_Time=0;
            }
        }
    }else //-- 老人没有摔倒           
    {
        if(Up_Time!=0)        Up_Time--;      //-- 如果手动时间不等于0, 手动取消报警时间清零
        else            Hand_Close=0;     //-- 清零后,取消手动标志
        Fall_Time=0;//-- 摔倒时间清零
        if(Beep_Flag)                 //-- 直立后取消报警
        {                       //-- 发送直立短信
            Beep_Flag=0;
            GSM_Send=1;
            GSM_Send_Num=2;
            GSM_Send_Time=0;
        }           
    }  
}
//=====================================================================================================================  心率检测
/*****************************************************************************************************************
    心率检测函数:
      心率检测方法,就是先检测出第一次心跳的时候,将时间清零,开始计时,当再次检测到心跳后,停止计时
    读取出,时间数据,这个时间就是两次心跳之间的间隔时间,然后用1分钟除以这个时间,就可以得到1分钟之内
    对应的心跳数,循环测量多次,然后取平均值即可。
*****************************************************************************************************************/
bit OnceFlag=1;
void Xinlv_dispose()
{
    unsigned int pules=0;
    static bit Send_Flag=1;
    if(Start_Flag && Heat_Time==0)
    {
        if(Xinlv==0)
        {
            if(OnceFlag)
            {
                OnceFlag=0;
                if(Heat_State==0)   Heat_State=1;
                else if(Heat_State==1)  Heat_State=2;
            }
        }else OnceFlag=1;
        if(Heat_State==1)           TR1=1;  //-- 开始计时
        else if(Heat_State==2)
        {
            Heat_State=0;
            TR1=0;              //-- 停止计时,准备计算
            if((6000/Heat_ms) > 50 && (6000/Heat_ms) < 150)
            {
                if(Heat_Cnt<7)
                {
                    Heat_Cnt++;
                    if(Heat_Cnt>=3) 
                    {
                        pules = 6000/Heat_ms;         //Heat_dat = 
                        Heat_Total = Heat_Total+pules;
                        pules=0;
                    }
                }else
                {
                    SIM800_Heat = Heat_dat   = Heat_Total/5;
                    Heat_Total = Heat_Cnt=0;
                    Heat_Time  = xinlv_Time;   //-- 显示2分钟
                    Beep_Num=4;
                      Memory_data();         //-- 存储心率数据  
                }
            }
            Heat_ms = TH1 = TL1=0;
        }
    }
    if(Heat_Time!=0)    //-- 心跳测量完成
    {
        if(Heat_dat>Heat_H || Heat_dat<Heat_L)    
        {
            if(Send_Flag)
            {
                Send_Flag=0;
                Beep_Num = 100;
                GSM_Send=1;
                GSM_Send_Num=3; //-- 发送心率报警短信   SIM800_Heat
                GSM_Send_Time=0;
            }
        }
    }else Send_Flag=1;
}
uchar dis_Cnt=0;
//=====================================================================================================================  OLED液晶显示
void OLED_display_Init()
{
    display_GB2312_string(0,0,"                ");
    display_GB2312_string(0,1,"                ");
    display_GB2312_string(0,2,"  初 始 化");
    switch(dis_Cnt)
    {
        case  0:  display_GB2312_string(10,2,"       ");    break;
        case  1:  display_GB2312_string(10,2,".      ");    break;
        case  2:  display_GB2312_string(10,2,"..     ");    break;
        case  3:  display_GB2312_string(10,2,"...    ");    break;
        default:  break;
    }
    display_GB2312_string(0,3,"                ");
}
//=====================================================================================================================  OLED液晶显示
void OLED_display()
{
    display_GB2312_string(0,0,"当前状态:"); //------------------------------------------->第一行显示温度数据
    if(Fall_Flag==0)            display_GB2312_string(11,0," 正常");
    else                  display_GB2312_string(11,0," 摔倒");
    display_GB2312_string(0,1,"心率:"); //------------------------------------------->第二行显示心率数据
    if(Start_Flag==0)           display_GB2312_string(5,1,"---");
    else 
    {
        if(Heat_dat>99)           display_buff(5,1,Heat_dat/100%10);
        else                display_GB2312_string(5,1," ");
        if(Heat_dat>9)              display_buff(6,1,Heat_dat/10%10);
        else                display_GB2312_string(6,1," ");
        display_buff(7,1,Heat_dat/1%10);
    }
    display_GB2312_string(8,1,"次/分  ");
    display_GB2312_string(0,2,"经度:");//------------------------------------------->第三行  显示经度
    display_buff(5,2,jing_du/100000000%10);
    display_buff(6,2,jing_du/10000000%10);
    display_buff(7,2,jing_du/1000000%10);
    display_GB2312_string(8,2,"."); 
    display_buff(9,2,jing_du/100000%10);              
    display_buff(10,2,jing_du/10000%10);
    display_buff(11,2,jing_du/1000%10);
    display_buff(12,2,jing_du/100%10);
    display_buff(13,2,jing_du/10%10);
    display_buff(14,2,jing_du/1%10);
    if(BaseFlag==0)             display_GB2312_string(15,2," ");
    else                  display_GB2312_string(15,2,"*");
    display_GB2312_string(0,3,"纬度:");//------------------------------------------->第三行  显示纬度
    display_buff(5,3,wei_du/10000000%10);
    display_buff(6,3,wei_du/1000000%10);
    display_GB2312_string(7,3,"."); 
    display_buff(8,3,wei_du/100000%10);
    display_buff(9,3,wei_du/10000%10);
    display_buff(10,3,wei_du/1000%10);
    display_buff(11,3,wei_du/100%10);
    display_buff(12,3,wei_du/10%10);
    display_buff(13,3,wei_du/1%10);
}
//=====================================================================================================================  定时器初始化
void Time_Init()//初始化函数
{
    TMOD=0x11;    //-- 配置定时器0和定时器1
    TH0=0x4C;
    TL0=0x00;   //-- 定时器0,初值50ms
    ET0=1;      //-- 开启定时器0
    TR0=1;      //-- 开启定时器0中断
    TH1=0xDC;
    TL1=0x00;     //-- 10ms中断  
    ET1=1;       
    TR1=0;          //-- 关闭定时器1中断
      EA=1;           
}
//=====================================================================================================================  程序主函数
void main()
{
      Time_Init();    //-- 初始化
    Uart_Init();  //-- 串口初始化配置波特率
    EA=1;     //-- 开总中断 
    initial_lcd();  //-- 屏幕初始化
    Init_ADXL345(); //-- 角度初始化
    Read_data();  //-- 读取存储的经纬度数据
    Read_Phone();   //-- 读取手机号
    while(1)
    {   
        if(GSM_Send_Time==0)      SIM800_Send_Message();  
        if(Quest_flag==1)       OLED_display_Init();
        else              
        {
            OLED_display(); //---------------------->OLED 液晶显示
            Read_ADXL345(); //-- 读取角度数据 
            Xinlv_dispose();//-- 心率测量
        }
        if(GPS_Buff[0]=='$'&&GPS_Buff[1]=='G'&&GPS_Buff[2]=='P'&&GPS_Buff[3]=='G'&&GPS_Buff[4]=='L'&&GPS_Buff[5]=='L'&&GPS_Buff[18]=='N'&&GPS_Buff[32]=='E')
        {
            if(((GPS_Buff[30]-0x30)*100+(GPS_Buff[31]-0x30)*10+(GPS_Buff[32]-0x30))>=0&&((GPS_Buff[30]-0x30)*100+(GPS_Buff[31]-0x30)*10+(GPS_Buff[32]-0x30))<=180)   //经度0°——180°  纬度0°——90°
            {
                jing_du=  (((GPS_Buff[20]-0x30)*100000000)+((GPS_Buff[21]-0x30)*10000000)+((GPS_Buff[22]-0x30)*1000000))
                      +(((((GPS_Buff[23]-0x30)*10)+(GPS_Buff[24]-0x30))*100000)/6)
                      +(((((GPS_Buff[26]-0x30)*1000)+((GPS_Buff[27]-0x30)*100)+((GPS_Buff[28]-0x30)*10)+(GPS_Buff[29]-0x30))*10)/6);      
                wei_du= ((GPS_Buff[7]-0x30)*10000000+(GPS_Buff[8]-0x30)*1000000)
                      +(((((GPS_Buff[9]-0x30)*10)+(GPS_Buff[10]-0x30))*100000)/6)
                      +(((((GPS_Buff[12]-0x30)*1000)+((GPS_Buff[13]-0x30)*100)+((GPS_Buff[14]-0x30)*10)+(GPS_Buff[15]-0x30))*10)/6); 
                GPS_Flag=1;
                GPS_Time = GPS_Cnt; //-- 赋值存储  GPS接收到卫星定位
                Memory_data();    //-- 存储经纬度数据
                BaseFlag=0; //-- 取消基站定位
            }
        }
        if(Quest_flag==0 && GPS_Time==0)//-- GSM初始化完成后
        {
            if(GPS_Flag==0)//--- GPS 未接收到卫星定位   
            {
                if(GSM_Send==0 && GSM_Send_Time==0)//-- 未执行AT指令
                {
                    Uart1_Count=0;
                    Uartdat_byte("AT+CLBS=1,1\r\n"); //-- 获取经纬度
                    GSM_Send_Time=200;
                }
            }
        }
    }                         
}
//=====================================================================================================================  定时器0中断  50ms
unsigned char Time0_ms=0;     //-- 定时器计时变量
void Time_0 ()interrupt 1   //----50MS       
{
      TH0=0x4C;
      TL0=0x00; 
    Time0_ms++;
    Scan_keyscan();               //-- 50ms进行1次按键扫描
    if(GSM_Send_Time!=0)    GSM_Send_Time--;//-- AT指令间隔倒计时
    if(Beep_Flag!=0 || Beep_Num!=0)         //--蜂鸣器产生报警
    {
        if(Beep_Num!=0)   Beep_Num--;
        Beep=!Beep;
    }else Beep=1;
    if(Time0_ms%5==0)       
    {
        Read_dat=1;   // 对4取余 200ms 读取一次角度数据
        dis_Cnt=(dis_Cnt+1)%4;  
    }
    if(Time0_ms>=20)          
    {
        Time0_ms=0;
        police_ADXL345(); //-- 1s中检测角度报警
        if(Heat_Time!=0)  
        {
            Heat_Time--;
            if(Heat_Time<=5)
            {
                Heat_Time=0;
                Start_Flag=0;
            }
        }
        if(GPS_Time!=0)   GPS_Time--;
        else        GPS_Flag=0;
    }                    
}     
//=================================================================================================================   定时器1 心率计时
void Time_1 () interrupt 3
{ 
      TH1=0xDC;
      TL1=0x00;  //-- 重载10ms初值  
    Heat_ms++;  
}
//=====================================================================================================================  串口2中断 GPS定位
void Uart_2 () interrupt 8
{
    if (S2CON & S2RI)
    {
        S2CON &= ~S2RI;
        if(S2BUF=='$')      GPS_Num=0;
        GPS_Buff[GPS_Num]=S2BUF;
        GPS_Num=(GPS_Num+1)%100;
    }
}


//

image.png

目录
相关文章
|
6月前
|
机器学习/深度学习 传感器 人工智能
植保机器人在生长监测与分析以及病虫害预警与防控方面
植保机器人在生长监测与分析以及病虫害预警与防控方面
97 2
|
6月前
|
监控 安全 自动驾驶
基于python的室内老人实时摔倒智能监测系统-跌倒检测系统(康复训练检测+代码)
基于python的室内老人实时摔倒智能监测系统-跌倒检测系统(康复训练检测+代码)
|
传感器 安全 前端开发
井下空气质量检测预警系统学习
随着现代化煤矿深入开采,井下空气质量监测已成为重要的安全问题。煤矿通常有大量地瓦斯、煤尘等气体,如果空气质量不良,无疑会给矿工的健康和安全带来极大的威胁。因此,煤矿必须配备有效的井下空气质量检测预警系统,用来监测空气质量,预警可能的问题,为矿工提供更安全的工作环境。
井下空气质量检测预警系统学习
|
6月前
|
机器学习/深度学习 算法 安全
药品不良反应智能监测,不良反应(ADR)智能监测系统源码
药物不良反应智能监测系统是一套用于监测和收集药品在使用过程中发生的不良反应的系统。它基于医院临床数据中心,运用信息技术实现药品不良反应的智能监测、报告管理、知识库查询、统计分析等功能。    不良反应(ADR)智能监测系统由系统管理、规则管理、监测报告三个大的功能模块组成,方便药师维护监测规则知识库,以及监测主题库。
药品不良反应智能监测,不良反应(ADR)智能监测系统源码
|
存储 数据采集 算法
巡检机器人之仪表识别系统
巡检机器人—— 数字表计识别、指针表计识别。
247 0
巡检机器人之仪表识别系统
|
6月前
|
安全
ADR药物不良反应智能监测预警系统源码:辅助医务人员发现不良反应
ADR是英文Adverse Drug Reaction的缩写,意为药物不良反应。是指按规定剂量正常应用药品的过程中产生的有害、而非所期望的与药品应用有因果关系的反应。
64 1
|
传感器 监控 安全
井下空气质量检测预警系统,煤矿生产、事故应急检测和实时监测
井下空气质量检测预警系统,主要用于煤矿生产、事故应急检测和实时监测
井下空气质量检测预警系统,煤矿生产、事故应急检测和实时监测
|
前端开发 BI C#
手术麻醉系统源码,实现监护仪、麻醉机、血气分析仪等设备输出数据自动采集
基于C# +前端框架:Winform+后端框架:WCF +数据库:sqlserver 开发的手术室麻醉临床信息系统源码,应用于医院手术室、麻醉科室的计算机软件系统。该系统针对整个围术期,对病人进行全程跟踪与信息管理,采用计算机和通信技术,实现监护仪、麻醉机、血气分析仪等设备输出数据自动采集,如实准确地反映患者生命体征参数变化,并实现信息高度共享,根据采集结果,综合其他患者数据,自动生成手术麻醉等相关医疗文书,把麻醉医生从繁重的单据记录中解放出来,从而有更多时间为手术顺利进行保驾护航。
198 0
手术麻醉系统源码,实现监护仪、麻醉机、血气分析仪等设备输出数据自动采集
|
传感器 监控 安全
基于单片机的家庭防盗报警系统的设计与实现_kaic
摘要:本论文研究的是将AT89C52单片机芯片作为核心元器件的防盗报警系统,该系统除了具有直接报警的功能外,还额外增加了布防和红外感应的功能。和市场上的其他各类防盗报警器相比,该设计的不同之处在于它所具有的布防功能和红外检测功能。在到达指定布防时间的时候,红外检测电路与之相配合来达到防盗的目的。此外,不论何时只要有人经过,红外检测电路的热释电红外传感器都会感应到相应的人体红外信号,并将其转化为电平信号传送给单片机,从而驱动显示灯亮。这种报警器相对比较隐蔽,能够很好的掩人耳目,不至于被盗贼发现实行破坏行为。另外,增加的布防功能可以让住户有足够的开门关门时间,减小了误报率。 整体的设计运用了模块化
|
机器学习/深度学习 算法 数据可视化
项目实践 | 行人跟踪与摔倒检测报警(文末获取完整源码)
项目实践 | 行人跟踪与摔倒检测报警(文末获取完整源码)
186 0