STM32CubeMX教程11 RTC 实时时钟 - 入侵检测和时间戳
使用STM32CubeMX软件配置STM32F407开发板RTC实现入侵检测和时间戳功能,具体为周期唤醒回调中使用串口输出当前RTC时间,按键WK_UP存储当前RTC时间到备份寄存器,按键KEY_2从备份寄存器中读取上次存储的时间,按键KEY_1负责产生入侵事件
1、准备材料
开发板(正点原子stm32f407探索者开发板V2.4)
ST-LINK/V2驱动
STM32CubeMX软件(Version 6.10.0)
keil µVision5 IDE(MDK-Arm)
CH340G Windows系统驱动程序(CH341SER.EXE)
XCOM V2.6串口助手
杜邦线一根
2、实验目标
使用STM32CubeMX软件配置STM32F407开发板RTC实现入侵检测和时间戳功能,具体为周期唤醒回调中使用串口输出当前RTC时间,按键WK_UP存储当前RTC时间到备份寄存器,按键KEY_2从备份寄存器中读取上次存储的时间,按键KEY_1负责产生入侵事件
3、实验流程
3.0、前提知识
STM32F407的RTC上有两个入侵检测模块,但是笔者使用的LQFP144封装的STM32F407ZGT6只有一个入侵检测模块,只有一个入侵检测模块的STM32F407单片机是利用RTC_AF1(PC13)引脚来进行触发的,和按键外部中断类似,如果设置入侵检测触发为低电平触发,那么当PC13为低电平时就会进入Tampere1事件回调函数,当发生入侵事件时,RTC的20个备份寄存器中的值会全部丢失
由于开发板上PC13引脚并没有按键控制,不方便实现其电平的翻转变化操作,因此本实验需要一根杜邦线,将按键KEY_1所使用的PE3引脚与PC13引脚短接,相当于使用按键KEY_1来间接控制PC13的电平变化,如下图所示,当按键KEY_1松开时,此时PE3/PC13状态应该由外部上/下拉决定,而当按键KEY_1按下时,PE3/PC13的状态应该为低电平,通过设置PC13外部上拉,就可以实现KEY_1按键松开时为高电平,按下为低电平
3.1、CubeMX相关配置
请阅读“STM32CubeMX教程10 RTC 实时时钟 - 周期唤醒、闹钟A/B事件和备份寄存器”实验3.1.1小节配置RCC和SYS
3.1.1、时钟树配置
系统时钟树配置与上一实验一致,均设置为STM32F407总线能达到的最高时钟频率,配置LSE,RTC时钟频率为32.768kHz,具体如下图所示
3.1.2、外设参数配置
本实验需要需要初始化USART1作为输出信息渠道,具体配置步骤请阅读“STM32CubeMX教程9 USART/UART 异步通信”
单击Pinout & Configuration页面左边Timers/RTC,并在页面中间激活日历,周期唤醒WakeUp采用内部模式,勾选入侵检测1将其输入复用到引脚RTC_AF1(PC13),则此后PC13引脚便作为入侵检测引脚,具体配置如下图所示
与上一小节实验类似,需要配置RTC通用参数、日历日期时间、周期唤醒参数和入侵检测参数
① 滤波设置中,如果不滤波则入侵检测的触发方式只能选择边沿触发,而如果选择滤波,则触发方式只能选择电平触发,这里由于使用的机械按键存在抖动,因此对输入滤波
② 入侵引脚是否上拉设置中,如上述3.0小节所述,我们需要PE3/PC13外部上拉才能实现目标,因此此处选择上拉
③ 保存了入侵时间戳就可以在Tampere1事件回调函数中使用HAL_RTCEx_GetTimeStamp获取入侵时间戳
④ 入侵检测触发方式设置中,由于按键按下为低电平,因此这里选择低电平
3.1.3、外设中断配置
在Pinout & Configuration页面左边System Core/NVIC中勾选入侵检测及周期唤醒中断,然后选择合适的中断优先级即可
3.2、生成代码
请先阅读“STM32CubeMX教程1 工程建立”实验3.4.3小节配置Project Manager
单击页面右上角GENERATE CODE生成工程
3.2.1、外设初始化调用流程
与上一小节RTC初始化函数MX_RTC_Init对比,可以发现本小节的初始化函数中减少了闹钟A/B的初始化,但是新增加了入侵检测的初始化,如下图所示,也即我们在CubeMX中设置的参数,类似的中断相关的初始化设置仍然在HAL_RTC_MspInit函数中
3.2.2、外设中断调用流程
在CubeMX中勾选RTC入侵检测启动中断后,在stm32f4xx_it.c中均会生成对应的中断服务函数TAMP_STAMP_IRQHandler()
在该TAMP_STAMP_IRQHandler()中断服务函数中调用了HAL库HAL_RTCEx_TamperTimeStampIRQHandler()函数统一处理时间戳/入侵事件
最终根据发生的事件来源调用了时间戳事件回调函数HAL_RTCEx_TimeStampEventCallback()、入侵检测1事件回调函数HAL_RTCEx_Tamper1EventCallback()和入侵检测2事件HAL_RTCEx_Tamper2EventCallback()
具体流程如下图所示
3.2.3、添加其他必要代码
由于无入侵检测2,笔者这里只实现了入侵检测1事件回调函数HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc),将其实现在了rtc.c中,另外周期唤醒回调函数内容与上一小结内容一致,这里不再赘述,入侵检测1事件回调函数具体代码如下图所示
源代码如下
/*Tampere1事件回调函数*/
void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
if(HAL_RTCEx_GetTimeStamp(hrtc, &sTime, &sDate, RTC_FORMAT_BIN) == HAL_OK)
{
char str[24];
sprintf(str,"TimeStamp = %2d:%2d:%2d\r\n",sTime.Hours,sTime.Minutes,sTime.Seconds);
printf("Tampere1 Event Happend, %s", str);
}
HAL_GPIO_TogglePin(GREEN_LED_GPIO_Port,GREEN_LED_Pin);
}
经过了上述的过程之后目前还缺少两个操作,利用按键WK_UP存储当前RTC时间到备份寄存器,按键KEY_2从备份寄存器中读取上次存储的时间,其代码实现在了主函数主循环中,简单采用轮询的方式处理按键,如下图所示
源代码如下
/*按下WK_UP按键将当前时间存储到备份寄存器*/
if(HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin) == GPIO_PIN_SET)
{
HAL_Delay(50);
if(HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin) == GPIO_PIN_SET)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
if(HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN) == HAL_OK)
{
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR2, sTime.Hours);
HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR3, sTime.Minutes);
HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR4, sTime.Seconds);
char timeStr[30];
sprintf(timeStr,"%2d:%2d:%2d",sTime.Hours,sTime.Minutes,sTime.Seconds);
printf("Store %s to the backup register\r\n", timeStr);
while(HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin));
}
}
}
/*按下KEY2按键将存储到备份寄存器的时间利用串口输出*/
if(HAL_GPIO_ReadPin(KEY_2_GPIO_Port,KEY_2_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(50);
if(HAL_GPIO_ReadPin(KEY_2_GPIO_Port,KEY_2_Pin) == GPIO_PIN_RESET)
{
uint32_t sHour,sMinute,sSecond;
sHour = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2); //Hour
sMinute = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3); //Minute
sSecond = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4); //Second
char timeStr[30];
sprintf(timeStr,"%u:%u:%u",sHour,sMinute,sSecond);
printf("Read out %s from the backup register\r\n", timeStr);
while(!HAL_GPIO_ReadPin(KEY_2_GPIO_Port,KEY_2_Pin));
}
}
4、常用函数
/*时间戳回调函数*/
void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc)
/*Tampere1事件回调函数*/
void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc)
/*Tampere2事件回调函数*/
void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc)
/*获取RTC时间戳*/
HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTimeStamp, RTC_DateTypeDef *sTimeStampDate, uint32_t Format)
5、烧录验证
5.1、具体步骤
“RTC Mode and Configuration中启用内部模式的WakeUp周期唤醒 -> 勾选入侵检测Tamper1 Routed to AF1 -> 配置合适的日历通用参数、日历日期时间、周期唤醒参数和入侵检测参数 -> NVIC中勾选RTC周期唤醒中断及RTC入侵检测中断,并选择合适的中断优先级 -> 在生成的工程代码中重新实现周期唤醒回调函数、Tampere1事件回调函数HAL_RTCEx_Tamper1EventCallback -> 添加必要的代码逻辑(具体看上述3.2)”
5.2、实验现象
烧录程序,利用杜邦线短接PE3和PC13,当开发板上电后,会在周期唤醒回调函数中不断地输出当前RTC的时间,另外开发板上的红色LED灯也会不断地闪烁,当按下开发板上的WK_UP按键之后会将当前RTC日历的时间存储到备份寄存器RTC_BKP_DR2~4中,按下开发板上的KEY_2按键可以从备份寄存器中将上次存储的时间读出来
然后当按下按键KEY_1的时候,会发生入侵事件,此时入侵被检测到,会触发Tampere1事件回调函数通过串口输出入侵事件的信息,并且如果再去通过KEY_2按键读取备份寄存器中存储的时间会发现由于入侵的发生,备份寄存器中的值已经被清空
上述整个流程串口输出信息如下图所示
6、奇怪的现象
有时候会出现写备份寄存器写不进去的情况,如果你也遇到了,可以尝试将开发板完全断电(电源线、USB串口和调试器接口),然后重新上电复位再向备份寄存器中写入试试
参考资料
更多内容请浏览 OSnotes的CSDN博客
STM32CubeMX教程11 RTC 实时时钟 - 入侵检测和时间戳的更多相关文章
- 第43章 RTC—实时时钟
第43章 RTC—实时时钟 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fireg ...
- 第43章 RTC—实时时钟—零死角玩转STM32-F429系列
第43章 RTC—实时时钟 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fireg ...
- 教你在树莓派使用上RTC实时时钟,不用再担心断电后时间归零的问题,开机后自动同步RTC时钟!!!
准备工作:1.系统建议使用官方最新的镜像文件 2.RTC时钟模块板(I2C接口)建议使用DS1307时钟模块,或者RTC时钟模块RTC时钟模块: 大家知道arduino的电平是5V,树莓派是3.3V, ...
- stm32——RTC实时时钟
stm32——RTC实时时钟 一.关于时间 2038年问题 在计算机应用上,2038年问题可能会导致某些软件在2038年无法正常工作.所有使用UNIX时间表示时间的程序都将将受其影响,因为它们以自19 ...
- RTC实时时钟驱动
RTC(Real-Time Clock)实时时钟为操作系统提供了一个可靠的时间,并且在断电的情况下,RTC实时时钟也可以通过电池供电,一直运行下去. RTC通过STRB/LDRB这两个ARM指令向CP ...
- RTC实时时钟
作者:宋老师,华清远见嵌入式学院讲师. 1.1 RTC介绍 在 一个嵌入式系统中,通常采用RTC 来提供可靠的系统时间,包括时分秒和年月日等,而且要求在系统处于关机状态下它也能够正常工作(通常采用后备 ...
- stm32 rtc 实时时钟
STM32的实时时钟是一个独立的定时器 通常会在后备区域供电端加一个纽扣电池,当主电源没有电的时,RTC不会停止工作 若VDD电源有效,RTC可以触发秒中断.溢出中断和闹钟中断 备份寄存器BKP 备份 ...
- RTC实时时钟-备份区域BKP--原理讲解
RTC(Real Time Clock):实时时钟 BCD码:用4位2进制来表示10以内的十进制的形式. RTC的时钟源:LSE(32.768KHZ).HSE_RTC.LSI.经过一个精密校准(RTC ...
- 【iCore3 双核心板】例程十:RTC实时时钟实验——显示日期和时间
实验指导书及代码包下载: http://pan.baidu.com/s/1jHuZcnc iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...
- 【iCore4 双核心板_ARM】例程十:RTC实时时钟实验——显示时间和日期
实验现象: 核心代码: int main(void) { /* USER CODE BEGIN 1 */ RTC_TimeTypeDef sTime; RTC_DateTypeDef sDate; ; ...
随机推荐
- SQL运用full join连接,decode函数,nvl函数进行列转行
背景说明:full join连接,decode函数,nvl函数,结合生产背景理解更深刻: test_A表是现金业主某时间段的收益:test_B表是非现金业主某时间段的收益:对于业主,test_A表与t ...
- .Net7自定义GC垃圾回收器
1.前言 CLR和GC高度耦合,.Net7里面分离CLR和GC,则比较容易实现这件事情.本篇来看下,自定义一个GC垃圾回收器. 2.概述 这里首先演示下自定义GC垃圾回收后的效果. 1.下载Custo ...
- Matlab 设计仿真CIC滤波器
2023.09.26 使用CIC滤波器用于降采样.同样的,CIC滤波器也适用于升采样. 参考连接: [1] Matlab中CIC滤波器的应用_dsp.cicdecimator_张海军2013的博客-C ...
- WPF 中引入依赖注入(.NET 通用主机)
WPF 中引入依赖注入(.NET 通用主机) 在网上看到的文章都是通过 App.cs 中修改配置进行的,这样侵入性很高而且服务主机是通过 App 启动时加载的而不是服务主机加载的 App 有一点违反原 ...
- [NISACTF 2022]level-up
[NISACTF 2022]level-up 查看源码,根据这个提示就可以反应出是需要去访问robots.txt这个文件 访问level_2_1s_h3re.php进入第二关 需要post进去arra ...
- 再学Blazor——扩展方法
上篇提到 Blazor 组件的高级写法,是采用扩展方法对 HTML 元素和组件进行扩展,以便于书写组件结构和代码阅读.本篇主要介绍扩展方法实现的思路. 什么是扩展方法 要扩展哪个类 扩展方法的实现 1 ...
- Python使用pymysql和xlrd2将Excel数据导入MySQL数据库
在数据处理和管理中,有时候需要将Excel文件中的数据导入到MySQL数据库中进行进一步的分析和操作.本文将介绍如何使用Python编程语言实现这个过程. 导入所需库 import xlrd2 # 导 ...
- 手撕Vuex-模块化共享数据上
前言 好,经过上一篇的介绍,实现了 Vuex 当中的 actions 方法,接下来我们来实现 Vuex 当中的模块化共享数据(modules). modules 方法用于模块化共享数据,那么什么叫模块 ...
- MongoDB 6.0 单实例基于用户角色实现授权登录
现代数据库系统能够存储和处理大量数据.因此,由任何一个用户单独负责处理与管理数据库相关的所有活动的情况相对较少.通常,不同的数据库用户需要对数据库的某些部分具有不同级别的访问权限:某些用户可能只需要读 ...
- 【漏洞分析】Reflection Token 反射型代币攻击事件通用分析思路
在本篇文章中,我将通过一个攻击事件引出 Reflection Token 攻击事件的一个通用分析思路. 关于 Reflection Token 的其他案例分析,可以参考BEVO代币攻击事件分析及复现一 ...