基于freeRTOS定时器实现闹钟(定时)任务
基于freeRTOS定时器实现闹钟(定时)任务
在智能硬件产品中硬件中,闹钟定时任务是基本的需求。一般通过APP设置定时任务,从云端或者是APP直连硬件将闹钟任务保存在硬件flash中,硬件运行时会去处理闹钟任务。
最简单的实现方式是在循环或者定时器处理函数中不断的去判断当前时间是否等于闹钟设定时间,若相等则产生相应的动作。
这样做虽然可行,但是做了太多无用的计算。我们可以根据当前时间距离下一次闹钟激发时间,设定一个对应的定时器,定时器激发时就是闹钟时间,然后继续根据下次激发时间设定新的定时器,这样可以减少不必要的时间比较。
闹钟任务的表示
闹钟任务的表示包含一下及部分的内容:闹钟时间、重复类型、响应操作。
闹钟任务的本地表示可以根据cron格式来定义,当然也可以DIY一个,只要包含以上三个方面内容的就可以。
cron格式的时间表示如下:
| Character | Descriptor | Acceptable Values |
|---|---|---|
| 1 | Minute | 0~59, * (no specific value) |
| 2 | Hour | 0~23, * (no specific value) |
| 3 | Day of month | 1~31, * (no specific value) |
| 4 | Month | 1~12, * (no specific value) |
| 5 | Day of week | 0~7, * (no specific value) |
比如对于一个周一到周五早上7:00的闹钟,可以表示如为:0 7 * * 1,2,3,4,5。
我在代码中定义了如下的闹钟任务:
/* cron 格式时间表示 */
typedef struct
{
int min; // minute, 0xFFFFFFFF表示*
int hour; // hour, 0xFFFFFFFF表示*
int wday; // day of week, 0xFFFFFFFF表示*,bit[0~6] 表示周一到周日,如周一到周五每天响铃,则0x1F
int mday; // day of month, 0xFFFFFFFF表示*, bit[0~31] 表示1~31日,每月1,3,5号响铃,则0x15
int mon; // month, 0xFFFFFFFF表示*,bit[0~11] 表示1~12月
} cron_tm_t;
/* 闹钟任务 */
typedef struct
{
int id; // 任务ID
cron_tm_t cron_tm; // cron格式时间
int action; // 响应操作,对于灯控产品来说,action可以表示开关、颜色、场景等等
TimerHandle_t xTimer; // 定时器句柄
list_node_t node; // 节点,用于将一系列定时任务组织成list
} alarm_task_t;
闹钟下一次激发时间
基于定时器实现闹钟的原理是在每次设置闹钟时计算出距离下一次激发的间隔时间,然后设置一个相应时间的定时器。
首先需要根据cron格式时间计算出下一次激发的时间
/* 距离闹钟下一次激发的时间(min) */
int get_expiry_time(alarm_task_t *alarm_task)
{
/* 首先获取当前时间 */
time_t t;
struct tm now;
time(&t);
localtime_r(&t, &now);
int ret = 0;
if(alarm_task->cron_tm.min != 0xFFFFFFFF)
{
ret += cron_tm.min - now.tm_min;
}
if(alarm_task->cron_tm.hour != 0xFFFFFFFF)
{
int flag = 0;
for(int i=0; i<24; i++)
{
if(i == alarm_task->cron_tm.hour){
flag=1;
break;
}
}
if(flag){
ret += 60*(i-now.tm_hour);
}
}
/* 找到wday或者mday中距离今天最近的一天 */
int t = ret<0?1:0;
int d_wday=0;
int d_mday=0;
for(int i=0; i<7; i++)
{
int wday = now.tm_wday + t +i;
if(1<<(wday%7) & alarm_task->cron_tm.wday){
d_wday=i+t;
break;
}
}
for(int i=0; i<30; i++)
{
int mday = now.tm_mday + t +i;
if(1<<(mday%30) & alarm_task->cron_tm_.mday){
d_mday = i+t;
break;
}
}
int d = d_mday<d_wday?d_mday:d_wday;
ret += d*24*60;
return ret;
}
设置定时器
每次硬件上电时,或者闹钟激发时,都要根据下一次激发的时间,设置一次定时器。
int set_timer(alarm_task_t *alarm_task)
{
int t = get_expiry_time(alarm_task);
if(t <= 0) return -1; // 不需要设置下一次闹钟,不重复的闹钟,且时间已过
alarm_task->xTimer = xTimerCreate( "timer",
t / portTICK_RATE_MS,
1,
(void*)alarm_task,
timer_task_callback );
if(alarm_task->xTimer == NULL)
{
printf("!!! timer created failed\n");
return -1;
}
else
{
xTimerStart(alarm_task->xTimer, 0);
}
return 0;
}
基于freeRTOS定时器实现闹钟(定时)任务的更多相关文章
- FreeRTOS 定时器组
以下转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解 FreeRTOS 支持的定时器组,或者叫软件定时器,又或者叫用户定时器均可.软件定时器的功 ...
- 订餐系统之定时器Timer不定时
经过几天漫长的问题分析.处理.测试.验证,定时器Timer终于定时了,于是开始了这篇文章,希望对还在纠结于“定时器Timer不定时”的同学有所帮助,现在的方案,在系统日志中会有警告,如果您有更好的方案 ...
- 定时器Timer不定时
订餐系统之定时器Timer不定时 经过几天漫长的问题分析.处理.测试.验证,定时器Timer终于定时了,于是开始了这篇文章,希望对还在纠结于“定时器Timer不定时”的同学有所帮助,现在的方案,在系统 ...
- 乐鑫esp8266基于freeRtos实现私有服务器本地远程OTA升级
目录 一.前言: 二.回顾下OTA的流程: 三.lwip网络框架的知识的使用: 四.如何处理服务器返回的数据? 五.扇区的擦除和烧写? 六.如何调用? 七.好好享用吧! 八.下载: 九.工程截图: 代 ...
- JS定时器使用,定时定点,固定时刻,循环执行
JS定时器使用,定时定点,固定时刻,循环执行 本文概述:本文主要介绍通过JS实现定时定点执行,在某一个固定时刻执行某个函数的方法.比如说在下一个整点执行,在每一个整点执行,每隔10分钟定时执行的方法. ...
- java.util.Timer类似于闹钟定时做任务
在web中实现任务计划,相当于实现闹钟的功能,要完成2个步骤: 1.定时器的设置: 2.对这个定时器的启动运行和停止进行实时监听 java.util.Timer定时器,实际上是个线程,定时调度所拥有的 ...
- stm32f10x基于freeRTOS的低功耗实现
0. 写在前面 没有太多时间更新,可能偶尔有时间就更新一些. 因为突然有项目用到了stm32f10x系列并且是电池驱动的,所以需要对功耗进行优化,其他CM3核心系列应该也同样适用. 1. 背景 Stm ...
- Java系列--第八篇 基于Maven的SSME之定时邮件发送
关于ssme这个我的小示例项目,想做到麻雀虽小,五脏俱全,看到很多一些web都有定时发送邮件的功能,想我ssme也加入一下这种功能,经查询相关文档,发现spring本身自带了一个调度器quartz,下 ...
- 基于Quartz实现简单的定时发送邮件
一.什么是Quartz Quartz 是一个轻量级任务调度框架,只需要做些简单的配置就可以使用:它可以支持持久化的任务存储,即使是任务中断或服务重启后,仍可以继续运行.Quartz既可以做为独立的应用 ...
随机推荐
- 五、MapReduce 发布服务
是一个并行计算框架(计算的数据源比较广泛-HDFS.RDBMS.NoSQL),Hadoop的 MR模块充分利用了HDFS中所有数据节点(datanode)所在机器的内存.CUP以及少量磁盘完成对大数据 ...
- Error Note1:错误修复笔记
1.遍历同时修改数组内容导致崩溃 bugly上bug提醒如下图所示,经检查发现,可能是页面上数据加载惹得祸. 页面加载过程是这样的,首先进入页面,初始化页面,将本地数据加载到array中刷新table ...
- The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.报该错误的一种原因。
今天发现某个action返回404. HTTP Status 404 – Not Found Type Status Report Message /xxx.action Description Th ...
- 利用SoapUI 测试web service的一些问题总结
总结两个利用SoapUI 测试web service的一些问题: 1.请求一个soap service 请求的时候:按照下面的配置输入请求地址后, 2.根据实际service接口的需要,传入相应的参数 ...
- 爬虫-爬虫介绍及Scrapy简介
在编写案例之前首先理解几个问题,1:什么是爬虫2:为什么说python是门友好的爬虫语言?3:选用哪种框架编写爬虫程序 一:什么是爬虫? 爬虫 webSpider 也称之为网络蜘蛛,是使用一段编写好的 ...
- A1041
输入n个数,找出第一个只出现一次的数,输出它. 如果没有,输出none. 思路: 将输入的数值作为HashTable的数组下标即可. #include<cstdio> ], hashTab ...
- linux线程篇 (一) 线程的基本概念
--进程 一个正在执行的程序,资源分配的最小单位 进程中的事情需要按照一定顺序区执行的,但是如何在一个进程中让一些事情同时发生呢?子进程存在缺陷 --引进多线程 --线程:有时又称轻量级进程,程序执行 ...
- mysql自动提交
MySQL的autocommit(自动提交)默认是开启,其对mysql的性能有一定影响,举个例子来说,如果你插入了1000条数据,mysql会commit1000次的,如果我们把autocommit关 ...
- [SGU223]Little Kings(状压DP)
随便DP一下 Code #include <cstdio> int sta[150],cnt[150],tp,n,k; long long dp[12][144][150],Ans; in ...
- object转List<XXX>的问题
List<object> demo(object a) { List<object> res = new List<object>(); object c = a; ...