版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
图STYLEREF1\s5.2、REF_Ref71301167\h图5.3、REF_Ref71710657\h图5.4REF_Ref71710662\h和图5.5所示。图STYLEREF1\s5.SEQ图\*ARABIC\s12系统测试过程图图STYLEREF1\s5.SEQ图\*ARABIC\s13系统记录时间图图STYLEREF1\s5.SEQ图\*ARABIC\s14蜂鸣器报警图图STYLEREF1\s5.SEQ图\*ARABIC\s15系统测试原理图本章小结本章主要进行了系统的组装与调试,为系统的设计做进一步的完善工作。结论本文介绍了一种基于单片机的家用微型单片智能电子医疗食品药盒的整体结构设计。本产品设计方案是一款多功能的人机智能帮助老年人正确用药健康护理与医疗控制解决系统,该控制系统主要能够实现的用药功能是通过监督帮助老年人正确服药并及时反馈老人相应的用药信息。通过利用stm32单片机作为主控制器芯片用无线蓝牙技术,可以经过用户手机上的app自动设定一个中老年人的手机吃药停止时间以及自动检查手机吃药停止视图中的状态,当用户设定的手机吃药停止时间达到,相应的手机药盒启动信号灯和指示灯就会开始变亮,同时手机蜂鸣器也会开始报警,然后提醒中老年人们的吃药停止时间,当用户拨动检测到位置开关,则用户可从一个手机软件应用程序上看到一个药盒已经开始打开,显示出中老人们的吃药已经结束。通过这次动手实践,我更加明白理论结合实践的重要性,在软硬件设计方面也提高了自己的动手能力,设计还有不足之处以及在设计中遇到一些困难,比如在准备设计的器械材料上,需要和同学一起合作完成,在这个过程中也明白了合作的重要性,并且自己的经验也不足,希望随着日后经验的不断积累,可以完善不足之处,努力提升自己。参考文献付莎莎.基于羌族羊崇拜的羊角纹图像语意解读与设计[J].四川戏剧,2017(08):64-67.张凌浩.产品的语意[M].北京:中国建筑工业出版社,2005.王坤茜.产品符号语意[M].长沙:湖南大学出版社,2014.李芸莉.汉字字体在包装设计中的艺术性应用研究[D].北京建筑大学,2019.唐立民,李广羽.基于单片机的模块化智能药盒的开发[J].产业与科技论坛,2011,10(22):61-62.郑人杰.计算机软件测试技术.北京:清华大学出版社,1992.胡汉才.单片机原理及系统设计.北京:清华大学出版社,2002.张俊谟.单片机中级教程原理与应用.北京航空航天大学出版社.2002.李向玉.分析单片机在电子技术中的应用和技术开发[J].电子测试,2019(Z1):41-42.童严,周元超,郭健,刘晓海,迟亚海.单片机在电子技术中的应用[J].山东工业技术,2019(05):141.王江,刘明德,苏芸,曾震.基于老人的智能药盒设计[J].南方农机,2019,50(03):170-171.刘明德,王江,曾震,苏芸.老年人居家使用的智能药盒设计[J].科技与创新,2018(24):128-130.龚鑫宇.基于RFID技术的智能药盒系统的设计与实现[D].江苏大学,2017.雷嘉明,王宇歌,龙玲.基于Cortex-A9处理器和STM32单片机的GPS智能导航手杖设计[J].科学技术创新,2019(14):85-86.李静,杨子维,李顺平,张鹏琴.基于GSM的智能防盗远程监控系统[J].计算机产品与流通,2019(05):88.附录#include"pbdata.h"u8rtc_ok=MSG_FALSE;/*****************************************************任务一*****************************************************/voidTask_1(void*p_arg){ u8minute_now; LED_Init(); //初始化与LED连接的硬件接口 Beep_Init(); Beep_ON();//打开蜂鸣器 Uart_init(USART1,9600);// Uart_init(USART2,9600); Debug(USART1,"UartisOK!",11);// Debug(USART2,"Uart2isOK!",12); while(RTC_Init()){ }//如果RTC有问题,或者没有焊接32768晶振,则程序会停在这 Debug(USART1,"RTCisOK!",10); RTC_Set(2018,9,19,14,10,30);//设置实时时钟时间 RequestTimeFromAPP();//单片机RTC初始化完成后就向app请求设置时间(运行app的手机的时间) AlarmInit();//定时器初始化 RecordInit();//记录初始化// RequestTimeFromAPP(); OSTimeDly(100); //如果没有设置时间(app没有运行),则蜂鸣器一直以0.5s的间隔鸣叫 while(rtc_ok==MSG_FALSE){ RequestTimeFromAPP(); Beep_OFF(); OSTimeDly(500); Beep_ON(); OSTimeDly(500); } IWDG_Init(4,625);//与分频数为64,重载值为625,溢出时间为1s Beep_OFF();//关闭蜂鸣器 while(1) {// printf("Task_1isruning!\r\n"); IWDG_Feed();//喂狗,如果死机则不会执行此程序,单片机会复位 if(minute_now!=calendar.min){//每分钟检查一次闹钟 minute_now=calendar.min; AlarmCheckRTC(calendar);//检查定时器并报警 }// sendCmdData(USART1,0x66,&length_record,1); OSTimeDly(500); }}/*******************************************************任务2******************************************************/voidTask_2(void*p_arg){// u8dat[LENGTH_MSG_MAX]; u8index_msg=0; u16pos=0,index_buf_read=0; while(1) {/****************************************************** 此处的代码理解起来比较费劲,要根据自定义协议的设置来解释 看此代码前请先阅读自定义协议的具体定义data_msg.h 此段代码的作用是从串口接收的数据流中截取符合自定义协议的数据并保存在缓冲区 ******************************************************/ if(index_buf_read!=USART1_index_save){//所有接收到的数据还没处理完,index_buf_read是从串口缓冲区取数据的下标,USART1_index_save是串口接收中断程序存数据的下标 //串口接收到的数据是在申请的缓冲区内循环保存的,如果取数据的下标是0(缓冲区的开头),那么它的前一个数据就是缓冲区的结尾 if((index_buf_read==0&&USART1_RX_BUF[USART_BUF_LEN-1]==START_MSG_MSB&&USART1_RX_BUF[index_buf_read]==START_MSG_LSB)||(USART1_RX_BUF[index_buf_read-1]==START_MSG_MSB&&USART1_RX_BUF[index_buf_read]==START_MSG_LSB)){ pos=1;//检测到了数据的起始 } if(pos==2){ dat_msg[index_msg].length=USART1_RX_BUF[index_buf_read];//信息主体长度 } elseif(pos==3){ dat_msg[index_msg].cmd_byte=USART1_RX_BUF[index_buf_read];//指令码 } elseif(pos>3){ if(pos<dat_msg[index_msg].length+4){ dat_msg[index_msg].payLoad[pos-4]=USART1_RX_BUF[index_buf_read];//信息主体 } else{ dat_msg[index_msg].checkSum=USART1_RX_BUF[index_buf_read];//校验码,用于验证接收到的数据是否正确 dat_msg[index_msg].enable=MSG_TRUE;//数据还没有被处理 pos=0; index_msg++;//接收到的数据下标往后移动 index_msg=index_msg%NUM_DAT_MSG;//最多保存NUM_DAT_MSG个完整数据,防止数组越界 } } if(pos){ pos++; }/****************************************************************************************** //上面的程序作用与下面这段一样,不同的是下面这段程序需要申请最大信息长度的数组用于保存数据 //起始字节和结束字节都要保存,确认数据完整后再进行转存储到信息结构体 //而上面的程序在确认起始字节后直接将数据转存到信息结构体,并且不转存起始字节和结束字节 //相比较之下,上面的程序占用空间更小,执行速度更快,另外上面的程序同样会舍弃掉不完整数据 if(index_buf_read==0&&USART1_RX_BUF[USART_BUF_LEN-1]==START_MSG_MSB&&USART1_RX_BUF[index_buf_read]==START_MSG_LSB){ pos=0;//添加这一句可以舍弃掉一个不完整的数据(某个数据只发了前面的一半) dat[pos++]=USART1_RX_BUF[USART_BUF_LEN-1];//保存信息起始字节的高字节 } //判断信息的起始两位字节,只要检测到这两个字节就认为是信息的开头 elseif(USART1_RX_BUF[index_buf_read-1]==START_MSG_MSB&&USART1_RX_BUF[index_buf_read]==START_MSG_LSB){ pos=0;//添加这一句可以舍弃掉一个不完整的数据(某个数据值发了前面的一半) dat[pos++]=USART1_RX_BUF[index_buf_read-1];//保存信息起始字节的高字节 } if(pos){//已经检测到了数据的起始字节 dat[pos++]=USART1_RX_BUF[index_buf_read];//保存数据 if(USART1_RX_BUF[index_buf_read]==END_MSG&&pos>(dat[2]+5)){//检测到了数据的结尾(数据结构/协议的定义中可以没有结束字节,仅凭数据长度检测结尾) dat_msg[index_msg].length=dat[2];//数据长度 dat_msg[index_msg].cmd_byte=dat[3];//指令码 memcpy((void*)dat_msg[index_msg].payLoad,dat+4,dat[2]);//数据主体 dat_msg[index_msg].checkSum=dat[dat[2]+4];//校验码,用于验证接收到的数据是否正确 dat_msg[index_msg].enable=MSG_TRUE;//数据还没有被处理 pos=0;//下标移动到开始(标识为还没有检测到起始字节) index_msg++;//接收到的数据下标往后移动 index_msg=index_msg%NUM_DAT_MSG;//最多保存NUM_DAT_MSG个完整数据,防止数组越界 } }*****************************************************************************************************/ index_buf_read++;//从串口接收缓冲区取数据的指针往后移动 index_buf_read=index_buf_read%USART_BUF_LEN;//申请的串口接收缓冲区大小为USART_BUF_LEN,防止数组越界 }// else{// //串口没有接收到新的数据则可以执行其他程序// //此处程序执行时间不能太长,否则串口接收到的数据可能会来不及处理就被新的数据覆盖掉// }// printf("Task_3isruning!\r\n"); OSTimeDly(1); }}/*******************************************************任务3******************************************************/voidTask_3(void*p_arg){ u8loopCount=0,index_msg=0; _data_msg_objmsgDat; //数据结构体 while(1) { if(dat_msg[index_msg].enable==MSG_TRUE){//存放完整数据的数组中有还没被处理数据 msgDat=dat_msg[index_msg];//取出数据单独存放,防止被新的数据覆盖 dat_msg[index_msg].enable=MSG_FALSE;//在存放完整数据的数组中将此数据标记为已处理,可以存放新的数据 index_msg++;//取完整数据的下标往后移动 index_msg=index_msg%NUM_DAT_MSG;//存放完整数据的数组长度为NUM_DAT_MSG,防止数组越界 if(dataIsCorrect(msgDat)){//数据接收正确 switch(msgDat.cmd_byte){ caseCMD_SET_RTC://设置时间 RTC_Set(2000+msgDat.payLoad[0],msgDat.payLoad[1],msgDat.payLoad[2],msgDat.payLoad[3],msgDat.payLoad[4],msgDat.payLoad[5]); rtc_ok=MSG_TRUE;//时间设置成功 dat_msg_send.cmd_byte=CMD_SET_RTC; dat_msg_send.payLoad[0]=MSG_TRUE;//时间设置成功 dat_msg_send.length=1;//数据长度设置为1 sendMsgData(USART1,dat_msg_send);//发送数据 break; caseCMD_APP_GET_RTC://APP查询时间 dat_msg_send.cmd_byte=CMD_APP_GET_RTC; dat_msg_send.payLoad[0]=calendar.w_year-2000; dat_msg_send.payLoad[1]=calendar.w_month; dat_msg_send.payLoad[2]=calendar.w_date; dat_msg_send.payLoad[3]=calendar.hour; dat_msg_send.payLoad[4]=calendar.min; dat_msg_send.payLoad[5]=calendar.sec; dat_msg_send.payLoad[6]=calendar.week; dat_msg_send.length=7; sendMsgData(USART1,dat_msg_send); break; caseCMD_SET_ALARM://设置闹钟 alarm[msgDat.payLoad[0]].weekday=msgDat.payLoad[1];alarm[msgDat.payLoad[0]].hour=msgDat.payLoad[2];alarm[msgDat.payLoad[0]].min=msgDat.payLoad[3];alarm[msgDat.payLoad[0]].sec=msgDat.payLoad[4];alarm[msgDat.payLoad[0]].num_box =msgDat.payLoad[5];alarm[msgDat.payLoad[0]].state=msgDat.payLoad[6]; alarm[msgDat.payLoad[0]].alive=MSG_TRUE; AlarmSaveAll(); dat_msg_send.cmd_byte=CMD_SET_ALARM; dat_msg_send.payLoad[0]=msgDat.payLoad[0]; dat_msg_send.payLoad[1]=alarm[msgDat.payLoad[0]].weekday; dat_msg_send.payLoad[2]=alarm[msgDat.payLoad[0]].hour;dat_msg_send.payLoad[3]=alarm[msgDat.payLoad[0]].min;dat_msg_send.payLoad[4]=alarm[msgDat.payLoad[0]].sec;dat_msg_send.payLoad[5]=alarm[msgDat.payLoad[0]].num_box;dat_msg_send.payLoad[6]=alarm[msgDat.payLoad[0]].state;dat_msg_send.payLoad[7]=alarm[msgDat.payLoad[0]].alive; dat_msg_send.length=8; sendMsgData(USART1,dat_msg_send); break; caseCMD_GET_ALARM://APP查询闹钟 for(loopCount=0;loopCount<NUM_ALARM;loopCount++){ if(alarm[loopCount].alive==MSG_TRUE){ dat_msg_send.cmd_byte=CMD_GET_ALARM; dat_msg_send.payLoad[0]=loopCount; dat_msg_send.payLoad[1]=alarm[loopCount].weekday; dat_msg_send.payLoad[2]=alarm[loopCount].hour; dat_msg_send.payLoad[3]=alarm[loopCount].min; dat_msg_send.payLoad[4]=alarm[loopCount].sec; dat_msg_send.payLoad[5]=alarm[loopCount].num_box; dat_msg_send.payLoad[6]=alarm[loopCount].state; dat_msg_send.payLoad[7]=alarm[loopCount].alive; dat_msg_send.length=8; sendMsgData(USART1,dat_msg_send); } } break; caseCMD_DEL_ALARM://删除闹钟 AlarmDelete(msgDat.payLoad[0]); dat_msg_send.cmd_byte=CMD_DEL_ALARM; dat_msg_send.payLoad[0]=msgDat.payLoad[0]; dat_msg_send.payLoad[1]=MSG_TRUE; dat_msg_send.length=2; sendMsgData(USART1,dat_msg_send); break; caseCMD_GET_RECODE://app查询记录 for(loopCount=0;loopCount<length_record;loopCount++){ dat_msg_send.cmd_byte=CMD_GET_RECODE; dat_msg_send.payLoad[0]=loopCount; dat_msg_send.payLoad[1]=record[loopCount].month; dat_msg_send.payLoad[2]=record[loopCount].day; dat_msg_send.payLoad[3]=record[loopCount].hour; dat_msg_send.payLoad[4]=record[loopCount].min; dat_msg_send.payLoad[5]=record[loopCount].sec; dat_msg_send.payLoad[6]=record[loopCount].num_box; dat_msg_send.length=7; sendMsgData(USART1,dat_msg_send); } break; caseCMD_DEL_RECODE://删除记录 RecordDelete(msgDat.payLoad[0]); dat_msg_send.cmd_byte=CMD_DEL_RECODE; dat_msg_send.payLoad[0]=msgDat.payLoad[0]; dat_msg_send.payLoad[1]=MSG_TRUE; dat_msg_send.length=2; sendMsgData(USART1,dat_msg_send); break; } } } RecordNow();//保存药盒打开记录,查询方式(此处足以满足要求),想要记录保存及时迅速,可以使用中断方式// printf("Task_3isruning!\r\n"); OSTimeDly(1); }}/*******************************************************任务4******************************************************/voidTask_4(void*p_arg){ while(1) {//此任务只用于保存记录到内部flash//当记录个数较多时,保存数据的时间太长//每次需要保存数据时,count_save_record加1即可 while(count_save_record){ Write_FlashData(ADDR_RECORD,(uint16_t*)&record[0].month,length_record*sizeof(_record_obj)/2);//写数据到flash count_save_record--; }// printf("Task_4isruning!\r\n"); OSTimeDly(10); }}/*******************************************************任务5蜂鸣器鸣叫任务******************************************************/voidTask_5(void*p_arg){ while(1) {// OSTaskSuspend(TASK_5_PRIO);//挂起任务5 //蜂鸣器鸣叫的程序也是必然占用很长时间,所以单独使用一个任务 while(beepCount_task){ Beep_ON(); LED_ON(beepPort_task,beepPin_task); OSTimeDly(beepOnTimeMs_task); LED_OFF(beepP
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年农经系统版村集体经济组织会计制度试题
- 2026年液压与气动技术基础题
- 2026年工作计划与总结制作技巧自测
- 2026年全县涉诈短信拦截题库
- 2026年农村电商服务站点运营与服务规范测试
- 2026年学习之翼智能试题教程
- STEM教育艺术教育融合课题申报书
- 2026年开发区主导产业招商引资优惠政策题库
- 居家锻炼身体英文演讲稿
- 演讲稿关于大学父母爱情
- 2026届东北三省三校高三第二次联合模拟考试物理试题(含答案解析)
- 2026北京海淀高三一模政治(含答案)
- 2025年《中华人民共和国疫苗管理法》知识测试试题及答案
- 初中物理八年级下册《功与机械能》单元教学设计:探究“功”的内涵、计算与意义
- 管住屏幕成就人生+高二下学期文明上网主题班会
- AI在水土流失治理植被覆盖监测与评估应用
- 初中生物八年级下册遗传与变异大概念统摄下科学思维赋能的中考专题复习教学设计
- 2026江西省信用融资担保集团股份有限公司社会招聘1人备考题库有答案详解
- 2026年青少年国防教育专题竞赛题库
- 立讯精密测评题库及答案
- 保密协议(2026年游戏行业保密)
评论
0/150
提交评论