38. RTC实验
一、RTC原理详解
1、6U内部自带到了一个RTC外设,确切的说是SRTC。6U和6ULL的RTC内容在SNVS章节。6U的RTC分为LP和HP。LP叫做SRTC,HP是RTC,但是HP的RTC掉电以后数据就丢失了,即使用了纽扣电池也没用。所以必须要使用LP,也就是SRTC。
SNVS章节有些是跟加密有关的,需要与NXP签订NDA协议才可以拿到。
RTC分为SNVS_LP和SNVS_HP,
如果做产品,建议使用外置RTC芯片,PCF8563。
RTC很类似定时器,外接32.768KHz的晶振,然后就开始计时,RTC使用两个寄存器来保存计数值。
RTC使用很简单,打开RTC,然后RTC就开始工作,我们要做的就是不断地读取RTC计数寄存器,获取时间值,或者向RTC计数器写入时间值,也就是调整时间。
SNVS_HPCOMR的bit31置1,表示所有的软件都可以访问SNVS所有寄存器。Bit8也是和安全有关的,我们置1,也可以不置1.
SNVS_LPCR寄存器,bit0置1,开始SRTC功能。
SNVS_LPSRTCMR的bit14:0为RTC计数寄存器的高15位
SNVS_LPSRTCLR是低32为RTC计数器,与LPSRTCMR共同组成了SRTC计数器,,每1秒数据加1。
6U的RTC模式从1970年1月1日0时0点0分0秒。
二、时间乱码的问题
1、问题
当我们按照6U的参考手册编写代码,读取SRTC的LPSRTCMR和LPSRTCLR获取时间值的时候,发现按照手册的说法,时间是错误的。
手册上写的:LPSRTCMR是SRTC的高15bit。LPSRTCLR寄存器是SRTC的低32位。RTC计数器是47bit。
2、问题解决方法
LPSRTCMR作为SRTC计数器的高15位,但是LPSRTCLR寄存器bit31:15作为SRTC计数器的低17位。相当于SRTC的计数器是个32位的。不是47位!
三、代码
参考:7、I.MX6U参考资料\3、I.MX6ULL SDK包\devices\MCIMX6Y2\drivers
//bsp_rtc.c
#include "bsp_rtc.h"
#include "stdio.h"/* * 描述:初始化RTC*/
void rtc_init(void)
{/** 设置HPCOMR寄存器* bit[31] 1 : 允许访问SNVS寄存器,一定要置1* bit[8] 1 : 此位置1,需要签署NDA协议才能看到此位的详细说明,* 这里不置1也没问题*/SNVS->HPCOMR |= (1 << 31) | (1 << 8);#if 0struct rtc_datetime rtcdate;rtcdate.year = 2018U;rtcdate.month = 12U;rtcdate.day = 13U;rtcdate.hour = 14U;rtcdate.minute = 52;rtcdate.second = 0;rtc_setDatetime(&rtcdate); //初始化时间和日期
#endifrtc_enable(); //使能RTC}/** 描述: 开启RTC*/
void rtc_enable(void)
{/** LPCR寄存器bit0置1,使能RTC*/SNVS->LPCR |= 1 << 0; while(!(SNVS->LPCR & 0X01));//等待使能完成}/** 描述: 关闭RTC*/
void rtc_disable(void)
{/** LPCR寄存器bit0置0,关闭RTC*/SNVS->LPCR &= ~(1 << 0); while(SNVS->LPCR & 0X01);//等待关闭完成
}/** @description : 判断指定年份是否为闰年,闰年条件如下:* @param - year: 要判断的年份* @return : 1 是闰年,0 不是闰年*/
unsigned char rtc_isleapyear(unsigned short year)
{ unsigned char value=0;if(year % 400 == 0)value = 1;else {if((year % 4 == 0) && (year % 100 != 0))value = 1;else value = 0;}return value;
}/** @description : 将时间转换为秒数* @param - datetime: 要转换日期和时间。* @return : 转换后的秒数*/
unsigned int rtc_coverdate_to_seconds(struct rtc_datetime *datetime)
{ unsigned short i = 0;unsigned int seconds = 0;unsigned int days = 0;unsigned short monthdays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};for(i = 1970; i < datetime->year; i++){days += DAYS_IN_A_YEAR; /* 平年,每年365天 */if(rtc_isleapyear(i)) days += 1;/* 闰年多加一天 */}days += monthdays[datetime->month];if(rtc_isleapyear(i) && (datetime->month >= 3)) days += 1;/* 闰年,并且当前月份大于等于3月的话加一天 */days += datetime->day - 1;seconds = days * SECONDS_IN_A_DAY + datetime->hour * SECONDS_IN_A_HOUR +datetime->minute * SECONDS_IN_A_MINUTE +datetime->second;return seconds;
}/** @description : 设置时间和日期* @param - datetime: 要设置的日期和时间* @return : 无*/
void rtc_setdatetime(struct rtc_datetime *datetime)
{unsigned int seconds = 0;unsigned int tmp = SNVS->LPCR; rtc_disable(); /* 设置寄存器HPRTCMR和HPRTCLR的时候一定要先关闭RTC *//* 先将时间转换为秒 */seconds = rtc_coverdate_to_seconds(datetime);SNVS->LPSRTCMR = (unsigned int)(seconds >> 17); /* 设置高16位 */SNVS->LPSRTCLR = (unsigned int)(seconds << 15); /* 设置地16位 *//* 如果此前RTC是打开的在设置完RTC时间以后需要重新打开RTC */if (tmp & 0x1)rtc_enable();
}/** @description : 将秒数转换为时间* @param - seconds : 要转换的秒数* @param - datetime: 转换后的日期和时间* @return : 无*/
void rtc_convertseconds_to_datetime(unsigned int seconds, struct rtc_datetime *datetime)
{unsigned int x;unsigned int secondsRemaining, days;unsigned short daysInYear;/* 每个月的天数 */unsigned char daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};secondsRemaining = seconds; /* 剩余秒数初始化 */days = secondsRemaining / SECONDS_IN_A_DAY + 1; /* 根据秒数计算天数,加1是当前天数 */secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY; /*计算天数以后剩余的秒数 *//* 计算时、分、秒 */datetime->hour = secondsRemaining / SECONDS_IN_A_HOUR;secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;datetime->minute = secondsRemaining / 60;datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;/* 计算年 */daysInYear = DAYS_IN_A_YEAR;datetime->year = YEAR_RANGE_START;while(days > daysInYear){/* 根据天数计算年 */days -= daysInYear;datetime->year++;/* 处理闰年 */if (!rtc_isleapyear(datetime->year))daysInYear = DAYS_IN_A_YEAR;else /*闰年,天数加一 */daysInYear = DAYS_IN_A_YEAR + 1;}/*根据剩余的天数计算月份 */if(rtc_isleapyear(datetime->year)) /* 如果是闰年的话2月加一天 */daysPerMonth[2] = 29;for(x = 1; x <= 12; x++){if (days <= daysPerMonth[x]){datetime->month = x;break;}else{days -= daysPerMonth[x];}}datetime->day = days;}/** @description : 获取RTC当前秒数* @param : 无* @return : 当前秒数 */
unsigned int rtc_getseconds(void)
{unsigned int seconds = 0;seconds = (SNVS->LPSRTCMR << 17) | (SNVS->LPSRTCLR >> 15);return seconds;
}/** @description : 获取当前时间* @param - datetime: 获取到的时间,日期等参数* @return : 无 */
void rtc_getdatetime(struct rtc_datetime *datetime)
{unsigned int seconds = 0;seconds = rtc_getseconds();rtc_convertseconds_to_datetime(seconds, datetime);
}
//bsp_rtc.h
#ifndef _BSP_RTC_H
#define _BSP_RTC_H
#include "imx6ul.h"/* 相关宏定义 */
#define SECONDS_IN_A_DAY (86400) /* 一天86400秒 */
#define SECONDS_IN_A_HOUR (3600) /* 一个小时3600秒 */
#define SECONDS_IN_A_MINUTE (60) /* 一分钟60秒 */
#define DAYS_IN_A_YEAR (365) /* 一年365天 */
#define YEAR_RANGE_START (1970) /* 开始年份1970年 */
#define YEAR_RANGE_END (2099) /* 结束年份2099年 *//* 时间日期结构体 */
struct rtc_datetime
{unsigned short year; /* 范围为:1970 ~ 2099 */unsigned char month; /* 范围为:1 ~ 12 */unsigned char day; /* 范围为:1 ~ 31 (不同的月,天数不同).*/unsigned char hour; /* 范围为:0 ~ 23 */unsigned char minute; /* 范围为:0 ~ 59 */unsigned char second; /* 范围为:0 ~ 59 */
};/* 函数声明 */
void rtc_init(void);
void rtc_enable(void);
void rtc_disable(void);
unsigned int rtc_coverdate_to_seconds(struct rtc_datetime *datetime);
unsigned int rtc_getseconds(void);
void rtc_setdatetime(struct rtc_datetime *datetime);
void rtc_getdatetime(struct rtc_datetime *datetime)
;#endif
//main.c
/**************************************************************
描述 : I.MX6U开发板裸机实验17 RTC实时时钟实验
其他 : 本实验学习如何编写I.MX6U内部的RTC驱动,使用内部RTC可以实现一个实时时钟。
**************************************************************/
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_beep.h"
#include "bsp_key.h"
#include "bsp_int.h"
#include "bsp_uart.h"
#include "bsp_lcd.h"
#include "bsp_lcdapi.h"
#include "bsp_rtc.h"
#include "stdio.h"/** @description : main函数* @param : 无* @return : 无*/
int main(void)
{unsigned char key = 0;int i = 3, t = 0;char buf[160];struct rtc_datetime rtcdate;unsigned char state = OFF;int_init(); /* 初始化中断(一定要最先调用!) */imx6u_clkinit(); /* 初始化系统时钟 */delay_init(); /* 初始化延时 */clk_enable(); /* 使能所有的时钟 */led_init(); /* 初始化led */beep_init(); /* 初始化beep */uart_init(); /* 初始化串口,波特率115200 */lcd_init(); /* 初始化LCD */rtc_init(); /* 初始化RTC */tftlcd_dev.forecolor = LCD_RED;lcd_show_string(50, 10, 400, 24, 24, (char*)"ZERO-IMX6UL RTC TEST"); /* 显示字符串 */lcd_show_string(50, 40, 200, 16, 16, (char*)"ATOM@ALIENTEK"); lcd_show_string(50, 60, 200, 16, 16, (char*)"2019/3/27"); tftlcd_dev.forecolor = LCD_BLUE;memset(buf, 0, sizeof(buf));while(1){if(t==100) //1s时间到了{t=0;printf("will be running %d s......\r", i);lcd_fill(50, 90, 370, 110, tftlcd_dev.backcolor); /* 清屏 */sprintf(buf, "will be running %ds......", i);lcd_show_string(50, 90, 300, 16, 16, buf); i--;if(i < 0)break;}key = key_getvalue();if(key == KEY0_VALUE){rtcdate.year = 2018;rtcdate.month = 1;rtcdate.day = 15;rtcdate.hour = 16;rtcdate.minute = 23;rtcdate.second = 0;rtc_setdatetime(&rtcdate); /* 初始化时间和日期 */printf("\r\n RTC Init finish\r\n");break;}delayms(10);t++;}tftlcd_dev.forecolor = LCD_RED;lcd_fill(50, 90, 370, 110, tftlcd_dev.backcolor); /* 清屏 */lcd_show_string(50, 90, 200, 16, 16, (char*)"Current Time:"); /* 显示字符串 */tftlcd_dev.forecolor = LCD_BLUE;while(1) { rtc_getdatetime(&rtcdate);sprintf(buf,"%d/%d/%d %d:%d:%d",rtcdate.year, rtcdate.month, rtcdate.day, rtcdate.hour, rtcdate.minute, rtcdate.second);lcd_fill(50,110, 300,130, tftlcd_dev.backcolor);lcd_show_string(50, 110, 250, 16, 16,(char*)buf); /* 显示字符串 */state = !state;led_switch(LED0,state);delayms(1000); /* 延时一秒 */}return 0;
}
相关文章:
38. RTC实验
一、RTC原理详解 1、6U内部自带到了一个RTC外设,确切的说是SRTC。6U和6ULL的RTC内容在SNVS章节。6U的RTC分为LP和HP。LP叫做SRTC,HP是RTC,但是HP的RTC掉电以后数据就丢失了,即使用了纽扣电池也没用。所以必须要使用LP,…...
Flutter 新春第一弹,Dart 宏功能推进暂停,后续专注定制数据处理支持
在去年春节,Flutter 官方发布了宏(Macros)编程的原型支持, 同年的 5 月份在 Google I/O 发布的 Dart 3.4 宣布了宏的实验性支持,但是对于 Dart 内部来说,从启动宏编程实验开始已经过去了几年,但…...
巴菲特价值投资思想的核心原则
巴菲特价值投资思想的核心原则 关键词:安全边际、长期投资、内在价值、管理团队、经济护城河、简单透明 摘要:本文深入探讨了巴菲特价值投资思想的核心原则,包括安全边际、长期投资、企业内在价值、优秀管理团队、经济护城河和简单透明的业务…...
C 或 C++ 中用于表示常量的后缀:1ULL
1ULL 是一个在 C 或 C 中用于表示常量的后缀,它具体指示编译器将这个数值视为特定类型的整数。让我们详细解释一下: 1ULL 的含义 1: 这是最基本的部分,表示数值 1。U: 表示该数值是无符号(Unsigned)的。这意味着它只…...
vue3中el-input无法获得焦点的问题
文章目录 现象两次nextTick()加setTimeout()解决结论 现象 el-input被外层div包裹了,设置autofocus不起作用: <el-dialog v-model"visible" :title"title" :append-to-bodytrue width"50%"><el-form v-model&q…...

程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图<3>
大家好啊,我是小象٩(๑ω๑)۶ 我的博客:Xiao Xiangζั͡ޓއއ 很高兴见到大家,希望能够和大家一起交流学习,共同进步。 今天我们来对上一节做一些小补充,了解学习一下assert断言,指针的使用和传址调用…...

(三)QT——信号与槽机制——计数器程序
目录 前言 信号(Signal)与槽(Slot)的定义 一、系统自带的信号和槽 二、自定义信号和槽 三、信号和槽的扩展 四、Lambda 表达式 总结 前言 信号与槽机制是 Qt 中的一种重要的通信机制,用于不同对象之间的事件响…...

Qt 5.14.2 学习记录 —— 이십이 QSS
文章目录 1、概念2、基本语法3、给控件应用QSS设置4、选择器1、子控件选择器2、伪类选择器 5、样式属性box model 6、实例7、登录界面 1、概念 参考了CSS,都是对界面的样式进行设置,不过功能不如CSS强大。 可通过QSS设置样式,也可通过C代码…...

Hot100之哈希
1两数之和 题目 思路解析 解法1--两次循环 解法2--哈希表一次循环 代码 解法1--两次循环 class Solution {public int[] twoSum(int[] nums, int target) {int nums1[] new int[2];int length nums.length;for (int i 0; i < length; i) {for (int j i 1; j < …...
油漆面积——蓝桥杯
1.题目描述 X 星球的一批考古机器人正在一片废墟上考古。 该区域的地面坚硬如石、平整如镜。 管理人员为方便,建立了标准的直角坐标系。 每个机器人都各有特长、身怀绝技。它们感兴趣的内容也不相同。 经过各种测量,每个机器人都会报告一个或多个矩…...
深度解析:网站快速收录与服务器性能的关系
本文转自:百万收录网 原文链接:https://www.baiwanshoulu.com/37.html 网站快速收录与服务器性能之间存在着密切的关系。服务器作为网站运行的基础设施,其性能直接影响到搜索引擎对网站的抓取效率和收录速度。以下是对这一关系的深度解析&am…...

925.长按键入
目录 一、题目二、思路三、解法四、收获 一、题目 你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。 你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字&am…...
JavaScript 中的 var 和 let :关键区别与使用建议
在 JavaScript 开发中,变量声明是基础且重要的部分。 var 和 let 都是用于声明变量的关键字,但它们在作用域、变量提升、重复声明等方面存在显著差异。本文将详细探讨它们的区别,并给出使用建议。 1. 作用域 1.1 var 的作用域 …...
寒假刷题Day19
一、923. 三数之和的多种可能 class Solution { public:int threeSumMulti(vector<int>& arr, int target) {const int MOD 1000000007; // 正确的模数long long ans 0; // 使用 long long 防止溢出std::sort(arr.begin(), arr.end());for (size_t i 0; i < a…...
写好简历的三个关键认知
在当今竞争激烈的就业市场中,一份优秀的简历往往是敲开理想企业大门的第一把钥匙。然而,很多求职者在写简历时往往不得要领,让宝贵的机会从指间溜走。今天,让我们一起探讨如何提升简历写作水平,让你的职业之路走得更顺…...

工具的应用——安装copilot
一、介绍Copilot copilot是一个AI辅助编程的助手,作为需要拥抱AI的程序员可以从此尝试进入,至于好与不好,应当是小马过河,各有各的心得。这里不做评述。重点在安装copilot的过程中遇到了一些问题,然后把它总结下&…...
Koa 基础篇(二)—— 路由与中间件
let app new Koa() router.get(“/”,async ctx > { ctx.body “hello koa router” }) app.use(router.routes()) app.use(router.allowedMethods()) app.listen(3000) 运行项目,在浏览器访问本地3000端口,在页面上就会看到输出的语句。这就…...

帆软 FCA -业务分析师认证学习
帆软 FCA -业务分析师认证学习 认证概述 适合人群 企业中有需求管理、指标梳理、业务逻辑梳理、项目规划等需求的人员,想提升综合数据能力、推进数据应用落地的业务/IT骨干。 具体-FCA-业务分析理论 考试要求: FCA-业务分析理论考试- 费用:…...
Miniconda 安装及使用
文章目录 前言1、Miniconda 简介2、Linux 环境说明2.1、安装2.2、配置2.3、常用命令2.4、常见问题及解决方案 前言 在 Python 中,“环境管理”是一个非常重要的概念,它主要是指对 Python 解释器及其相关依赖库进行管理和隔离,以确保开发环境…...
solidity高阶 -- Eth支付
在区块链的世界里,智能合约是实现去中心化应用(DApp)的核心技术之一。Solidity 是一种专门用于编写以太坊智能合约的编程语言,它可以帮助开发者构建各种功能,包括支付功能。 今天,我们就来探讨如何使用 Sol…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...