ARM嵌入式学习--第十二天(WDOG,RTC)

ops/2025/2/4 1:09:48/

--WDOG

-介绍

    WatchDog是为了能够防止程序跑飞而使用的一种硬件模块,如果你的程序没有跑飞,那么你的程序会定时的去喂看门狗;如果你的程序跑飞了,那么就不会再去喂狗了,如果超过了喂狗时间,那么狗就会自己生成一个信号来重新reset你的CPU让程序重新开始。这是一种在很重要的情况下防止系统跑飞的一种方式

-编程思路

   1.设置复位信号产生后以冷启动方式复位

    2.关闭看门狗控制器

    3.设置看门狗定时器定时时间

    4.使能看门狗

    5.进行喂狗服务,重置看门狗定时器

    6.不喂狗看门狗定时器超时,产生复位信号,复位开发板

--RTC

-介绍

    实时时钟的缩写是RTCReal_Time Clock).RTC是集成电路,通常称为时钟芯片

    实时时钟芯片是日常生活中应用最广泛的消费类电子产品之一。它为人们提供精确的实际时间,或者为电子系统提供精确的时间基准,实时时钟芯片大多数采用精度较高的晶体振荡器作为时钟源。有些时钟芯片为了在主电源掉电时,还可以工作,需要外加电池供电

为什么我们需要一个单独的RTC?

    答:原因是CPU的定时器时钟功能只在通电时运行,断电时停止,当然,如果时钟不能连续跟踪时间,则必须手动设置时间,如今,通过接收标准电波(传输各国标准时间的电波)来自动调整时间手表越来越多,但它是一种不应该在室内携带的电子设备

    RTC有一个与CPU单独分离的电源,如纽扣电池(备用电池),即使主机电源关闭,它也保持滴答作响随时可以实时显示时间。然后,当计算机再次打开时,计算机内置的定时器时钟从RTC读取当前时间,并在此基础上供电的同时,时间在其自身机制下显示

    同时RTC单元外接32.768KHZ晶振,具有定时报警功能

-编程思路

    1.设置寄存器访问不受限制

    2.使能SNVS时钟

    3.停止RTC计数器,等待RTC计数器停止成功

    4.设置日期

    5.开启RTC计数器,等待RTC计数器开启成功

    6.每隔一秒读取RTC数据,然后输出

-代码实现

rtc_datetime.h

stdint.h( /usr/include )
#ifndef __DATETIME_HEAD_H__
#define __DATETIME_HEAD_H__
#include <stdint.h>
/*stdint.h头文件中定义了int16_t、uint32_t、int64_t等整型,在
需要确定大小的整型时可以使用它们代替short、unsigned long long
等*/
#define SECONDS_IN_A_DAY (86400U)
#define SECONDS_IN_A_HOUR (3600U)
#define SECONDS_IN_A_MINUTE (60U)
#define DAYS_IN_A_YEAR (365U)
#define YEAR_RANGE_START (1970U)
/*! @brief Structure is used to hold the date and time */
typedef struct rtc_datetime
{
uint_fast16_t year; /*!< Range from 1970.*/
uint_fast16_t month; /*!< Range from 1 to 12.*/
uint_fast16_t day; /*!< Range from 1 to 31
(depending on month).*/
uint_fast16_t hour; /*!< Range from 0 to 23.*/
uint_fast16_t minute; /*!< Range from 0 to 59.*/
uint_fast16_t second; /*!< Range from 0 to 59.*/
}rtc_datetime_t;
extern uint_fast32_t convert_datetime_to_seconds(const
rtc_datetime_t *datetime);
extern void convert_seconds_to_datetime(uint_fast32_t
seconds, rtc_datetime_t *datetime);
#endif
rtc_datetime.c
#include "rtc_datetime.h"
uint_fast32_t convert_datetime_to_seconds(const
rtc_datetime_t *datetime)
{
/* Number of days from begin of the non Leap-year*/
uint_fast16_t monthDays[] = {0U, 31U, 59U, 90U,
120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
uint_fast32_t seconds;
/* Compute number of days from 1970 till given
year*/
seconds = (datetime->year - 1970U) * DAYS_IN_A_YEAR;
/* Add leap year days */
seconds += ((datetime->year / 4) - (1970U / 4));
/* Add number of days till given month*/
seconds += monthDays[datetime->month-1];
/* Add days in given month. We subtract the current
day as it is
* represented in the hours, minutes and seconds
field*/
seconds += (datetime->day - 1);
// 前面计算出共多少天
/* For leap year if month less than or equal to
Febraury, decrement day counter*/
if ((!(datetime->year & 3U)) && (datetime->month <=
2U))
{
seconds--;
}
seconds = (seconds * SECONDS_IN_A_DAY) + (datetime-
>hour * SECONDS_IN_A_HOUR) +
(datetime->minute *
SECONDS_IN_A_MINUTE) + datetime->second;
return seconds;
} v
oid convert_seconds_to_datetime(uint_fast32_t seconds,
rtc_datetime_t *datetime)
{
uint_fast32_t x;
uint_fast32_t secondsRemaining, days;
uint_fast16_t daysInYear;
/* Table of days in a month for a non leap year.
First entry in the table is not used,
* valid months start from 1
*/
uint_fast8_t daysPerMonth[] = {31U, 28U, 31U, 30U,
31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
/* Start with the seconds value that is passed in to
be converted to
date time format*/
secondsRemaining = seconds;
/* Calcuate the number of days, we add 1 for the
current day which is represented in
the hours and seconds field
*/
days = secondsRemaining / SECONDS_IN_A_DAY + 1;
/* Update seconds left*/
secondsRemaining = secondsRemaining %
SECONDS_IN_A_DAY;
/* Calculate the datetime hour, minute and second
fields */
datetime->hour = secondsRemaining /
SECONDS_IN_A_HOUR;
secondsRemaining = secondsRemaining %
SECONDS_IN_A_HOUR;
datetime->minute = secondsRemaining /
SECONDS_IN_A_MINUTE;
datetime->second = secondsRemaining %
SECONDS_IN_A_MINUTE;
/* Calculate year */
daysInYear = DAYS_IN_A_YEAR;
datetime->year = YEAR_RANGE_START;// 默认从1970年开始
while (days > daysInYear)
{
/* Decrease day count by a year and increment
year by 1 */
days -= daysInYear;
datetime->year++;
/* Adjust the number of days for a leap year */
if (datetime->year & 3U)
{
daysInYear = DAYS_IN_A_YEAR;
}
else
{
daysInYear = DAYS_IN_A_YEAR + 1;
}
}
/* Adjust the days in February for a leap year */
if (!(datetime->year & 3U))
{
daysPerMonth[1] = 29U;
}
for (x = 1U; x <= 12U; x++)
{
if (days <= daysPerMonth[x-1])
{
datetime->month = x;
break;
}
else
{
days -= daysPerMonth[x-1];
}
}
datetime->day = days;
return;
rtc.c
#include "rtc.h"
// RTC_EN = 0
void disable_rtc_counter(){
SNVS->HPCR &=~(0x1 << 0);
while((SNVS->HPCR & 1));
} /
/ RTC_EN = 1
void enable_rtc_counter(){
SNVS->HPCR |=(0x1<<0);
while(!(SNVS->HPCR & 1));
} v
oid rtc_set_datetime(const rtc_datetime_t* p_curtime){
// 停止RTC计数器,等待RTC计数器停止成功
disable_rtc_counter();
uint_fast32_t seconds;
seconds = convert_datetime_to_seconds(p_curtime);
// [14:0]存放高15位
SNVS->HPRTCMR = seconds >> 17;
// [31:15]存放低17位
SNVS->HPRTCLR = seconds << 15;
// 开启RTC计数器,等待RTC计数器开启成功
enable_rtc_counter();
} /
/ 获取时间
void rtc_get_datetime(rtc_datetime_t* p_curtime){
uint_fast32_t seconds = 0;
uint_fast32_t compareVal = 0;
do{
compareVal = seconds;
seconds = (SNVS->HPRTCMR << 17) | (SNVS-
>HPRTCLR >> 15);
}while(compareVal!=seconds);
convert_seconds_to_datetime(seconds, p_curtime);
} v
oid rtc_init(){
/*
设置寄存器访问不受权限限制
any software can access the privileged registers.
*/
SNVS->HPCOMR |=(0x1 << 31);
/*
使能SNVS时钟
*/
CCM_CCGR5 |=(0x3 << 18);
}
void rtc_test(){
rtc_init();
rtc_datetime_t curtime;
curtime.year = 2024;
curtime.month = 9;
curtime.day = 25;
curtime.hour = 10;
curtime.minute = 35;
curtime.second = 40;
rtc_set_datetime(&curtime);
while(1){
rtc_get_datetime(&curtime);
uart_printf("%d-%d-%d
%d:%d:%d\r\n",curtime.year,curtime.month,curtime.day,curtim
e.hour,curtime.minute,curtime.second);
gpt_delay_seconds(1); // 延迟1秒
}
}

--Alarm中断

-编程思路

    1.注册RTC中断

    2.设置RTC alarm日期

        1>Disable RTC alarm

        2>设置日期

        3>Enable RTC alarm

    3.在中断处理函数判断是否时RTC alarm中断,如果时则输出信息提醒闹钟时间到达

    4.在中断处理函数中清除RTC alarm中断标志,写1清0


http://www.ppmy.cn/ops/155436.html

相关文章

蓝牙技术在物联网中的应用有哪些

蓝牙技术凭借低功耗、低成本和易于部署的特性&#xff0c;在物联网领域广泛应用&#xff0c;推动了智能家居、工业、医疗、农业等多领域发展。 智能家居&#xff1a;在智能家居系统里&#xff0c;蓝牙技术连接各类设备&#xff0c;像智能门锁、智能灯泡、智能插座、智能窗帘等。…

浏览器同源策略:从“源”到安全限制的全面解析

一、什么是“源”&#xff08;Origin&#xff09;&#xff1f; 在浏览器中&#xff0c;“源”是 Web 安全的核心概念。一个“源”由三部分组成&#xff1a; 协议&#xff08;Protocol&#xff09;&#xff1a;如 http://、https://、ftp:// 域名&#xff08;Host&#xff09;…

[EAI-028] Diffusion-VLA,能够进行多模态推理和机器人动作预测的VLA模型

Paper Card 论文标题&#xff1a;Diffusion-VLA: Scaling Robot Foundation Models via Unified Diffusion and Autoregression 论文作者&#xff1a;Junjie Wen, Minjie Zhu, Yichen Zhu, Zhibin Tang, Jinming Li, Zhongyi Zhou, Chengmeng Li, Xiaoyu Liu, Yaxin Peng, Chao…

Linux的循环,bash的循环

Linux的循环,bash的循环 在 Linux 系统中&#xff0c;Bash 循环是最常用的循环实现方式&#xff08;Bash 是 Linux 默认的 Shell&#xff09;&#xff0c;但广义上“Linux 的循环”可能涉及其他 Shell 或编程语言的循环结构。以下是 Bash 循环的详细解析及其在 Linux 环境中的…

vscode和pycharm的区别

VSCode&#xff08;Visual Studio Code&#xff09;和 PyCharm 是两款常用的 Python 开发工具&#xff0c;它们在功能和使用体验上有一些关键区别&#xff1a; 1. 核心定位 VSCode&#xff1a;轻量级、多语言支持的代码编辑器&#xff0c;依靠插件扩展 Python 开发能力。PyCh…

it基础使用--5---git远程仓库

文章目录 it基础使用--5---git远程仓库1. 按顺序看2. 什么是远程仓库3. Gitee操作3.1 新建远程仓库3.2 远程操作基础命令3.3 查看当前所有远程地址别名 git remote -v3.4 创建远程仓库别名 git remote add 别名 远程地址3.4 推送本地分支到远程仓库 git push 别名 分支3.5 拉取…

【开源免费】基于SpringBoot+Vue.JS体育馆管理系统(JAVA毕业设计)

本文项目编号 T 165 &#xff0c;文末自助获取源码 \color{red}{T165&#xff0c;文末自助获取源码} T165&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

UE学习日志#19 C++笔记#5 基础复习5 引用1

C中的引用&#xff08;reference&#xff09;是另一个变量的别名。对引用的所有修改都会更改其引用的变量的值。可以将引用视为隐式指针&#xff0c;它省去了获取变量地址和解引用指针的麻烦。另外&#xff0c;可以将引用视为原始变量的另一个名称。可以创建独立的引用变量&…