Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
alarm
RTC
组件
RT-Thread 应用笔记 - RTC Alarm 组件的使用
发布于 2020-11-21 19:04:07 浏览:4928
订阅该版
[tocm] [RT-Thread 入门学习笔记 - 目录](https://club.rt-thread.org/ask/article/3420.html) [RT-Thread 应用笔记 - 不正确使用LOG也会引发hard fault](https://club.rt-thread.org/ask/article/2329.html) [RT-Thread 应用笔记 - RTC Alarm 组件的使用](https://club.rt-thread.org/ask/article/2312.html) [RT-Thread 应用笔记 - freemodbus RTU RS485 从机](https://club.rt-thread.org/ask/article/2346.html) [RT-Thread 应用笔记 - freemodbus RTU RS485 主机](https://club.rt-thread.org/ask/article/2353.html) [RT-Thread 应用笔记 - libmodbus RTU RS485 从机](https://club.rt-thread.org/ask/article/2378.html) [RT-Thread 应用笔记 - libmodbus RTU RS485 主机](https://club.rt-thread.org/ask/article/2382.html) [RT-Thread 应用笔记 - STM32 CAN 通信双机](https://club.rt-thread.org/ask/article/2385.html) ## 背景 * 调试完RTC,实现闹钟的功能,RT-Thread已经有了闹钟alarm的组件。 * 但没找到较详细的使用文档或实现例程。 * 熟悉MCU平台的RTC alarm功能,把RT-Thread alarm组件用起来。 ## 使能 RTC Alarm组件 * 使用RT-Thread 的 ENV工具:menuconfig,配置使能RTC与Alarm ``` [RT-Thread Components] ->[Device Drivers] -> [Using RTC device drivers] -> [Using RTC alarm] ``` ![使能alarm](/uploads/20201121/a2fa9d6a9c92eed8817d5eabd8e716cb.png) * Alarm 组件包含: ``` alarm.h alarm 组件头文件 alarm.c alarm 组件功能实现 ``` ## 闹钟的使用方法 * 什么是闹钟? > 闹钟类似于定时器,如手机上的闹钟,你设置好时间,时间到了,就可以触发闹钟事件,振动或声音提醒。 * 可以同时设置几个闹钟? > 对于用户来讲,理论上可以设置无限个闹钟!但对于底层硬件,只有一个,也就是你只能设置一个alarm时间。设置多次,只有最后一次的生效! * 如何实现多个闹钟? > 底层只能设置一个闹钟,但用户需要多个闹钟。所以,需要引入闹钟alarm组件,用于管理多个闹钟。你可以认为每创建一个闹钟,就有一个闹钟的节点,链入到闹钟的链表里。 * Alarm组件 alarm链表有几个?如何实现其中部分闹钟的使能? > Alarm组件链表只有一个链表。比如你创建了4个闹钟,只开启2个闹钟。闹钟结构体,有使能的标志,你不使能,那这个闹钟就不工作。 ## alarm组件基本工作原理 * 闹钟的创建:rt_alarm_create * 例程如下:
```c static struct rt_alarm * p_alarm_hour = RT_NULL; /* 闹钟的回调函数,多个闹钟,可以有多个回调函数,用于创建闹钟时注册。闹钟时间到了,会执行此函数 */ static void alarm_hour_cb(rt_alarm_t alarm, time_t timestamp) { LOG_D("alarm_hour_cb ok!\n"); } static void rtc_alarm_hour_create(void) { static time_t now; struct tm *p_tm; struct rt_alarm_setup alarm_setup_test; if (p_alarm_hour != RT_NULL) return; now = time(NULL); p_tm = localtime(&now); alarm_setup_test.flag = RT_ALARM_HOUR; alarm_setup_test.wktime.tm_year = p_tm->tm_year; alarm_setup_test.wktime.tm_mon = p_tm->tm_mon; alarm_setup_test.wktime.tm_mday = p_tm->tm_mday; alarm_setup_test.wktime.tm_wday = p_tm->tm_wday; alarm_setup_test.wktime.tm_hour = p_tm->tm_hour + 1; alarm_setup_test.wktime.tm_min = p_tm->tm_min; alarm_setup_test.wktime.tm_sec = p_tm->tm_sec; p_alarm_hour = rt_alarm_create(alarm_hour_cb, &alarm_setup_test); } ``` * 闹钟创建后,并不会执行! * 闹钟有个flag,用于标识此闹钟是一次性的,还是周期性的。 * 创建闹钟时的flag参数 * 介绍如下: ```c /* alarm flags */ /* 一次性的闹钟,【rtc到了这个时间】,闹钟响应后,就不再工作!只有一次 */ #define RT_ALARM_ONESHOT 0x000 /* only alarm onece */ /* Daily,闹钟每天这个时间,都会响一次 每天一次 */ #define RT_ALARM_DAILY 0x100 /* alarm everyday */ /* weekly,闹钟【每周的这一天】【rtc到了这个时间】,会响一次 每周一次 */ #define RT_ALARM_WEEKLY 0x200 /* alarm weekly at Monday or Friday etc. */ /* monthly,闹钟【每月的这一天】【rtc到了这个时间】,会响一次 ,每月一次 */ #define RT_ALARM_MONTHLY 0x400 /* alarm monthly at someday */ /* yearly,闹钟【每年,并且这个月的这一天】【rtc到了这个时间】,会响一次,每年一次*/ #define RT_ALARM_YAERLY 0x800 /* alarm yearly at a certain date */ /* each hourly,闹钟【每小时】【这个时间:分钟:秒】,会响一次,每天24次!!*/ #define RT_ALARM_HOUR 0x1000 /* alarm each hour at a certain min:second */ /* each minute,闹钟【每分钟】【这个时间:秒】,会响一次,每小时60次!!*/ #define RT_ALARM_MINUTE 0x2000 /* alarm each minute at a certain second */ /* each second ,闹钟【每秒】【这个时间:不关心!】,会响一次,每分钟60次!!*/ #define RT_ALARM_SECOND 0x4000 /* alarm each second */ ``` * 闹钟设置 > 一般MCU只会设置hh:mm:ss, MCU的alarm,一般可以设置按天、按周等周期性的重复响应,也可以设置一次性的。 * 按天周期性的闹钟,一天一次,设置时,只关心hh:mm:ss * 按小时周期性的闹钟,一天24次,设置时,只关心mm:ss,也就是分钟:秒钟,每个小时都会触发一次。 * 按分钟周期性的闹钟,一分钟一次,只关心秒。下一分钟的那个秒,就会触发。 * 按秒周期性的闹钟,每一秒触发一次!! 设置的hh:mm:ss,不关心!! >alarm 开启:rt_alarm_start * 类似于定时器的开启 ```c static void rtc_alarm_hour_start(void) { if (p_alarm_hour != RT_NULL) rt_alarm_start(p_alarm_hour); } ``` * alarm 停止:rt_alarm_stop * 类似于定时器的停止 ```c static void rtc_alarm_hour_stop(void) { if (p_alarm_hour != RT_NULL) rt_alarm_stop(p_alarm_hour); } ``` * alarm 删除:rt_alarm_delete * 闹钟的删除,删除后,再次使用,需要重新创建闹钟 ```c static void rtc_alarm_hour_delete(void) { if (p_alarm_hour != RT_NULL) { if (rt_alarm_delete(p_alarm_hour) == RT_EOK) p_alarm_hour = RT_NULL; } } ``` ## alarm组件的工作原理 * 闹钟创建一个,就会新增一个闹钟的节点在闹钟的链表上。注意,无排序。 * 闹钟启动:每次遍历一遍闹钟的链表,找到最先超时的闹钟,并设置闹钟。 * 闹钟的停止:更改闹钟的flag为不使能。 * 闹钟的删除:闹钟的链表上,删除这个闹钟节点,目前,闹钟节点句柄是全局的。 * 闹钟中断,需要调用:rt_alarm_update * rt_alarm_update 会根据闹钟的周期性标志位,判断是否超时,并执行注册的闹钟回调函数。并重新遍历闹钟链表,获取最先超时的闹钟。并设置闹钟。 ## alarm组件的实现 * 首先需要实现rtc的功能 * 配置MCU alarm,默认使能 [按天]周期性响应的闹钟。 * 完善rtc的平台适配:drv_rtc.c control函数 * 示例如下: ```c static struct rt_rtc_device rtc_device; #ifdef RT_USING_ALARM static rt_err_t rtc_alarm_time_set(struct rt_rtc_device* p_dev); static int rt_rtc_alarm_init(void); #endif /* rtc 与 alrm,共用 control函数 */ static rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void *args) { rt_err_t result = RT_EOK; #ifdef RT_USING_ALARM struct rt_rtc_wkalarm *p_wkalarm = RT_NULL; #endif RT_ASSERT(dev != RT_NULL); switch (cmd) { case RT_DEVICE_CTRL_RTC_GET_TIME: *(rt_uint32_t *)args = get_rtc_timestamp(); LOG_D("RTC: get rtc_time %x\n", *(rt_uint32_t *)args); break; case RT_DEVICE_CTRL_RTC_SET_TIME: if (set_rtc_timestamp(*(rt_uint32_t *)args)) { result = -RT_ERROR; } #ifdef RT_USING_ALARM rt_alarm_update(&rtc_device.device, 1); #endif LOG_D("RTC: set rtc_time %x\n", *(rt_uint32_t *)args); break; #ifdef RT_USING_ALARM case RT_DEVICE_CTRL_RTC_GET_ALARM: args = &rtc_device.wkalarm; break; case RT_DEVICE_CTRL_RTC_SET_ALARM: p_wkalarm = (struct rt_rtc_wkalarm *)args; if (p_wkalarm != RT_NULL) { rtc_device.wkalarm.enable = p_wkalarm->enable; rtc_device.wkalarm.tm_hour = p_wkalarm->tm_hour; rtc_device.wkalarm.tm_min = p_wkalarm->tm_min; rtc_device.wkalarm.tm_sec = p_wkalarm->tm_sec; rtc_alarm_time_set(&rtc_device); } else { result = -RT_ERROR; } break; #endif } return result; } /* 设置闹钟的MCU适配函数,不同的MCU,会有区别 */ static rt_err_t rtc_alarm_time_set(struct rt_rtc_device* p_dev) { am_hal_rtc_time_t rtc_Time = {0}; time_t timestamp = 0; struct tm *p_tm; if (p_dev->wkalarm.enable) { timestamp = get_rtc_timestamp(); p_tm = localtime(×tamp); if (p_tm->tm_year < 100) { return -RT_ERROR; } rtc_Time.ui32Second = p_dev->wkalarm.tm_sec ; rtc_Time.ui32Minute = p_dev->wkalarm.tm_min ; rtc_Time.ui32Hour = p_dev->wkalarm.tm_hour; LOG_D("%s-%d:%d:%d", __func__, p_dev->wkalarm.tm_hour, p_dev->wkalarm.tm_min,p_dev->wkalarm.tm_sec); rtc_Time.ui32DayOfMonth = p_tm->tm_mday; rtc_Time.ui32Month = p_tm->tm_mon + 1 ; rtc_Time.ui32Year = p_tm->tm_year - 100; rtc_Time.ui32Weekday = p_tm->tm_wday + 1; am_hal_rtc_alarm_set(&rtc_Time, RTC_ALM_RPT_INTERVAL); rt_rtc_alarm_enable(); } return RT_EOK; } ``` ## alarm组件功能验证
>创建了alarm,怎么知道是否成功?
* 除了LOG的打印,等事件是很难的,如设置了一年后,需要一年后再回来看结果?使用date更改系统的时间!! * alarm组件提供alarm查询功能,如下: ```c msh />alarm_dump | alarm_id | YYYY-MM-DD hh:mm:ss | weekday | flags | +----------+---------------------+---------+---------+ | No 0 | 2000-01-01 00:00:20 | 6 | 0x4003 | +----------+---------------------+---------+---------+ msh /> ``` * 前期可以使用MSH CMD命令,进行闹钟的创建、开启、停止、删除操作。
* 参考文档 [RTC设备](https://www.rt-thread.org/document/site/programming-manual/device/rtc/rtc/)
17
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
张世争
学以致用
文章
131
回答
813
被采纳
177
关注TA
发私信
相关文章
1
RTC驱动框架几点建议
2
求助:RTT在STM32F407上使用内置的RTC设置日期需重启生效,设置时间即时生效,有遇到同样问题的吗?
3
[新人试水] LPC1768 Nano3_9 添加RTC
4
STM32 关于RTC的问题
5
stm32f4xx-HAL BSP的RTC设置不对
6
关于STM32的RTC设置年份不正确的问题
7
RTT的RTC驱动调试
8
rtc驱动中的bkp模块起不到防止时间的重新设置
9
rtc时钟跑十几个小时后,比实际时间快几秒怎么解决
10
stm32如何断电之后开发板rtc时间继续往前跑
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
xusiwei1236
8
个答案
2
次被采纳
踩姑娘的小蘑菇
1
个答案
2
次被采纳
用户名由3_15位
9
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
RTT_逍遥
3
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
15
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
4
次点赞
Ghost_Girls
1
篇文章
7
次点赞
xiaorui
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部