文章目录
- 一、功能简介
- 二、软件设计
- 三、实验现象
- 联系作者
一、功能简介
本项目使用Proteus8仿真STM32单片机控制器,使用OLED显示模块、红外传感器、蜂鸣器、DS18B20温度传感器,风扇LED、语音识别模块等。
主要功能:
系统运行后,OLED显示动画效果,一段时间后静止。当到达指定时间时开启闹钟,系统需感应到有人后,此时可通过K4键或语音关闭闹铃。系统感应到有人后,OLED显示测量的人体体温、时间、LED和风扇的开关状态;此时可通过语音开关LED和风扇;可通过按键K3进入闹钟设置界面,通过K3键切换不同时间位置,K1和K2键加减调节,设置后按下K4键保存并退出,返回测温和时钟显示界面。
语音识别指令(十六进制数):
开灯–>0X01
关灯–>0X02
开风扇–>0X11
关风扇–>0X12
关闹铃–>0X22
二、软件设计
/*
作者:嗨小易(QQ:3443792007)*///系统数据获取
void sys_data_get(void)
{static u8 i=0;static u8 oneflag=1;while(1){ //人体红外检测if(IRED==0){//温度获取i++;if(i%1==0){TIM_Cmd(TIM2,DISABLE); //关闭定时器sys_ctrl.temp=DS18B20_GetTemperture()*10;TIM_Cmd(TIM2,ENABLE); //打开定时器}sys_ctrl.man=1;}else sys_ctrl.man=0;//界面状态显示if(sys_ctrl.man==0){sys_ctrl.window=0;if(oneflag==0){oneflag=1;sys_open_show();//系统开机界面显示 } }else {sys_ctrl.window=1;if(oneflag==1){oneflag=0;sys_parm_show();//系统数据参数显示界面 } } break;}
}//系统数据显示
void sys_data_show(void)
{u8 buf[9];while(1){ //显示数据界面if(sys_ctrl.window==1){ //正常模式下if(sys_ctrl.mode==0){//温度显示buf[0]=sys_ctrl.temp/100+0x30;buf[1]=sys_ctrl.temp%100/10+0x30;buf[2]='.';buf[3]=sys_ctrl.temp%100%10+0x30;buf[4]='C';buf[5]='\0';OLED_ShowString(3*16,0,buf,16); //时间显示buf[0]=sys_ctrl.hour/10+0x30;buf[1]=sys_ctrl.hour%10+0x30;buf[2]=':';buf[3]=sys_ctrl.min/10+0x30;buf[4]=sys_ctrl.min%10+0x30;buf[5]=':';buf[6]=sys_ctrl.sec/10+0x30;buf[7]=sys_ctrl.sec%10+0x30;buf[8]='\0';OLED_ShowString(3*16,2,buf,16);//灯状态显示if(sys_ctrl.led==1)OLED_ShowString(2*16,4,"ON ",16);else OLED_ShowString(2*16,4,"OFF",16);//风扇状态显示if(sys_ctrl.motor==1)OLED_ShowString(6*16+8*1,4,"ON ",16);else OLED_ShowString(6*16+8*1,4,"OFF",16);}//时间设置模式下else{//吃药时间显示buf[0]=sys_ctrl.stime[0][0]/10+0x30;buf[1]=sys_ctrl.stime[0][0]%10+0x30;buf[2]=':';buf[3]=sys_ctrl.stime[0][1]/10+0x30;buf[4]=sys_ctrl.stime[0][1]%10+0x30;buf[5]=':';buf[6]=sys_ctrl.stime[0][2]/10+0x30;buf[7]=sys_ctrl.stime[0][2]%10+0x30;buf[8]='\0';OLED_ShowString(3*16,0,buf,16);//运动时间显示buf[0]=sys_ctrl.stime[1][0]/10+0x30;buf[1]=sys_ctrl.stime[1][0]%10+0x30;buf[2]=':';buf[3]=sys_ctrl.stime[1][1]/10+0x30;buf[4]=sys_ctrl.stime[1][1]%10+0x30;buf[5]=':';buf[6]=sys_ctrl.stime[1][2]/10+0x30;buf[7]=sys_ctrl.stime[1][2]%10+0x30;buf[8]='\0';OLED_ShowString(3*16,3,buf,16);//休息时间显示buf[0]=sys_ctrl.stime[2][0]/10+0x30;buf[1]=sys_ctrl.stime[2][0]%10+0x30;buf[2]=':';buf[3]=sys_ctrl.stime[2][1]/10+0x30;buf[4]=sys_ctrl.stime[2][1]%10+0x30;buf[5]=':';buf[6]=sys_ctrl.stime[2][2]/10+0x30;buf[7]=sys_ctrl.stime[2][2]%10+0x30;buf[8]='\0';OLED_ShowString(3*16,6,buf,16);switch(sys_ctrl.mode){case 1://吃药-时OLED_ShowString(3*16,0," ",16);delay_ms(50);buf[0]=sys_ctrl.stime[0][0]/10+0x30;buf[1]=sys_ctrl.stime[0][0]%10+0x30;buf[2]='\0';OLED_ShowString(3*16,0,buf,16);break;case 2://吃药-分OLED_ShowString(3*16+3*8,0," ",16);delay_ms(50);buf[0]=sys_ctrl.stime[0][1]/10+0x30;buf[1]=sys_ctrl.stime[0][1]%10+0x30;buf[2]='\0';OLED_ShowString(3*16+3*8,0,buf,16);break;case 3://吃药-秒OLED_ShowString(3*16+6*8,0," ",16);delay_ms(50);buf[0]=sys_ctrl.stime[0][2]/10+0x30;buf[1]=sys_ctrl.stime[0][2]%10+0x30;buf[2]='\0';OLED_ShowString(3*16+6*8,0,buf,16);break;case 4://运动-时OLED_ShowString(3*16,3," ",16);delay_ms(50);buf[0]=sys_ctrl.stime[1][0]/10+0x30;buf[1]=sys_ctrl.stime[1][0]%10+0x30;buf[2]='\0';OLED_ShowString(3*16,3,buf,16);break;case 5://运动-分OLED_ShowString(3*16+3*8,3," ",16);delay_ms(50);buf[0]=sys_ctrl.stime[1][1]/10+0x30;buf[1]=sys_ctrl.stime[1][1]%10+0x30;buf[2]='\0';OLED_ShowString(3*16+3*8,3,buf,16);break;case 6://运动-秒OLED_ShowString(3*16+6*8,3," ",16);delay_ms(50);buf[0]=sys_ctrl.stime[1][2]/10+0x30;buf[1]=sys_ctrl.stime[1][2]%10+0x30;buf[2]='\0';OLED_ShowString(3*16+6*8,3,buf,16);break;case 7://休息-时OLED_ShowString(3*16,6," ",16);delay_ms(50);buf[0]=sys_ctrl.stime[2][0]/10+0x30;buf[1]=sys_ctrl.stime[2][0]%10+0x30;buf[2]='\0';OLED_ShowString(3*16,6,buf,16);break;case 8://休息-分OLED_ShowString(3*16+3*8,6," ",16);delay_ms(50);buf[0]=sys_ctrl.stime[2][1]/10+0x30;buf[1]=sys_ctrl.stime[2][1]%10+0x30;buf[2]='\0';OLED_ShowString(3*16+3*8,6,buf,16);break;case 9://休息-秒OLED_ShowString(3*16+6*8,6," ",16);delay_ms(50);buf[0]=sys_ctrl.stime[2][2]/10+0x30;buf[1]=sys_ctrl.stime[2][2]%10+0x30;buf[2]='\0';OLED_ShowString(3*16+6*8,6,buf,16);break;}} }break; }
}//系统数据设置
void sys_data_set(void)
{u8 key=0;static u8 oneflag=0;//有人的时候if(sys_ctrl.window==1){key=KEY_Scan(1);//语音识别if(USART1_RX_BUF[0]==LED_ON_CMD)//开灯{USART1_RX_BUF[0]=0;LED=0;sys_ctrl.led=1; }else if(USART1_RX_BUF[0]==LED_OFF_CMD)//关灯{USART1_RX_BUF[0]=0;LED=1;sys_ctrl.led=0; }else if(USART1_RX_BUF[0]==MOTOR_ON_CMD)//开风扇{USART1_RX_BUF[0]=0;MOTOR=0;sys_ctrl.motor=1; }else if(USART1_RX_BUF[0]==MOTOR_OFF_CMD)//关风扇{USART1_RX_BUF[0]=0;MOTOR=1;sys_ctrl.motor=0;}else if(USART1_RX_BUF[0]==ALARM_OFF_CMD)//关闹铃{USART1_RX_BUF[0]=0;sys_ctrl.alarm=0;OLED_ShowString(0,6," ",16);} } //模式设置if(key==KEY3_PRESS){sys_ctrl.mode++;if(sys_ctrl.mode>9)sys_ctrl.mode=1; if(oneflag==0)//时间设置界面仅显示1次{oneflag=1;sys_time_set_show();//系统时间设置界面显示 }}//在设置模式下,加else if(key==KEY1_PRESS){switch(sys_ctrl.mode){case 1://吃药-时sys_ctrl.stime[0][0]++;if(sys_ctrl.stime[0][0]>23)sys_ctrl.stime[0][0]=0; break;case 2://吃药-分sys_ctrl.stime[0][1]++;if(sys_ctrl.stime[0][1]>59)sys_ctrl.stime[0][1]=0; break;case 3://吃药-秒sys_ctrl.stime[0][2]++;if(sys_ctrl.stime[0][2]>59)sys_ctrl.stime[0][2]=0; break;case 4://运动-时sys_ctrl.stime[1][0]++;if(sys_ctrl.stime[1][0]>24)sys_ctrl.stime[1][0]=0; break;case 5://运动-分sys_ctrl.stime[1][1]++;if(sys_ctrl.stime[1][1]>59)sys_ctrl.stime[1][1]=0; break;case 6://运动-秒sys_ctrl.stime[1][2]++;if(sys_ctrl.stime[1][2]>59)sys_ctrl.stime[1][2]=0; break;case 7://休息-时sys_ctrl.stime[2][0]++;if(sys_ctrl.stime[2][0]>24)sys_ctrl.stime[2][0]=0; break;case 8://休息-分sys_ctrl.stime[2][1]++;if(sys_ctrl.stime[2][1]>59)sys_ctrl.stime[2][1]=0; break;case 9://休息-秒sys_ctrl.stime[2][2]++;if(sys_ctrl.stime[2][2]>59)sys_ctrl.stime[2][2]=0; break; } }//在设置模式下,减else if(key==KEY2_PRESS){switch(sys_ctrl.mode){case 1://吃药-时sys_ctrl.stime[0][0]--;if(sys_ctrl.stime[0][0]<0)sys_ctrl.stime[0][0]=23; break;case 2://吃药-分sys_ctrl.stime[0][1]--;if(sys_ctrl.stime[0][1]<0)sys_ctrl.stime[0][1]=59; break;case 3://吃药-秒sys_ctrl.stime[0][2]--;if(sys_ctrl.stime[0][2]<0)sys_ctrl.stime[0][2]=59; break;case 4://运动-时sys_ctrl.stime[1][0]--;if(sys_ctrl.stime[1][0]<0)sys_ctrl.stime[1][0]=23; break;case 5://运动-分sys_ctrl.stime[1][1]--;if(sys_ctrl.stime[1][1]<0)sys_ctrl.stime[1][1]=59; break;case 6://运动-秒sys_ctrl.stime[1][2]--;if(sys_ctrl.stime[1][2]<0)sys_ctrl.stime[1][2]=59; break;case 7://休息-时sys_ctrl.stime[2][0]--;if(sys_ctrl.stime[2][0]<0)sys_ctrl.stime[2][0]=23; break;case 8://休息-分sys_ctrl.stime[2][1]--;if(sys_ctrl.stime[2][1]<0)sys_ctrl.stime[2][1]=59; break;case 9://休息-秒sys_ctrl.stime[2][2]--;if(sys_ctrl.stime[2][2]<0)sys_ctrl.stime[2][2]=59; break; } }//确定else if(key==KEY4_PRESS){ if(oneflag==1){sys_ctrl.mode=0;oneflag=0;sys_parm_show();//系统数据参数显示界面 }//闹铃if(sys_ctrl.alarm==1){sys_ctrl.alarm=0;OLED_ShowString(0,6," ",16); } }
}//应用控制系统
void appdemo_show(void)
{u8 i=10;KEY_Init();ctrl_pin_init();BEEP_Init();DS18B20_Init();//等待温度数据稳定while(i--){sys_ctrl.temp=DS18B20_GetTemperture()*10;delay_ms(100); }OLED_Init();USART1_Init(9600);printf("USART1_Init OK\r\n");TIM2_Init(400-1,70);//定时10mssys_parm_init();//系统参数初始化sys_open_show();//系统初始界面显示TIM_Cmd(TIM2,ENABLE); //打开定时器while(1){sys_data_get();//系统数据获取sys_data_show();//系统数据显示sys_data_set();//系统数据设置sys_fun_ctrl();//系统功能控制 }
}
三、实验现象
B站演示视频:https://space.bilibili.com/444388619
联系作者
视频地址:https://space.bilibili.com/444388619/video
专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。