利用51单片机完成一种智能助眠机系统的设计

控制/MCU

1883人已加入

描述

一、功能简介

本项目使用Proteus8.12仿真51单片机控制器,使用蜂鸣器闹铃模块、LCD1602显示模块、心率血氧模块、PCF8691 ADC模块、按键模块等。

主要功能:

系统运行后,LCD1602显示传感器采集的心率和血氧值以及当前时间;可通过K3键进入时间修改模式,K3用于切换时、分、秒,K1和K2键调节;时间修改完成后可按下K4键保存并返回主界面。

可通过K4键进入助眠和起床闹铃设置模式,K4用于切换助眠时/分,起床时/分,K1和K2键调节。闹铃设置好后可按下K3键保存并返回主界面。若当前时间到达助眠时间或起床闹钟时间,则开启蜂鸣器闹铃,可通过K2键取消正在闹铃。正常界面下,可通过K1键查阅监测心率和血氧的数据信息,LCD1602显示心率及血氧的最小和最大值。

主要功能如下:

(1)心率/血氧监测;

(2)助眠/起床闹钟设置;

(3)闹铃提醒;

(4)LCD1602液晶显示。

二、软件设计

//系统数据显示
void sys_data_show(void)
{
  while(1)
  {
    //未查阅
    if(sys_ctrl.find==0)
    {
      //未进入设置闹钟模式
      if(sys_ctrl.set_alarm_mode==0)
      {
        //显示时间
        lcd1602_show_nums(6,0,sys_ctrl.hour,2,0x80);
        lcd1602_show_nums(9,0,sys_ctrl.min,2,0x80);
        lcd1602_show_nums(12,0,sys_ctrl.sec,2,0x80);

        //心率显示
        lcd1602_show_nums(3,1,sys_ctrl.heart,3,0);
        //血氧显示
        lcd1602_show_nums(12,1,sys_ctrl.oxygen,3,0);

        //时间调节位置闪烁
        switch(sys_ctrl.set_time_mode)
        {
          case 1://时
            lcd1602_show_string(6,0,"  ");
            delay_ms(50);
            lcd1602_show_nums(6,0,sys_ctrl.hour,2,0x80);
            break;
          case 2://分
            lcd1602_show_string(9,0,"  ");
            delay_ms(50);
            lcd1602_show_nums(9,0,sys_ctrl.min,2,0x80);
            break;
          case 3://秒
            lcd1602_show_string(12,0,"  ");
            delay_ms(50);
            lcd1602_show_nums(12,0,sys_ctrl.sec,2,0x80);
            break;
        }  
      }
      //进入闹钟设置模式
      else
      {
        //显示助眠时间
        lcd1602_show_nums(7,0,sys_ctrl.alarm_time[0][0],2,0x80);
        lcd1602_show_nums(10,0,sys_ctrl.alarm_time[0][1],2,0x80);
        //显示起床时间
        lcd1602_show_nums(7,1,sys_ctrl.alarm_time[1][0],2,0x80);
        lcd1602_show_nums(10,1,sys_ctrl.alarm_time[1][1],2,0x80);

        //时间调节位置闪烁
        switch(sys_ctrl.set_alarm_mode)  
        {
          case 1://助眠时
            lcd1602_show_string(7,0,"  ");
            delay_ms(50);
            lcd1602_show_nums(7,0,sys_ctrl.alarm_time[0][0],2,0x80);
            break;
          case 2://助眠分
            lcd1602_show_string(10,0,"  ");
            delay_ms(50);
            lcd1602_show_nums(10,0,sys_ctrl.alarm_time[0][1],2,0x80);
            break;
          case 3://起床时
            lcd1602_show_string(7,1,"  ");
            delay_ms(50);
            lcd1602_show_nums(7,1,sys_ctrl.alarm_time[1][0],2,0x80);
            break;
          case 4://起床分
            lcd1602_show_string(10,1,"  ");
            delay_ms(50);
            lcd1602_show_nums(10,1,sys_ctrl.alarm_time[1][1],2,0x80);
            break;
        }  
      }  
    }
    //正在查阅
    else
    {
      //显示心率最小和最大值
      lcd1602_show_nums(8,0,sys_ctrl.heart_lh[0],3,0x80);
      lcd1602_show_nums(12,0,sys_ctrl.heart_lh[1],3,0x80);
      //显示血氧最小和最大值
      lcd1602_show_nums(8,1,sys_ctrl.oxygen_lh[0],3,0x80);
      lcd1602_show_nums(12,1,sys_ctrl.oxygen_lh[1],3,0x80);  
    }

    break;      
  }
}


//系统数据设置
void sys_data_set(void)
{
  u8 key=0;
  static u8 oneflag=0;


  key=key_scan(0);
  //设置时间
  if(key==KEY3_PRESS)
  {
    //未进入设置闹钟模式
    if(sys_ctrl.set_alarm_mode==0)
    {
      TR1=0;//关闭定时器
      sys_ctrl.set_time_mode++;
      if(sys_ctrl.set_time_mode >=4)sys_ctrl.set_time_mode=1;  
    }
    //闹钟设置模式,确定
    else
    {
      oneflag=0;
      sys_ctrl.set_alarm_mode=0;
      sys_open_show();//开机界面显示
      TR1=1;//开启定时器  
    }    
  }
  //加
  else if(key==KEY1_PRESS)
  {
    //时间设置模式
    switch(sys_ctrl.set_time_mode)
    {
      case 1://时
        sys_ctrl.hour++;
        if(sys_ctrl.hour >23)sys_ctrl.hour=0;
        break;
      case 2://分
        sys_ctrl.min++;
        if(sys_ctrl.min >59)sys_ctrl.min=0;
        break;
      case 3://秒
        sys_ctrl.sec++;
        if(sys_ctrl.sec >59)sys_ctrl.sec=0;
        break;
    }  
    //闹钟设置模式
    switch(sys_ctrl.set_alarm_mode)
    {
      case 1://助眠时
        sys_ctrl.alarm_time[0][0]++;
        if(sys_ctrl.alarm_time[0][0] >23)sys_ctrl.alarm_time[0][0]=0;
        break;
      case 2://助眠分
        sys_ctrl.alarm_time[0][1]++;
        if(sys_ctrl.alarm_time[0][1] >59)sys_ctrl.alarm_time[0][1]=0;
        break;
      case 3://起床时
        sys_ctrl.alarm_time[1][0]++;
        if(sys_ctrl.alarm_time[1][0] >23)sys_ctrl.alarm_time[1][0]=0;
        break;
      case 4://起床分
        sys_ctrl.alarm_time[1][1]++;
        if(sys_ctrl.alarm_time[1][1] >59)sys_ctrl.alarm_time[1][1]=0;
        break;    
    }
    //正常模式下,查阅血氧心率信息
    if(sys_ctrl.set_time_mode==0 && sys_ctrl.set_alarm_mode==0)
    {
      sys_ctrl.find=!sys_ctrl.find;
      //查阅
      if(sys_ctrl.find==1)
      {
        lcd1602_clear();
        lcd1602_show_string(0,0," Heart- >000-000");
        lcd1602_show_string(0,1,"Oxygen- >000-000");    
      }
      //退出查阅
      else
      {
        sys_open_show();//开机界面显示  
      }  
    }  
  }
  //减
  else if(key==KEY2_PRESS)
  {
    //时间设置模式
    switch(sys_ctrl.set_time_mode)
    {
      case 1://时
        sys_ctrl.hour--;
        if(sys_ctrl.hour< 0)sys_ctrl.hour=23;
        break;
      case 2://分
        sys_ctrl.min--;
        if(sys_ctrl.min< 0)sys_ctrl.min=59;
        break;
      case 3://秒
        sys_ctrl.sec--;
        if(sys_ctrl.sec< 0)sys_ctrl.sec=59;
        break;
    }
    //闹钟设置模式
    switch(sys_ctrl.set_alarm_mode)
    {
      case 1://助眠时
        sys_ctrl.alarm_time[0][0]--;
        if(sys_ctrl.alarm_time[0][0]< 0)sys_ctrl.alarm_time[0][0]=23;
        break;
      case 2://助眠分
        sys_ctrl.alarm_time[0][1]--;
        if(sys_ctrl.alarm_time[0][1]< 0)sys_ctrl.alarm_time[0][1]=59;
        break;
      case 3://起床时
        sys_ctrl.alarm_time[1][0]--;
        if(sys_ctrl.alarm_time[1][0]< 0)sys_ctrl.alarm_time[1][0]=23;
        break;
      case 4://起床分
        sys_ctrl.alarm_time[1][1]--;
        if(sys_ctrl.alarm_time[1][1]< 0)sys_ctrl.alarm_time[1][1]=59;
        break;    
    }
    sys_ctrl.alarm_flag=0;//解除闹铃      
  }
  //确定
  else if(key==KEY4_PRESS)
  {
    //时间设置模式
    if(sys_ctrl.set_time_mode!=0)
    {
      sys_ctrl.set_time_mode=0;
      TR1=1;//开启定时器  
    }
    //闹钟设置模式
    else
    {
      TR1=0;//关闭定时器
      if(oneflag==0)//只显示1次界面
      {
        oneflag=1;
        lcd1602_clear();
        lcd1602_show_string(0,0,"Sleep- >00:00");
        lcd1602_show_string(0,1,"Alarm- >00:00");  
      }
      sys_ctrl.set_alarm_mode++;
      if(sys_ctrl.set_alarm_mode >=5)sys_ctrl.set_alarm_mode=1;  
    }  
  }
}


//应用控制系统
void appdemo_show(void)
{
  u8 i=5;
  sys_parm_init();//系统参数初始化
  lcd1602_init();
  time1_init();
  while(i--)
  {
    //血氧心率获取
    sys_ctrl.heart=pcf8591_read_adcvalue(1);
    sys_ctrl.heart=cal_map(sys_ctrl.heart,0,255,0,200);
    sys_ctrl.heart_lh[0]=sys_ctrl.heart;//初始值作为最小值
    sys_ctrl.heart_lh[1]=sys_ctrl.heart;//初始值作为最大值


    sys_ctrl.oxygen=pcf8591_read_adcvalue(0);
    sys_ctrl.oxygen=cal_map(sys_ctrl.oxygen,0,255,0,200);
    sys_ctrl.oxygen_lh[0]=sys_ctrl.oxygen;//初始值作为最小值
    sys_ctrl.oxygen_lh[1]=sys_ctrl.oxygen;//初始值作为最大值


    delay_ms(100);
  }
  sys_open_show();//系统开机界面显示
  TR1=1;//开启定时器


  while(1)
  {  
    sys_data_get();//系统数据获取
    sys_data_show();//系统数据显示
    sys_data_set();//系统数据设置
    sys_fun_ctrl();//系统功能控制
  }
}


//定时器1中断函数
void time1(void) interrupt 3 
{
  static u8 i=0;


  TH1=0XDC;  //给定时器赋初值,定时10ms
  TL1=0X00;
  i++;
  if(i >=100)//1秒到
  {
    i=0;
    sys_ctrl.sec++;
    if(sys_ctrl.sec >=60)//1分
    {
      sys_ctrl.sec=0;
      sys_ctrl.min++;
      if(sys_ctrl.min >=60)//1小时
      {
        sys_ctrl.min=0;
        sys_ctrl.hour++;
        if(sys_ctrl.hour >=24)sys_ctrl.hour=0;
      }
    }
  }
}

三、实验现象

LCD1602

LCD1602

LCD1602

LCD1602

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分