不依赖硬件,可以无限扩展的闹钟组件

news2024/11/20 7:03:41
  1. 在实际的开发项目中,很多时候我们需要定时的做一些事情,举例:

    • ①路上的路灯,每天晚上6:00准时打开,每天早上6:00准时关闭;
    • ②定时闹钟,起床上班。这些行为其实都是定时任务–闹钟。
  2. 大部分单片机都提供了rtc alarm硬件闹钟,但是实际很少人使用,就举个简单的例子,rt-thread的BSP中也没有几个芯片适配了alarm硬件闹钟。但是我们要使用怎么办??

  3. 我受到RTOS的调度的启发,像M3/M4这种内核都是SysTick产生时钟节拍,以供系统处理所有和时间有关的事情,如线程延时,线程的时间片轮转,以及定时器超时等。

  4. 有了第3点的经验,那么我们可以写一个软件闹钟功能就容易多了,只需要提供一个刷新节拍,定时查看哪一个闹钟需要唤醒,就可以解决闹钟的管理了。

  5. 闹钟组件名字:RAlarm(全称Rice Alarm),源码连接:https://gitee.com/RiceChen0/ralarm

RAlarm

RAlarm接口说明:

跨平台

  • RTOS的种类很多,接口差异性打,所以RAlarm为了解决这个问题,统一为上层提供一整套接口。
  1. 线程接口。
typedef void *ralarm_task_id;

struct ralarm_task_attr{
    const char *name;       // name of the task
    uint32_t stack_size;     // size of stack
    uint8_t priority;       // initial task priority
};

typedef void(*ralarm_task_func)(void *arg);

ralarm_task_id ralarm_task_create(ralarm_task_func func, void *arg, const struct ralarm_task_attr *attr);
void ralarm_task_delete(ralarm_task_id thread);
  1. 互斥量接口。
typedef void *ralarm_mutex_id;

ralarm_mutex_id ralarm_mutex_create(void);
ralarm_err_t ralarm_mutex_lock(ralarm_mutex_id mutex);
ralarm_err_t ralarm_mutex_unlock(ralarm_mutex_id mutex);
void ralarm_mutex_delete(ralarm_mutex_id mutex);
  1. 事件接口。
typedef void *ralarm_event_id;

ralarm_event_id ralarm_event_create(void);
uint32_t ralarm_event_recv(ralarm_event_id event, uint32_t flags);
ralarm_err_t ralarm_event_send(ralarm_event_id event, uint32_t flags);
void ralarm_event_delete(ralarm_event_id event);
  • RAlarm目前已经提供了两个环境的适配,如cmsis,rtthread。

接口使用简单

接口说明
ralarm_init初始化
ralarm_deinit去初始化
ralarm_create创建闹钟
ralarm_start启动闹钟
ralarm_stop停止闹钟
ralarm_modify修改闹钟
ralarm_delete删除闹钟
  • 闹钟初始化接口:初始化闹钟的链表,闹钟任务,事件,互斥锁;去初始化接口:注销闹钟组件
/* 闹钟初始化 */
ralarm_err_t ralarm_init(void);

/* 闹钟去初始化 */
void ralarm_deinit(void);
  • 闹钟创建:
  1. 参数说明:
参数描述
setup闹钟的时间和标志,flag可为:RALARM_ONESHOT(只设置一次)和RALARM_DAILY(每天都设置)
cb闹钟时间到了,唤醒的回调函数指针:typedef void (*ralarm_response_cb)(ralarm_t alarm)
userData设置闹钟时,自带的用户数据的指针
返回——
ralarm_t闹钟创建成功,放回闹钟句柄
NULL闹钟创建失败
  1. 函数说明:
    • ①申请闹钟控制块的空间。
    • ②设置闹钟参数到控制块中。
    • ③将闹钟加入到闹钟链表中。
struct ralarm_setup {
    ralarm_flag flag;
    struct ralarm_time time;
};
typedef struct ralarm_setup *ralarm_setup_t;

struct ralarm {
    ralarm_state state;
    struct ralarm_setup setup;
    ralarm_response_cb cb;
    void *userData;
    ralarm_list_t list;
};
typedef struct ralarm *ralarm_t;

ralarm_t ralarm_create(ralarm_setup_t setup, ralarm_response_cb cb, void *userData)
{
    ralarm_t alarm = NULL;
    
    if(setup == NULL) {
        RALARM_LOGE("Create alarm failed, Setup param is NULL");
        return NULL;
    }
    alarm = RALARM_MALLOC(sizeof(struct ralarm));                           // ----①
    if(alarm == NULL) {
        RALARM_LOGE("Malloc alarm memory failed");
        return NULL;
    }

    ralarm_list_init(&alarm->list);                                         // ----②
    memset((void *)alarm, 0, sizeof(struct ralarm));
    memcpy((void *)&alarm->setup, setup, sizeof(struct ralarm_setup));
    alarm->cb = cb;
    alarm->userData = userData;

    ralarm_mutex_lock(g_container.mutex);
    ralarm_list_insert_after(&g_container.list, &alarm->list);              // ----③
    ralarm_mutex_unlock(g_container.mutex);
    return alarm;
}
  • 闹钟启动:将闹钟的状态的start bit置为1。
ralarm_err_t ralarm_start(ralarm_t alarm)
{
    if(alarm == NULL) {
        return RALARM_ERROR;
    }
    ralarm_mutex_lock(g_container.mutex);
    alarm->state |= RALARM_STATE_START;

    ralarm_mutex_unlock(g_container.mutex);
    return RALARM_EOK;
}
  • 闹钟停止:将闹钟的状态的start bit置为0。
ralarm_err_t ralarm_stop(ralarm_t alarm)
{
    if(alarm == NULL) {
        return RALARM_ERROR;
    }
    ralarm_mutex_lock(g_container.mutex);
    alarm->state &= ~RALARM_STATE_START;

    ralarm_mutex_unlock(g_container.mutex);
    return RALARM_EOK;
}
  • 闹钟修改:修改闹钟的标志和闹钟的时间
  1. 参数说明:
参数描述
alarm闹钟的句柄
setup要修改闹钟的时间和标志参数
返回——
RALARM_EOK修改成功
RALARM_ERROR修改失败
ralarm_err_t ralarm_modify(ralarm_t alarm, ralarm_setup_t setup)
{
    if(alarm == NULL) {
        return RALARM_ERROR;
    }
    ralarm_mutex_lock(g_container.mutex);

    memcpy((void *)&alarm->setup, setup, sizeof(struct ralarm_setup));

    ralarm_mutex_unlock(g_container.mutex);
    return RALARM_EOK;
}
  • 删除闹钟:
  1. 函数说明:
    • ①将闹钟的状态的start bit置为0。
    • ②将闹钟从闹钟链表中移除。
    • ③释放闹钟的内存。
ralarm_err_t ralarm_delete(ralarm_t alarm)
{
    if(alarm == NULL) {
        return RALARM_ERROR;
    }
    ralarm_mutex_lock(g_container.mutex);

    alarm->state &= ~RALARM_STATE_START;        // ---①
    ralarm_list_remove(&alarm->list);           // ---②
    RALARM_FREE(alarm);                         // ---③
    alarm = NULL;

    ralarm_mutex_unlock(g_container.mutex);
    return RALARM_EOK;
}

适配简单

  • 根据系统能力,提供获取时间方法,创建ralarm的ops并注册获取时间接口。
struct ralarm_ops{
    ralarm_err_t (*time_get)(ralarm_time_t time);
};

ralarm_err_t ralarm_register_ops(struct ralarm_ops *ops);
  • 提供刷新节拍,然后调用刷新接口。
void ralarm_refresh(void);

RAlarm运行逻辑:

  1. 闹钟的refresh接口需要用户提供一个刷新节拍,以提供闹钟的生命。
  2. refresh皆苦根据闹钟链表是否存在已设置的闹钟,选择发送事件给更新任务,更新检测闹钟的状态。
  3. 如下图:当检测闹钟链表无设置的闹钟,则不会发送事件给更新任务

  1. 如下图:
    • 当用户创建了闹钟,则会将闹钟挂在闹钟量表中。
    • 刷新节拍调用refresh之后,发送事件给更新任务,然后调用wakeup检测闹钟的状态。
    • 如果某个闹钟时间到,则会调用对应闹钟的回调函数。

RAlarm的使用

  • 在RT-Thread下使用ralarm组件:
    • ① 闹钟的处理函数,当闹钟时间到了,则会调用这个函数。
    • ② 提供给ralarm组件时间接口。
    • ③ 创建ops,提供时间接口。
    • ④ 软件定时器的处理函数,调用ralarm的刷新函数,提供刷新节拍。
    • ⑤ ralarm组件初始化,注册ops。
    • ⑥ 创建闹钟。
    • ⑦ 创建一个软件定时器,为ralarm组件提供刷新节拍。
static rt_timer_t timer;
ralarm_t alarm_test = NULL;

static void alarm_handler(ralarm_t alarm)                               // ---①
{
    rt_kprintf("Time: %02d:%02d:%02d\r\n", alarm->setup.time.hour,      
                alarm->setup.time.minute, alarm->setup.time.second);
    ralarm_stop(alarm);
    ralarm_dump();
}

static ralarm_err_t alarm_time_get(ralarm_time_t timer)                 // ---②
{
    time_t current;
    struct tm *local;
    
    time(&current);
    local = localtime(&current);
    timer->hour = local->tm_hour;
    timer->minute = local->tm_min;
    timer->second = local->tm_sec;
    return RALARM_EOK;
}

static struct ralarm_ops ops = {                                        // ---③
    .time_get = alarm_time_get,
};

static void time_handler(void *param)                                   // ---④
{
    ralarm_refresh();
}

int main(void)
{
    ralarm_init();                                                      // ---⑤
    ralarm_register_ops(&ops);

    struct ralarm_setup setup;
    setup.flag = RALARM_DAILY;
    setup.time.hour = 15;
    setup.time.minute = 0;
    setup.time.second = 0;

    alarm_test = ralarm_create(&setup, alarm_handler, NULL);            // ---⑥
    ralarm_start(alarm_test);

    ralarm_dump();

    timer = rt_timer_create("timer", time_handler,                      // ---⑦
                             RT_NULL, 800,
                             RT_TIMER_FLAG_PERIODIC);
    if (timer != RT_NULL) 
        rt_timer_start(timer);
}
  • 验证结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/537016.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySql】数据库设计过程

目录 概念数据库设计: 逻辑数据库设计: 物理数据库设计: ->需求分析(收集需求和理解需求,“源”) ->概念数据库设计(建立概念模型:"E-R图/IDEF1X") ->逻辑数据库设计&…

idle_in_transaction_session_timeout idle_session_timeout

这两个参数都是用来控制PostgreSQL数据库中会话的超时时间的。 idle_in_transaction_session_timeout idle_in_transaction_session_timeout参数用于控制在事务中处于空闲状态的会话的超时时间。如果一个会话在事务中处于空闲状态超过了指定的时间,则该会话将被终…

Rocky Linux 9.2 正式版发布 - RHEL 下游免费发行版

Rocky Linux 由 CentOS 项目的创始人 Gregory Kurtzer 领导。 请访问原文链接:https://sysin.org/blog/rocky-linux-9/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 以社区方式驱动的企业 Linux Rocky Linux 是…

Android Studio 基础 之 使用 okhttp 长连接,流式获取数据的方法简单整理了

Android Studio 基础 之 使用 okhttp 长连接,流式获取数据的方法简单整理了 目录 Android Studio 基础 之 使用 okhttp 长连接,流式获取数据的方法简单整理了 一、简单介绍 二、实现原理 三、注意事项 四、效果预览 五、实现关键 六、关键代码 七…

2023年服务器数据保护的详细指南

​  无论您经营的是小型个人博客还是日常流量很高的大型企业电子商务网站,安全性都是每个人都关心的问题。虽然粗略的第三方有时间和资源来利用他们在您的系统中发现的任何弱点,但您也可以采取其他措施来提高服务器的安全性并阻止它们。以下是您可以采…

论文笔记:tri-plane 【持续更新】

文章目录 概述Tri-Plane 表达验证 tri-plane 表达 3D GAN 框架CNN生成器backbone以及渲染超分Dual discriminationModeling pose-correlated attributes 实验数据 参考文献 概述 论文名称: Efficient Geometry-aware 3D Generative Adversarial Networks Project pa…

Class 04 - 日期时间格式

Class 04 - 日期时间格式 R语言中的日期和时间格式tidyverse 和 lubridate 功能包简介tidyverse 简介lubridate 简介 加载 tidyverse 和 lubridate 功能包处理日期和时间日期时间的格式获取当前的日期 today()获取当前的时间 now() 字符串格式转换为日期格式ymd()mdy()dmy()字符…

AlmaLinux 9.2 正式版发布 - RHEL 兼容免费发行版

AlmaLinux 9.2 正式版发布 - RHEL 兼容免费发行版 由社区提供的免费 Linux 操作系统,RHEL 兼容发行版。 请访问原文链接:https://sysin.org/blog/almalinux-9/,查看最新版。原创作品,转载请保留出处。 作者主页:sys…

一个胖乎乎的3D卡片(有点像捏扁的圆柱体)

先上效果图&#xff08;图片是随机的&#xff0c;可能你们看到的和这个不一样。但效果是相同的&#xff09;&#xff1a; 再上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Titl…

飞浆AI studio人工智能课程学习(1)-大模型时代优质Prompt

文章目录 大模型时代&优质PromptAl生成技术价值概览开始构建你的优质prompt 近十年深度学习模型主要更迭为什么大模型能够有如此强大的表现力大模型与Prompt例1&#xff1a; 画一幅画&#xff0c;呆萌的小猫躺在大泡泡中例2&#xff1a;请生成一张统计图&#xff0c;内容为…

apk自动签名工具

序言 因为360加固&#xff0c;自动签名需要开通VIP&#xff0c;每次加固完了都得手动签名。所以写了个工具。实现通过配置文件配置&#xff0c;拖拽APK自动签名。 支持&#xff1a;V1 V2 V3 V4 签名。通过分析清单文件&#xff0c;自动选择版本。 效果 使用 1.下载jar包 au…

实验室检验系统源码,集检验业务、质量控制、报告、统计分析、两癌等模块于一体

云 LIS 系统针对区域化 LIS 而设计&#xff0c;依托底层云架构&#xff0c;将传统的 LIS 功能模块进行“云化”。 该系统是集检验业务、科室管理、质量控制、报告、统计分析、两癌等模块于一体的数据检验信息平台。通过计算机联网&#xff0c;实现各类仪器数据结果的实时自动接…

新库上线 | CnOpenData舆情云数据

舆情云数据 一、数据简介 网络舆情监测数据是决策者进行数据分析和决策处置的基础。舆情云数据覆盖81000 网站、5600 论坛、1000 平面媒体、2500万 微信账号、3亿 微博账号、300 网络视频、17000 境外媒体、1400万 自媒体账号、2500 新闻客户端、170 电视台 &#xff0c;数据来…

图神经网络:(大型图的有关处理)在Pumbed数据集上动手实现图神经网络

文章说明&#xff1a; 1)参考资料&#xff1a;PYG官方文档。超链。 2)博主水平不高&#xff0c;如有错误还望批评指正。 3)我在百度网盘上传了这篇文章的jupyter notebook和有关文献。超链。提取码8848。 文章目录 Pumed数据集文献阅读继续实验 Pumed数据集 导库 from torch_…

【day2】单片机

目录 【1】GPIO 1.定义 2.应用 I - Input - 输入采集 O - Output - 输出控制 ​编辑 3.GPIO结构框图 4.功能描述 输入功能 输出功能 5.相关寄存器 【2】点亮一盏LED灯 1.实验步骤 2.编程实现 3.编译下载 4.复位上电 练习&#xff1a;实现LED灯闪烁 练习…

Linux - 第15节 - 网络基础(应用层)

1.再谈 "协议" 1.1.协议的概念 协议&#xff0c;网络协议的简称&#xff0c;网络协议是通信计算机双方必须共同遵从的一组约定&#xff0c;比如怎么建立连接、怎么互相识别等。 为了使数据在网络上能够从源到达目的&#xff0c;网络通信的参与方必须遵循相同的规则&…

收集数据集以训练自定义模型的 5 种方法

来源&#xff1a;投稿 作者&#xff1a;王同学 编辑&#xff1a;学姐 在过去的十年中&#xff0c;深度学习技术在计算机视觉领域中的应用逐年增加。其中当属「行人检测」和「车辆检测」最为火爆&#xff0c;其原因之一就是「预训练模型」的「可复用性」。 由于深度学习技术在这…

Pandas+Pyecharts | 新冠疫情数据动态时序可视化

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 按月统计数据 &#x1f3f3;️‍&#x1f308; 3. Pyecharts数据可视化3.1 疫情动态时序地图3.2 疫情动态时序折线图3.3 疫情动态时序柱状图3.4 疫情动态…

Maven中scope(作用范围)详解

目录 一、依赖传递二、依赖范围三、依赖范围对传递依赖的影响四、依赖调节五、可选依赖六、排除依赖七、依赖归类八、依赖管理 一、依赖传递 Maven 依赖传递是 Maven 的核心机制之一&#xff0c;它能够一定程度上简化 Maven 的依赖配置。 如下图所示&#xff0c;项目 A 依赖于…

黄牛为什么能抢走“五月天”的门票?

目录 “史上最难抢票”的五月天演唱会 黄牛为什么能抢到票 黄牛抢票带来哪些坏影响 售票平台为什么挡不住黄牛&#xff1f; 管理上如何有效防控黄牛 技术上如何有效防黄牛 相关技术产品推荐 随着文娱活动的复苏&#xff0c;大量黄牛“卷土袭来”。顶象防御云业务安全情报…