基于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既可以做为独立的应用 ...
随机推荐
- 【centOS7.3 彻底卸载MySQL】
废话不多说,直接正面刚. 1.删除MySQL yum remove mysql mysql-server mysql-libs mysql-server; 执行后继续查找相关文件 find / -na ...
- Ext自定义控件 - 自学ExtJS
本文所有思想表达均为个人意见,如有疑义请多批评,如有雷同不甚荣幸. 转载请注明出处:Nutk'Z http://www.cnblogs.com/nutkz/p/3448801.html 在用到ExtJ ...
- 基于DCT的图片数字水印实验
1. 实验类别 设计型实验:MATLAB设计并实现基于DCT的图像数字水印算法. 2. 实验目的 了解基于DCT的图像数字水印技术,掌握基于DCT系数关系的图像水印算法原理,设计并实现一种基于DCT的 ...
- IDEA一直提示 错误: 找不到或无法加载主类
1.把http://repo1.maven.org/maven2...下载下来2.放到本地Manen仓库archetype 文件夹下3.设置IDEA Maven->Runner 界面的VM Op ...
- Vue中异步组件(结合webpack,转载)
转载,原文出处:https://www.jianshu.com/p/40a364b5e964 1.什么是异步组件? 异步组件就是定义的时候什么都不做,只在组件需要渲染(组件第一次显示)的时候进行加载渲 ...
- JavaScript&jQuery 基本使用
* 最近连续加班加点三周* 遭不住了 ...* 来点 js / jq 的货* 一个人撸PHP 撸HTML 撸CSS 撸JavaScript 撸jQuery* 不管有没有用记录一下** 1:jQuery ...
- 【Hive五】Hive函数UDF
Hive函数 系统自带的函数 查看系统自带的函数 查看系统自带的函数 show functions; 显示自带的函数的用法 desc function upper; 详细显示自带的函数的用法 desc ...
- spark ---词频统计(二)
利用python来操作spark的词频统计,现将过程分享如下: 1.新建项目:(这里是在已有的项目中创建的,可单独创建wordcount项目) ①新建txt文件: wordcount.txt (文件内 ...
- C语言小程序-基于链表的学生信息管理
程序支持增加.查询.删除.存盘和读取操作 一 程序定义和函数声明 头文件studentsys.h定义如下 /* student management system by list */ #ifndef ...
- Java语法糖 : try-with-resources
先了解几个背景知识 什么是语法糖 语法糖是在语言中增加的某种语法,在不影响功能的情况下为程序员提供更方便的使用方式. 什么是资源 使用之后需要释放或者回收的都可以称为资源,比如JDBC的connect ...