1. 前言

近年来,随着电子产品的发展,数字日程表这项应用在人们工作和生活中起到越来越重要的作用。时间对人们来说总是那么宝贵,工作的忙碌性和繁杂性容易使人忘记当前的时间,忘记了要做的事情,当事情不是很重要的时候,这种遗忘无伤大雅。但是,遇上重要事务,一时的耽误可能酿成大祸。

因此从人们的日常生活到公司办公,从台式电脑到便携式智能手机,都要求标配上日程表的作用。人们要求随时随地都能快速准确的提醒当前事务,并且要求日程表能够更直观、更可靠、更便宜。这种要求催生了新型日程表的产生。除此之外,由于对社会责任的更多承担,人们要求所设计的产品能够产生尽量少的垃圾、能够消耗尽量少的能量。因此人们对日程表的又有了体积小、功耗低的要求。

2. 功能需求

2.1 硬件部分

整个项目在正点原子stm32f103mini开发板环境下进行。开发板主控是stm32f103rct6。

项目模块由一些部分组成:

(1)2.8寸tft触摸屏负责显示和进行交互;

(2)pcf8563t用作时钟计时,并把日期和时间显示在屏幕上。

(3)时间采用24小时制显示,上位机要支持设备端RTC日期及时间信息更新.

(4)DHT11温湿度传感器检测环境信息,并把信息显示在液晶屏幕上;

(5)使用esp8266作WiFi模块与手机app进行通信;

(6)单片机将接收到的内容存储在w25Q64内,同时可以在屏幕上指定位置将内容显示出来。内容包括具体日程的文字内容以及日程开始、结束的时间;

(7)使用蜂鸣器以及通过syn6288语音芯片合成的语音信息,通过喇叭播报实现提醒功能。在日程开始、结束前五分钟提前(这个提前提醒的时间要可以修改)通过蜂鸣器以及喇叭发出语音提示。

(8)显示屏(横屏显示)上应包含:
基础的日期、时间、温湿度信息显示,屏幕主体部分通过列表的方式显示从手机app端接收到的日程内容;屏幕上设置一个触屏按钮,按下该按钮是可以跳当前进行中的,或者还未开始的下一项即将开始的日程。

日程显示部分:因为2.8寸显示屏的空间有限,所以同屏范围内只显示一到两个日程的具体内容。需要显示出日程的文字内容,开始和结束的时间。当日程时间即将开始以及即将结束时触发语音提示;日程结束之后要从当前显示位置上清除,同时删除w25Q64上存储的信息。同时显示下一个待开始的日程。

显示的文本部分要求能够支持显示16和24大小的,包括中文字符在内的所有字符(无法兼容就做成24大小即可)。从手机端发送的中文文本信息在在屏幕上显示的同时要存储在w25q64内。并且单片机终端上要支持存储最少十五条日程内容。单片机要能识别具体日程的时间信息,根据时间排序,同时判断日程是否过时,过时的日程直接删除,删除和跳过日程不需要触发提示。

(9)语音提示内容:
1:您有待开始的日程,请注意时间。(如果可以实现将手机端输入的日程内容(主要是汉字)读出来,那么此句改为:下一项日程:XXX即将开始,请注意时间。(XXX内即为日程内容))

2:当前日程即将结束

3:连接成功(成功连上app时播报)

4:连接失败

5:日程已设置(单片机接收到手机上发送的日程内容。)

(10)每句提示播报前蜂鸣器响一声,响完后停顿一秒再播报。

2.2 软件部分

软件部分主要就是手机上的控制app,手机的app包括可以选择添加日程的按钮,可以输入信息的文本框,可以将文本框内的内容发送到单片机的按钮。同时要可以在app上查看单片机终端的已录入的日程内容,以及加入一个可以删除已录入内容的按钮。文本框分为三部分,一部分输入文本内容(两到八个汉字字符左右的长度即可。)输入开始时间的文本框,输入结束时间的文本框。

2.3 功能总结

(1)STM32采用正点原子mini板。正点原子的2.8寸tft触摸屏

(2)pcf8563t用作时钟计时,并把日期和时间显示在屏幕上

(3)DHT11温湿度传感器检测环境信息,并把信息显示在液晶屏幕上

(4)使用esp8266作WiFi模块与手机app进行通信;

(5)w25Q64 烧录字库,存放字库,存放日程提醒信息
实现思路: 将W25Q64安装FATFS文件系统,方便数据存放读取,读写日程信息,字库信息。

(6)syn6288语音芯片合成的语音信息,通过喇叭播报实现提醒功能

(7)开发手机APP输入提醒日程,单片机接收到手机上发送的日程内容。
单片机将接收到的内容存储在w25Q64内,同时可以在屏幕上指定位置将内容显示出来。内容包括具体日程的文字内容以及日程开始、结束的时间;日程信息采用文件形式存储,修改、读写都针对文件进行操作。

3. 软件运行效果

软件打开之后先输入设备端的IP地址和端口,连接成功之后就可以进行功能操作。

软件上有日程表查看页面(也就是主页面)、日志页面、新增日程提醒页面。

软件分为windows桌面版本和Android手机版本,下面演示的截图以windows桌面版本为例。

软件采用QT设计,Qt Creator是跨平台的 Qt IDE, Qt Creator 是 Qt 被 Nokia 收购后推出的一款新的轻量级集成开发环境(IDE)。此 IDE 能够跨平台运行,支持的系统包括 Linux(32 位及 64 位)、Mac OS X 以及 Windows。

Qt Creator官网下载地址:Download Qt | Embedded System | Real Time Embedded Systems | Qt

QT所有版本下载地址:Index of /archive/qt

QT环境搭建,入门开发专栏: https://blog.csdn.net/xiaolong1126626497/category_11400392.html

1)日程表查看页面(也就是主页面),查看日程提醒事件,点击更新日程按钮,可以从设备端获取最新的数据过来。

(2)日志页面用来查看软件与设备间交互的过程,可以调试了解发送的数据是否正常。

(3)新增日程提醒页面

在这个页面上可以填入提醒的事件内容,输入提醒的起始时间、结束时间,提前提醒的时,输入完毕后,点击新增提醒事件按钮,就可以将数据发送给设备端,并且在主页面添加数据显示。

(4)Android手机运行效果

4. 通信协议

设备端与软件上位机之间数据交互的的协议:

1)
软件上位机对STM32发送:
#update          让STM32发送当前存储的所有日程数据过来STM32向上位机返回的数据格式:
$update,起始时间,结束时间,事件内容,提前提醒时间(0~59分钟)
$update,2022/02/22 13:15,2022/02/23 12:17,吃饭,52)
给STM32发送一条日程数据过去
格式:$add,起始时间,结束时间,事件内容,提前提醒时间(0~59分钟)
$add,2022/02/22 13:15,2022/02/23 12:17,吃饭,53)
给STM32发送校准时间  *202202221313384)
删除STM32上存储的日程数据
$del,起始时间,结束时间,事件内容,提前提醒时间(0~59分钟)
$del,2022/02/22 13:15,2022/02/23 12:17,吃饭,5

5. 测试流程总结

设备端采用ESP8266与上位机进行通信,ESP8266上电初始化为AP+TCP服务器模式,设置固定端口号。

采用电脑或者手机运行APP测试之前,先搜索ESP8266创建的WIFI热点连接上,然后打开软件,在软件里输入ESP8266服务器的IP地址和端口号点击连接,连接成功之后就可以与设备端进行交互。

如果没有设备端,也可以采用网络调试助手与上位机之前交互,测试功能。

6. 硬件部分

6.1 硬件实物

板子的串口正常提示:

(1)上电提示

(2) 更新事件提示

(3)SD卡上生成的文件

6.2 外设硬件连线

(1) ESP8266 WIFI
PB10--->ESP8266-RX
PB11--->ESP8266-TX
3.3v--->VCC
GND---->GND(2) SYN6628
PA2(TX)---SYN6628-RX
PA3(RX)---SYN6628-TX
3.3v---->VCC
GND----->GND(3) DHT11 温湿度传感器
PA5 ---->DHT11-OUT
3.3v---->VCC
GND----->GND剩下的用的硬件是开发板本身自带--正点原子STM32F1战舰V3开发板,硬件连接详情看原理图接口。

6.3 字库创建

6.4 SD卡上存放的字库文件

7. 设备端核心代码及实现思路

如果需要整个工程直接使用,可以去这里获取: https://download.csdn.net/download/xiaolong1126626497/85892788

7.1 字库读取

目前设备端LCD屏字库存放在SD卡上,通过fatfs文件系统读取字模进行显示,这样做的优点: 更换字库方便,直接把SD卡拔出来放在电脑上拷贝字库即可。

核心代码如下:

void NT35310_DisplayGBKData(u32 x,u32 y,u32 size,u8 *p,u16 c1,u16 c2)
{FIL fp;UINT br;u8 L,H;u32 Addr;u16 font_size=size/8*size; //字体占用的点阵码字节大小u8 *buff=NULL;H=*p;L=*(p+1);if(L<0x7f)L=L-0x40;else L=L-0x41;H=H-0x81;Addr=(190*H+L)*font_size; //中文在字库里的偏移量buff=malloc(font_size);   //使用的堆空间if(buff==NULL)return;switch(size){case 16:if(f_open(&fp,"0:SYSTEM/FONT/GBK16-H.DZK",FA_READ)!=FR_OK){printf("f_open error.\r\n");}f_lseek(&fp,Addr);f_read(&fp,buff,font_size,&br);f_close(&fp);break;case 24:f_open(&fp,"0:SYSTEM/FONT/GBK24-H.DZK",FA_READ);f_lseek(&fp,Addr);f_read(&fp,buff,font_size,&br);f_close(&fp);break;case 32:break;}//显示中文NT35310_DisplayData(x,y,size,size,buff,c1,c2);//释放空间free(buff);
}
void NT35310_DisplayData(u32 x,u32 y,u32 w,u32 h,u8 *p,u16 c1,u16 c2)
{u16 i,j,x0=x;u8 data;u16 colortemp=POINT_COLOR;    for(i=0;i<w/8*h;i++) //取出的模型总字节数{data=p[i]; //取出数组里一个字节的数据for(j=0;j<8;j++){if(data&0x80)Draw_Point(x0,y,c1); //字体颜色else {Draw_Point(x0,y,c2); //背景颜色}data<<=1; //继续判断下一位x0++; //继续画下一个点}if(x0-x==w) //判断是否需要换行{x0=x;//横坐标归位y++; //纵坐标自增}}POINT_COLOR=colortemp;
}

7.2 解析ESP8266数据

主函数里通过轮询方式检测,ESP8266是否收到上位机的命令,收到之后进行解析处理

核心代码如下:

//ESP8266 WIFI 返回的数据
if(USART3_RX_FLAG)
{USART3_RX_BUFFER[USART3_RX_CNT]='\0';printf("%s",USART3_RX_BUFFER);//解析WIFI返回的数据//如果是校准RTC时间 +IPD,0,15:*20220304220552if(strstr((char*)USART3_RX_BUFFER,":*")){printf("校准时间.\r\n");rtc_time_update((char*)USART3_RX_BUFFER);}//如果是请求更新提醒else if(strstr((char*)USART3_RX_BUFFER,"#update")){printf("请求更新事件.\r\n");update_enev();}//如果是新增提醒//+IPD,0,49:$add,2022/03/04 21:56,2022/03/04 21:56,else if(strstr((char*)USART3_RX_BUFFER,"$add")){printf("新增提醒事件.\r\n");add_enev((char*)USART3_RX_BUFFER);}//如果是删除某个提醒//+IPD,0,49:$del,2022/03/04 21:56,2022/03/04 21:56,水水水水,0else if(strstr((char*)USART3_RX_BUFFER,"$del")){printf("删除某个提醒.\r\n");del_enev((char*)USART3_RX_BUFFER);}USART3_RX_CNT=0;USART3_RX_FLAG=0;
}

7.3 向SD卡存放事件信息

事件提醒都是存放在SD卡上,以文件的形式存放,上面封装的几个函数里,主要是就是读写文件。

核心代码:

/*
函数功能:从buf里面得到第cnt个逗号所在的位置
返 回 值:0~254,代表逗号所在位置的偏移.
255,代表不存在第cnt个逗号
*/
u8 GetCommaOffset(char *buf,u8 cnt)
{char *p=buf;while(cnt){if(*buf==',')cnt--;buf++;}return buf-p; //计算偏移量
}/*
写文件
*/
void FATFS_Write(const TCHAR *FileName,const char *WriteBuff)
{FIL fp;FRESULT res;UINT cnt; //存放写入成功的数量/*1. 创建文件*/  res=f_open(&fp,FileName, FA_WRITE | FA_CREATE_ALWAYS);if(res!=0){printf("%s文件创建失败!\n",FileName);return;}/*2. 写入数据*/res=f_write(&fp,WriteBuff,strlen(WriteBuff),&cnt);if(res!=0){printf("%s文件写入失败!\n",FileName);return;}/*3. 关闭文件*/f_close(&fp);printf("%s文件创建成功,成功写入:%d\n",FileName,cnt);
}//提取指定逗号位置的数据
void GetCommaOffsetBuff(char *buf_in,char *buf_out,u8 cnt)
{while (cnt){if (*buf_in == ',')cnt--;if (*buf_in == '\0')break;buf_in++;}while (*buf_in != ',' && *buf_in != '\0'){*buf_out=*buf_in;buf_in++;buf_out++;}*buf_out = '\0';
}//字符串替换
//sub1替换前 sub2替换后字符
void StringSubstitution(char *p,char sub1,char sub2)
{while (*p!='\0'){if (*p == sub1){*p = sub2;}p++;}
}//新增提醒//+IPD,0,49:$add,2022/03/04 21:56,2022/03/04 21:56,
void add_enev(char *p)
{char buf_out[20];u8 offset = 0;char *p2;offset = GetCommaOffset(p, 3);p2 = p + offset;printf("%d,%s\r\n", offset, p2);//提取提醒的起始时间 例如:2022/03/04 21:56GetCommaOffsetBuff(p,buf_out,3);printf("buf_out1=%s\r\n",buf_out);StringSubstitution(buf_out,'/','-');StringSubstitution(buf_out, ' ','-');StringSubstitution(buf_out, ':','-');printf("buf_out2=%s\r\n", buf_out);strcat(buf_out,".ev");printf("buf_out3=%s\r\n", buf_out);FATFS_Write(buf_out, p2);//更新事件列表update_event_list();
}//删除某个提醒//+IPD,0,49:$del,2022/03/04 21:56,2022/03/04 21:56,水水水水,0
void del_enev(char *p)
{char buf_out[20];char dir_file_path[50];//提取提醒的起始时间 例如:2022/03/04 21:56GetCommaOffsetBuff(p, buf_out, 3);printf("buf_out1=%s\n", buf_out);StringSubstitution(buf_out, '/', '-');StringSubstitution(buf_out, ' ', '-');StringSubstitution(buf_out, ':', '-');printf("buf_out2=%s\n", buf_out);strcat(buf_out, ".ev");printf("buf_out3=%s\n", buf_out);//拼接目录名称sprintf(dir_file_path,"0:/%s",buf_out);//删除文件if(f_unlink(dir_file_path)==FR_OK){printf("%s\r\n删除成功.",dir_file_path);}else{printf("%s\r\n删除失败.",dir_file_path);}    //更新事件列表update_event_list();
}//向APP终端更新提醒
//+IPD,0,7:#update
/*
STM32向上位机返回的数据格式:
$update,起始时间,结束时间,事件内容,提前提醒时间(0~59分钟)
$update,2022/02/22 13:15,2022/02/23 12:17,吃饭,5
*/
u8 update_enev(void)
{
//    u8 buff[]="$update,2022/02/22 13:15,2022/02/23 12:17,吃饭,5";
//    ESP8266_ServerSendData(0,buff,strlen((char*)buff));char *path="0:/"; //目录位置DIR dir;FIL file; //文件指针FRESULT res; FILINFO fno; //存放读取的文件信息char *abs_path=NULL;  char cmd[]="$update,"; //请求的命令头char out_buff[100];UINT cnt;strcpy(out_buff,cmd);/*1. 打开目录*/    res=f_opendir(&dir,path);if(res!=FR_OK)return res;/*2. 循环读取目录*/while(1){res=f_readdir(&dir,&fno);if(fno.fname[0] == 0 || res!=0)break;//printf("文件名称: %s,文件大小: %ld 字节\r\n",fno.fname,fno.fsize);/*过滤目录*/if(strstr(fno.fname,".ev")){//申请存放文件名称的长度abs_path=malloc(strlen(path)+strlen(fno.fname)+1);if(abs_path==NULL)break;strcpy(abs_path,path);strcat(abs_path,"/");strcat(abs_path,fno.fname);//读取文件数据f_open(&file,abs_path,FA_READ);f_read(&file,out_buff+strlen(cmd),100,&cnt);free(abs_path);      printf("abs_path=%s,读取:%d\r\n",abs_path,cnt);out_buff[cnt+strlen(cmd)]='\0';//发送给上位机ESP8266_ServerSendData(0,(u8*)out_buff,strlen((char*)out_buff));printf("发送:%s\r\n",out_buff);delay_ms(100);}}/*3. 关闭目录*/f_closedir(&dir);return 0;
}//提取数据,存放到全局事件结构体里
//参数: i 索引值  buf_out 源数据内容
void ExtractData(int i,char *buf_out)
{//std_to_sec(u16 syear, u8 smon, u8 sday, u8 hour, u8 min)char buf_num[50];//格式化处理StringSubstitution(buf_out, '/', ',');StringSubstitution(buf_out, ' ', ',');StringSubstitution(buf_out, ':', ',');printf("buf_out=%s\r\n",buf_out);//2022-03-05-10-11-2022-03-05-10-11-打酱油-5//1. 提取起始时间GetCommaOffsetBuff(buf_out,buf_num,0);event_buff[i].s_year = atoi(buf_num);printf("起始-年: %d,%s\r\n", event_buff[i].s_year, buf_num);GetCommaOffsetBuff(buf_out, buf_num, 1);event_buff[i].s_month = atoi(buf_num);printf("起始-月: %d,%s\r\n", event_buff[i].s_month, buf_num);GetCommaOffsetBuff(buf_out, buf_num, 2);event_buff[i].s_date = atoi(buf_num);printf("起始-日: %d,%s\r\n", event_buff[i].s_date, buf_num);GetCommaOffsetBuff(buf_out, buf_num, 3);event_buff[i].s_hour = atoi(buf_num);printf("起始-时: %d,%s\r\n", event_buff[i].s_hour, buf_num);GetCommaOffsetBuff(buf_out, buf_num, 4);event_buff[i].s_min = atoi(buf_num);printf("起始-分: %d,%s\r\n", event_buff[i].s_min, buf_num);//2. 提取结束时间GetCommaOffsetBuff(buf_out, buf_num, 5);event_buff[i].e_year = atoi(buf_num);printf("结束-年: %d,%s\r\n", event_buff[i].e_year, buf_num);GetCommaOffsetBuff(buf_out, buf_num, 6);event_buff[i].e_month = atoi(buf_num);printf("结束-月: %d,%s\r\n", event_buff[i].e_month, buf_num);GetCommaOffsetBuff(buf_out, buf_num, 7);event_buff[i].e_date = atoi(buf_num);printf("结束-日: %d,%s\r\n", event_buff[i].e_date, buf_num);GetCommaOffsetBuff(buf_out, buf_num, 8);event_buff[i].e_hour = atoi(buf_num);printf("结束-时: %d,%s\r\n", event_buff[i].e_hour, buf_num);GetCommaOffsetBuff(buf_out, buf_num, 9);event_buff[i].e_min = atoi(buf_num);printf("结束-分: %d,%s\r\n", event_buff[i].e_min, buf_num);//3. 提取事件内容GetCommaOffsetBuff(buf_out, buf_num,10);strcpy((char*)event_buff[i].event_buff, buf_num);printf("事件内容:%s\r\n", event_buff[i].event_buff);//4. 提前提醒时间GetCommaOffsetBuff(buf_out, buf_num, 11);event_buff[i].time_min_advance = atoi(buf_num);printf("提前提醒时间:%d分钟\r\n", event_buff[i].time_min_advance);//5. 设置标志位event_buff[i].flag = 1;
}//最多15个事件提醒
struct Event event_buff[15];//更新事件列表
u8 update_event_list(void)
{char *path="0:/"; //目录位置DIR dir;FIL file; //文件指针FRESULT res; FILINFO fno; //存放读取的文件信息char *abs_path=NULL;  char out_buff[100];UINT cnt;int index=0; //数组索引//先将数组全部清0memset(event_buff,0,sizeof(event_buff));/*1. 打开目录*/    res=f_opendir(&dir,path);if(res!=FR_OK)return res;/*2. 循环读取目录*/while(1){res=f_readdir(&dir,&fno);if(fno.fname[0] == 0 || res!=0)break;//printf("文件名称: %s,文件大小: %ld 字节\r\n",fno.fname,fno.fsize);/*过滤目录*/if(strstr(fno.fname,".ev")){//申请存放文件名称的长度abs_path=malloc(strlen(path)+strlen(fno.fname)+1);if(abs_path==NULL)break;strcpy(abs_path,path);strcat(abs_path,"/");strcat(abs_path,fno.fname);//读取文件数据f_open(&file,abs_path,FA_READ);f_read(&file,out_buff,100,&cnt);free(abs_path); out_buff[cnt]='\0'; //添加结束符printf("abs_path=%s,读取:%d,%s\r\n",abs_path,cnt,out_buff);//解析数据存放到数组里//2022/03/05 10:11,2022/03/05 10:11,打酱油,5ExtractData(index++,out_buff);if(index>=15)break; //最大存放15个事件}}/*3. 关闭目录*/f_closedir(&dir);return 0;
}

7.4 时间更新

RTC时间更新,通过上位机发送时间进行更新。

核心代码:

void rtc_time_update(char *buff)
{char *time;/*判断是否收到客户端发来的数据  */char *p=strstr((char*)buff,"+IPD");if(p!=NULL) //正常数据格式: +IPD,0,7:LED1_ON    +IPD,0表示第0个客户端   7:LED1_ON表示数据长度与数据{/*解析上位机发来的数据*/p=strstr((char*)buff,":");if(p!=NULL){p+=1; //向后偏移1个字节if(*p=='*')  //设置RTC时间{p+=1; //向后偏移,指向正确的时间time=p;calendar.w_year=(time[0]-48)*1000+(time[1]-48)*100+(time[2]-48)*10+(time[3]-48)*1;calendar.w_month=(time[4]-48)*10+(time[5]-48)*1;calendar.w_date=(time[6]-48)*10+(time[7]-48)*1;calendar.hour=(time[8]-48)*10+(time[9]-48)*1;calendar.min=(time[10]-48)*10+(time[11]-48)*1;calendar.sec=(time[12]-48)*10+(time[13]-48)*1;RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);printf("时间设置成功:%s\r\n",buff);}}}
}

7.5 LCD屏几个主要页面

主循环里通过轮询按键,检测是否需要切换显示页面。

目前设计有3个主页面+N个事件显示页面。

(1)页面1: 模拟电子时钟页面

(2)页面2:日历显示页面

(3)页面3-N : 待办事件显示页面

7.6 RTC时钟

RTC开启了秒中断,在秒中断里绘制模拟时钟页面,更新当前的系统时间。

7.7 事件时间判断页面

主函数里使用定时器1,以10秒的频率,判断待办事件时间是否到达,是否需要语音播报。

/*
函数功能: 定时器1的更新中断服务函数
*/
#include "app.h"
#include "rtc.h"
#include "syn6628.h"
u32 time_ev_cnt=0;
void TIM1_UP_IRQHandler(void)
{int i=0;u32 t1=0;u32 t2=0;u32 t3=0;char dir_file_path[50];if(TIM1->SR&1<<0){TIM1->SR&=~(1<<0);}time_ev_cnt++;//10秒时间if(time_ev_cnt>=2){time_ev_cnt=0;printf("10秒时间到达.\r\n");for(i=0;i<15;i++){if(event_buff[i].flag==0)break;//当前时间t1=std_to_sec(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min);//提醒开始时间t2=std_to_sec(event_buff[i].s_year,event_buff[i].s_month,event_buff[i].s_date,event_buff[i].s_hour,event_buff[i].s_min);//提醒结束时间t3=std_to_sec(event_buff[i].e_year,event_buff[i].e_month,event_buff[i].e_date,event_buff[i].s_hour,event_buff[i].e_min);//加上提前提醒的分钟t2+=event_buff[i].time_min_advance*60;//判断有没有时间满足需求,满足就语音提示if(t1>=t2 && t1<=t3){//时间达到,语音播报SYN6288_Speech("您有待开始的日程,请注意");//如果需要播放具体的内容,直接播放结构体里的成员即可}//如果时间超过,就可以删除事件if(t1>=t3){//删除SD卡上的这个文件//拼接路径sprintf(dir_file_path,"0:/%d-%d-%d-%d-%d.ev",event_buff[i].s_year,event_buff[i].s_month,event_buff[i].s_date,event_buff[i].s_hour,event_buff[i].s_min);if(f_unlink(dir_file_path)==FR_OK){printf("%s\r\n删除成功.",dir_file_path);//更新事件列表update_event_list();}else{printf("%s\r\n删除失败.",dir_file_path);}  }}}
}

基于STM32设计的WiFi语音播报日程表相关推荐

  1. 最简单DIY基于STM32单片机的WIFI智能小车设计方案

    STM32库函数开发系列文章目录 第一篇:STM32F103ZET6单片机双串口互发程序设计与实现 第二篇:最简单DIY基于STM32单片机的蓝牙智能小车设计方案 第三篇:最简单DIY基于STM32F ...

  2. 基于STM32设计的健康检测设备(测温心率计步)

    1. 项目介绍 本文介绍的项目是基于STM32设计的健康检测设备,支持体温测量,心率检测,支持运动计步(采用MPU6050陀螺仪实现),支持WIFI传输数据到手机APP打印显示. 硬件环境介绍: MC ...

  3. (毕业设计资料)基于STM32的物联网WiFi智能家居控制系统

    092[电路方案]基于STM32的物联网WiFi智能家居控制系统 功能: 1.可以检测环境中温湿度,气压,一氧化碳,空气质量,烟雾浓度和光照强度. 2.将测量的值显示在屏幕上,数据上报机智云平台可以通 ...

  4. 基于STM32设计的指针式电子钟与万年历

    1. 项目简介 这是基于STM32设计的一个指针式电子钟+万年历小项目,采用3.5寸的LCD屏显示时钟,日历.温度.天气,支持触摸屏调整设置时间,设置闹钟,查看日历等等.整体项目主要是技术点就是LCD ...

  5. 基于stm32单片机智能WIFI加湿器水质温湿度测量

    基于stm32单片机智能WIFI加湿器水质温湿度测量(原理图+程序+参考论文) 资料编号:021 可通过手机连接wifi 远程控制加湿器的开关,并且可以通过手机查看温湿度,可检测是否有水,缺水报警,和 ...

  6. 基于STM32设计的小说阅读器(翻页、字体切换、颜色切换、语音播报)

    一.环境介绍 小车主控MCU: STM32F103ZET6 STM32程序开发IDE: keil5 STM32程序风格:  采用寄存器方式开发,注释齐全,执行效率高,方便移植 硬件包含:  一块STM ...

  7. 基于STM32设计的人体健康监护系统(华为云IOT)

    一.设计需求 1.1 设计需求总结 根据需求,要求设计一款基于 STM32 的人体健康监护系统.采用系统模块化思路进行,将多个数模传感器收集到的数据和操作指令一并送至 STM32 中心处理器进行处理分 ...

  8. stm32 交换机芯片_基于STM32的全链路语音交互 - stm32/stm8 - 电子工程世界

    硬件平台:STM32F746G-DISC开发板 编译软件:KEIL 5.31 操作系统:RTX5 TCP/IP协议栈:Cyclone-TCP 语音交互平台:思必驰DUI开放平台 这里说一下使用的TCP ...

  9. 基于stm32单片机的WIFI智能联网天气预报自动校时系统(源码+原理图+全套资料)

    资料编号:071 通过wifi 联网获取任何城市的时间和天气,OLED显示,城市位置可以调整, 具体功能请看演示视频  全套资料齐全: 71-基于stm32单片机的WIFI智能联网天气预报自动校时系统 ...

  10. 基于cw32f030c8t6的多功能语音播报提醒装置装置

    有幸申请到了武汉芯源公司的大学计划板开发板,本次结合历程探索学习,应一位小学教师朋友的需要,对孩子兴趣启蒙并对孩子们声音大小提醒,故使用cw32f030c8t6mcu开发这款多功能语音播报提醒装置 功 ...

最新文章

  1. 图灵九月书讯 ——金秋时节推荐给程序员们的书
  2. Matlab之switch-case语句
  3. 会计记忆总结之八:财务会计报告
  4. python —skleran分类示例(全流程)
  5. video-js RTMP直播
  6. 7个设计模式的基本原则
  7. 360数科第三季度财报:输出积木式技术样板,科技业务占比提升至28%
  8. Android StorageManager 存储设备管理
  9. 如何隐藏计算机桌面窗口,电脑如何设置切换任务时可以隐藏已打开的窗口?[多图]...
  10. postgresql -- 绑定变量窥视规则
  11. 企业微信防撤回插件 WeChatICU v1.0.1中文版
  12. html怎么做出相框的效果,使用CSS3制作PS级的图片边框效果
  13. 【泛函分析】距离空间和赋范空间
  14. Java将List对象导入Excel文件
  15. NER的过去、现在和未来综述-现在
  16. 射雕英雄传人物关系python_《射雕英雄传》人物关系图
  17. Case When和聚合函数count、sum的使用
  18. 又干起一起胡闹的事了,,,,,,,,
  19. 电影购票系统接口篇【全栈开发】
  20. 在橙黄色网站设计中寻找灵感

热门文章

  1. 无线安全之破解WPA/WPA2 加密WiFi
  2. windows server 2008安装配置DHCP服务器
  3. js下载activex
  4. 用c语言编程质数和合数,《质数和合数》教学设计
  5. 马士兵java学习之路
  6. Dynamics 365Online Server-Side OAuth身份认证二(S2S)
  7. 狸窝全能视频转换器功能介绍
  8. 找到某个关键字 同义词词林 python_python基础——标识符
  9. SQL Server 触发器
  10. adb shell 命令