细说STM32F407单片机RTC入侵检测和时间戳的原理及使用方法
目录
一、入侵检测的功能
二、示例功能
三、项目设置
1、晶振、DEBUG、CodeGenerator、USART6、KEYLED
2、RTC
(1)设置RTC的模式。
(2)General、Time、Date\Wake Up分组
(3)Tamper分组
1)Filter,滤波
2)Sampling Frequency,输入引脚RTC_AF1的采样频率
3)Precharge Duration,预充电时间
4)Tamper Pull Up,是否对输入引脚使用内部上拉
5)Time Stamp On Tamper Detection,是否保存时间戳
6)Tamper 1 Trigger,有效触发事件类型
3、NVIC
4、GPIO
四、软件设计
1、keyled.c、keyled.h
2、main.h
3、main.c
五、运行调试
本文将通过示例介绍 STM32单片机RTC时钟单元的的入侵检测和时间戳的原理及使用方法。本文将继续使用旺宝红龙开发板STM32F407ZGT6 KIT V1.0。本实例将引用本文作者写的其他文章作为参考文献。
参考文章1:细说STM32F407单片机RTC的基本原理及闹钟和周期唤醒功能的使用方法-CSDN博客 https://wenchm.blog.csdn.net/article/details/145575366
参考文章2:细说STM32F407单片机RTC的备份寄存器原理及使用方法-CSDN博客 https://wenchm.blog.csdn.net/article/details/145593205
一、入侵检测的功能
入侵检测和时间戳的HAL驱动程序头文件是stm32f4xx_hal_rtc_ex.h。RTC上有两个入侵检测模块,用Tamper1和Tamper2表示。当发生入侵事件时,如果开启了时间戳功能,就会记录时间戳数据,所以入侵检测通常是和时间戳一起使用的。
常用的入侵检测和时间戳HAL函数如下表所示,其他函数见文件stm32f4xx_hal_rtc_ex.h中的定义。入侵检测和时间戳共用一个中断号,3个中断事件对应表中的3个回调函数。
函数名 | 功能 |
__HAL_RTC_TAMPER1_DISABLE() | 禁用Tamper1 |
__HAL_RTC_TAMPER1_ENABLE() | 启用Tamper1 |
__HAL_RTC_TAMPER2_DISABLE() | 禁用Tamper2 |
__HAL_RTC_TAMPER2_ENABLE() | 启用Tamper2 |
__HAL_RTC_TIMESTAMP_DISABLE() | 禁用时间戳外设 |
__HAL_RTC_TIMESTAMP_ENABLE() | 启用时间戳外设 |
__HAL_RTC_TIMESTAMP_DISABLE_IT() | 禁止时间戳事件产生硬件中断,时间戳中断事件类型是RTC_IT_TS |
__HAL_RTC_TIMESTAMP_ENABLE_IT() | 允许时间戳事件产生硬件中断,时间戳中断事件类型是RTC_IT_TS |
HAL_RTCEx_GetTimeStamp() | 读取时间戳的数据 |
HAL_RTCEx_Tamper1EventCallback() | Tamper1的中断事件回调函数 |
HAL_RTCEx_Tamper2EventCallback() | Tamper2的中断事件回调函数 |
HAL_RTCEx_TimeStampEventCallback() | 时间戳中断事件回调函数 |
发生入侵事件时,RTC的20个备份寄存器的内容会被清零,时间戳寄存器保存发生入侵事件时的时间。用函数HAL_RTCEx_GetTimeStamp()可以读取出保存的时间戳数据,其函数原型如下:
HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc,RTC_TimeTypeDef*TimeStamp,RTC_DateTypeDef *sTimeStampDate,uint32_t Format);
其中,参数sTimeStamp返回时间数据的指针,sTimeStampDate返回日期数据的指针,Format省定二进制或BCD码格式。
二、示例功能
将复用引脚RTC_AF1(即引脚PC13)作为Tamper1输入引脚,在输入引脚发生边沿事件(无滤波时是边沿事件)或所需电平(有输入滤波时是电平检测)时,触发入侵事件中断,并自动将RTC的20个备份寄存器复位,自动记录入侵事件发生时刻的时间戳数据。
使用开发板上的按键制造入侵事件,用杜邦线连接引PC13和PF6。PC13是RTC的复用引脚RTC_AF1,PF6是KeyRight按键接入MCU的引脚。设置PC13内部上拉,KeyRight按下后是低电平,入侵检测设置为低电平有效,那么按建KeyRight按下后就会产生入侵事件。在实际调试中,要注意按建抖动的影响。
本文示例用于测试入侵检测功能。
- 采用1s周期的唤醒中断,在唤醒中断里读取RTC时间后显示。
- 可将RTC当前时间保存到备份寄存器。
- 可以读取备份寄存器中保存的时间数据并显示。
- 按下KeyRight键时产生入侵事件,看备份寄存器内容是否被复位。
- 菜单设计:
//菜单设计
[S2]KeyUp = Save time to BKUP //LED2 ON.
[S3]KeyDown = Read BKUP registers //LED3 ON.
[S5]KeyRight= Trigger tamper event //LED1 Flashing.
三、项目设置
1、晶振、DEBUG、CodeGenerator、USART6、KEYLED
与参考文章2相同。
2、RTC
(1)设置RTC的模式。
禁用闹钟A和闹钟B,启用Tamper1,并且使用复用引脚RTC_AF1作为入侵事件输入引脚。启用周期唤醒功能,设置为Internal WakeUp。
(2)General、Time、Date\Wake Up分组
参数设置和参考项目2的示例相同。
(3)Tamper分组
1)Filter,滤波
当选择为Disable时,禁用滤波。禁用滤波时,下面的Tamper 1 Trigger参数只能是边沿触发。使用滤波时,Tamper 1 Trigger只能是电平触发。
如果使用滤波,可选项为Tamper activated after 2 consecutive samples、Tamper activated after 4 consecutive samples和Tamper activated after 8 consecutive samples,即经过2、4或8个连续采样都是所设置的触发电平时,才确认产生入侵事件。带滤波的方式适用于按键抖动时的检测,相当于有一定的消抖作用。
2)Sampling Frequency,输入引脚RTC_AF1的采样频率
采样频率设置为RCCCLK的分频,分频系数为32768~256,且只能是2N。例如,当RCCCLK是32.768kHz时,分频系数设置为512,则采样频率为64Hz。又将滤波参数设置为连续4个采样信号有效,则需要电平持续时间为4/64s,即62.5ms。这个时间差不多是按键按下或释放时的抖动阶段时间,所以有一定的消除按键抖动影响的作用。
3)Precharge Duration,预充电时间
可选择为1、2、4或8个RTCCLK周期,这是每次采样之前激活上拉的持续时间。
4)Tamper Pull Up,是否对输入引脚使用内部上拉
可选Enable或Disable。因为按键输入是低有效,所以需要设置为上拉。
5)Time Stamp On Tamper Detection,是否保存时间戳
设置在发生入侵事件时是否保存时间戳数据,这里设置为保存,即Time Stamp on Tamper Detection event saved。
6)Tamper 1 Trigger,有效触发事件类型
当Filter参数设置为Disable时,有效事件为边沿触发,可选项为Rising Edge(上跳沿)和Falling Edge(下跳沿)。当Filter参数设置为Enable时,使用滤波,有效事件为电平触发,可选项为Low Level(低电平)和High Level(高电平)。本示例使用了滤波,且按键按下时输入是低电平,所以选择Low Level。
3、NVIC
启用RTC入侵检测和时间戳中断,启用RTC周期唤醒中断。在NVIC组件中将这两个中断的抢占优先级都设置为1。将这两个中断的抢占优先级设置为相同的,是为了避免它们之间发生抢占,导致串口显示出现混乱。
4、GPIO
本示例要用到3个按键,将与KeyRight连接的GPIO引脚PF6复位成原始状态,其他按键和LED的GPIO设置与参考文章2相同。
四、软件设计
1、keyled.c、keyled.h
与参考文章2相同。
2、main.h
/* USER CODE BEGIN Private defines */
void RTC_SaveToBKUP();
void RTC_ReadBKUP();
/* USER CODE END Private defines */
3、main.c
/* USER CODE BEGIN Includes */
#include "keyled.h"
#include <stdio.h>
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
uint8_t RTC_isReading=0;
/* USER CODE END PV */
/* USER CODE BEGIN 2 */__HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc); //禁止RTC周期唤醒printf("Demo11_3_RTC_Tamper:RTC tamper and timestamp.\r\n");printf("Please connect PF6 and PC13 by line.\r\n");printf("KeyRight simulate tamper event.\r\n\r\n");/* USER CODE END 2 */
/* Infinite loop *//* USER CODE BEGIN WHILE *///菜单设计printf("[S2]KeyUp = Save time to BKUP,LED2 ON.\r\n");printf("[S3]KeyDown = Read BKUP registers,LED3 ON.\r\n");printf("[S5]KeyRight= Trigger tamper event,LED1 Flashing.\r\n\r\n");__HAL_RTC_WAKEUPTIMER_ENABLE(&hrtc); //启用RTC周期唤醒while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */KEYS curKey=ScanPressedKey(KEY_WAIT_ALWAYS);switch(curKey){case KEY_UP: //[S2]KeyUp = Save time to BKUPRTC_SaveToBKUP();break;case KEY_DOWN: //[S3]KeyDown = Read BKUP registersRTC_ReadBKUP();break;default:break;}HAL_Delay(300); //消除按键后抖动的影响}/* USER CODE END 3 */
在main()函数里,执行MX_RTC_Init()后立刻执行__HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc)禁止了RTC周期唤醒功能,在进入while循环之前,重新开启了RTC周期唤醒功能。
while循环里检测按键并执行响应代码。只有KeyUp键和KeyDown键是执行菜单选项,KeyRight用于产生RTC入侵事件。KeyUp键按下时,调用函数RTC_SaveToBKUP(),用于将RTC当前时间写入备份寄存器;KeyDown键按下时,调用函数RTC_ReadBKUP(),用于读取备份寄存器中的数据并在串口助手上显示。这两个按键的功能是测试入侵事件发生后备份寄存器的内容是否被复位。
/* USER CODE BEGIN 4 */
//周期唤醒中断回调函数
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{LED1_Toggle();RTC_isReading=1;if (HAL_RTC_GetTime(hrtc,&sTime,RTC_FORMAT_BIN) == HAL_OK){//调用HAL_RTC_GetTime()之后必须调用HAL_RTC_GetDate()以解锁数据,才能连续更新日期和时间HAL_RTC_GetDate(hrtc,&sDate,RTC_FORMAT_BIN);RTC_isReading=0;//显示时间hh:mm:sschar str[40];sprintf(str,"RTC WakeUp Time = %2d:%2d:%2d",sTime.Hours,sTime.Minutes,sTime.Seconds);printf(" %s\r\n",str);}
}/* 入侵和时间戳事件回调函数 */
void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc)
{printf("Tamper1 is triggered and all BKUP-Regs are cleared.\r\n");RTC_TimeTypeDef time;RTC_DateTypeDef date;if (HAL_RTCEx_GetTimeStamp(hrtc,&time,&date,RTC_FORMAT_BIN) == HAL_OK){//显示时间hh:mm:sschar str[40];sprintf(str,"RTC Tamper1 Time = %2d:%2d:%2d",sTime.Hours,sTime.Minutes,sTime.Seconds);printf(" %s\r\n",str);}
}/* 保存RTC时间到备份寄存器 */
void RTC_SaveToBKUP()
{LED2_ON();while(RTC_isReading)HAL_Delay(1);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); //转换为字符串,自动添加"\0"printf("Time %s is saved in BKUP.\r\n",timeStr);HAL_Delay(5000);LED2_OFF();
}void RTC_ReadBKUP()
{LED3_ON();uint32_t regValue;char regStr[40];regValue=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2); //Hoursprintf(regStr,"Saved time(Hour) ,BKP_DR2= %lu",regValue);printf(" %s\r\n",regStr);regValue=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3); //Minutesprintf(regStr,"Saved time(Min) , BKP_DR3= %lu",regValue);printf(" %s\r\n",regStr);regValue=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4); //Secondsprintf(regStr,"Saved time(Sec) , BKP_DR4= %lu",regValue);printf(" %s\r\n",regStr);HAL_Delay(5000);LED3_OFF();
}//串口打印
int __io_putchar(int ch)
{HAL_UART_Transmit(&huart6,(uint8_t*)&ch,1,0xFFFF);return ch;
}
/* USER CODE END 4 */
Tamper1事件中断回调函数的主要功能就是调用函数HAL_RTCEx_GetTimeStamp()读取时间戳数据,然后在串口助手上显示这个时间。程序运行时,按下KeyRight键就会触发入侵事件,并在串口助手上显示相应的的信息。
五、运行调试
首次下载或S6键复位后,在串口助手上显示功能菜单。
正常情况下不按任何键,连续显示中断唤醒RTC时间,1秒1次。当按下S5键,切换显示入侵RTC时间。 然后恢复显示中断唤醒RTC时间。LED1闪烁。
按S2键,存储当前RTC时间到备份寄存器,LED2亮;按S3键,读取备份寄存器RTC时间,LED3亮。