当前位置: 首页 > news >正文

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外设&#xff0c;确切的说是SRTC。6U和6ULL的RTC内容在SNVS章节。6U的RTC分为LP和HP。LP叫做SRTC&#xff0c;HP是RTC&#xff0c;但是HP的RTC掉电以后数据就丢失了&#xff0c;即使用了纽扣电池也没用。所以必须要使用LP&#xff0c…...

Flutter 新春第一弹,Dart 宏功能推进暂停,后续专注定制数据处理支持

在去年春节&#xff0c;Flutter 官方发布了宏&#xff08;Macros&#xff09;编程的原型支持&#xff0c; 同年的 5 月份在 Google I/O 发布的 Dart 3.4 宣布了宏的实验性支持&#xff0c;但是对于 Dart 内部来说&#xff0c;从启动宏编程实验开始已经过去了几年&#xff0c;但…...

巴菲特价值投资思想的核心原则

巴菲特价值投资思想的核心原则 关键词&#xff1a;安全边际、长期投资、内在价值、管理团队、经济护城河、简单透明 摘要&#xff1a;本文深入探讨了巴菲特价值投资思想的核心原则&#xff0c;包括安全边际、长期投资、企业内在价值、优秀管理团队、经济护城河和简单透明的业务…...

C 或 C++ 中用于表示常量的后缀:1ULL

1ULL 是一个在 C 或 C 中用于表示常量的后缀&#xff0c;它具体指示编译器将这个数值视为特定类型的整数。让我们详细解释一下&#xff1a; 1ULL 的含义 1: 这是最基本的部分&#xff0c;表示数值 1。U: 表示该数值是无符号&#xff08;Unsigned&#xff09;的。这意味着它只…...

vue3中el-input无法获得焦点的问题

文章目录 现象两次nextTick()加setTimeout()解决结论 现象 el-input被外层div包裹了&#xff0c;设置autofocus不起作用&#xff1a; <el-dialog v-model"visible" :title"title" :append-to-bodytrue width"50%"><el-form v-model&q…...

程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图<3>

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。 今天我们来对上一节做一些小补充&#xff0c;了解学习一下assert断言&#xff0c;指针的使用和传址调用…...

(三)QT——信号与槽机制——计数器程序

目录 前言 信号&#xff08;Signal&#xff09;与槽&#xff08;Slot&#xff09;的定义 一、系统自带的信号和槽 二、自定义信号和槽 三、信号和槽的扩展 四、Lambda 表达式 总结 前言 信号与槽机制是 Qt 中的一种重要的通信机制&#xff0c;用于不同对象之间的事件响…...

Qt 5.14.2 学习记录 —— 이십이 QSS

文章目录 1、概念2、基本语法3、给控件应用QSS设置4、选择器1、子控件选择器2、伪类选择器 5、样式属性box model 6、实例7、登录界面 1、概念 参考了CSS&#xff0c;都是对界面的样式进行设置&#xff0c;不过功能不如CSS强大。 可通过QSS设置样式&#xff0c;也可通过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 星球的一批考古机器人正在一片废墟上考古。 该区域的地面坚硬如石、平整如镜。 管理人员为方便&#xff0c;建立了标准的直角坐标系。 每个机器人都各有特长、身怀绝技。它们感兴趣的内容也不相同。 经过各种测量&#xff0c;每个机器人都会报告一个或多个矩…...

深度解析:网站快速收录与服务器性能的关系

本文转自&#xff1a;百万收录网 原文链接&#xff1a;https://www.baiwanshoulu.com/37.html 网站快速收录与服务器性能之间存在着密切的关系。服务器作为网站运行的基础设施&#xff0c;其性能直接影响到搜索引擎对网站的抓取效率和收录速度。以下是对这一关系的深度解析&am…...

925.长按键入

目录 一、题目二、思路三、解法四、收获 一、题目 你的朋友正在使用键盘输入他的名字 name。偶尔&#xff0c;在键入字符 c 时&#xff0c;按键可能会被长按&#xff0c;而字符可能被输入 1 次或多次。 你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字&am…...

JavaScript 中的 var 和 let :关键区别与使用建议

在 JavaScript 开发中&#xff0c;变量声明是基础且重要的部分。 var 和 let 都是用于声明变量的关键字&#xff0c;但它们在作用域、变量提升、重复声明等方面存在显著差异。本文将详细探讨它们的区别&#xff0c;并给出使用建议。 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…...

写好简历的三个关键认知

在当今竞争激烈的就业市场中&#xff0c;一份优秀的简历往往是敲开理想企业大门的第一把钥匙。然而&#xff0c;很多求职者在写简历时往往不得要领&#xff0c;让宝贵的机会从指间溜走。今天&#xff0c;让我们一起探讨如何提升简历写作水平&#xff0c;让你的职业之路走得更顺…...

工具的应用——安装copilot

一、介绍Copilot copilot是一个AI辅助编程的助手&#xff0c;作为需要拥抱AI的程序员可以从此尝试进入&#xff0c;至于好与不好&#xff0c;应当是小马过河&#xff0c;各有各的心得。这里不做评述。重点在安装copilot的过程中遇到了一些问题&#xff0c;然后把它总结下&…...

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) 运行项目&#xff0c;在浏览器访问本地3000端口&#xff0c;在页面上就会看到输出的语句。这就…...

帆软 FCA -业务分析师认证学习

帆软 FCA -业务分析师认证学习 认证概述 适合人群 企业中有需求管理、指标梳理、业务逻辑梳理、项目规划等需求的人员&#xff0c;想提升综合数据能力、推进数据应用落地的业务/IT骨干。 具体-FCA-业务分析理论 考试要求&#xff1a; FCA-业务分析理论考试- 费用&#xff1a…...

Miniconda 安装及使用

文章目录 前言1、Miniconda 简介2、Linux 环境说明2.1、安装2.2、配置2.3、常用命令2.4、常见问题及解决方案 前言 在 Python 中&#xff0c;“环境管理”是一个非常重要的概念&#xff0c;它主要是指对 Python 解释器及其相关依赖库进行管理和隔离&#xff0c;以确保开发环境…...

solidity高阶 -- Eth支付

在区块链的世界里&#xff0c;智能合约是实现去中心化应用&#xff08;DApp&#xff09;的核心技术之一。Solidity 是一种专门用于编写以太坊智能合约的编程语言&#xff0c;它可以帮助开发者构建各种功能&#xff0c;包括支付功能。 今天&#xff0c;我们就来探讨如何使用 Sol…...

深入理解Java中的String

前言 在Java中&#xff0c;String类是一个非常重要的内置类&#xff0c;用于处理字符串数据。字符串是不可变的&#xff08;immutable&#xff09;&#xff0c;这意味着一旦创建&#xff0c;字符串的内容不能被修改。作为Java中最为基础和常用的类之一&#xff0c;String类在内…...

洛谷 P1734 最大约数和 C语言

P1734 最大约数和 - 洛谷 | 计算机科学教育新生态 题目描述 选取和不超过 S 的若干个不同的正整数&#xff0c;使得所有数的约数&#xff08;不含它本身&#xff09;之和最大。 输入格式 输入一个正整数 S。 输出格式 输出最大的约数之和。 输入输出样例 输入 #1复制 …...

Golang 执行流程分析

文章目录 1. 编译和运行2. 编译和运行说明 1. 编译和运行 如果是对源码编译后&#xff0c;再执行&#xff0c;Go的执行流程如下图 如果我们是对源码直接 执行 go run 源码&#xff0c;Go的执行流程如下图 两种执行流程的方式区别 如果先编译生成了可执行文件&#xff0c;那么…...

python学opencv|读取图像(五十一)使用修改图像像素点上BGR值实现图像覆盖效果

【1】引言 前序学习了图像的得加方法&#xff0c;包括使用add()函数直接叠加BGR值、使用bitwise()函数对BGR值进行按位计算叠加和使用addWeighted()函数实现图像加权叠加至少三种方法。文章链接包括且不限于&#xff1a; python学opencv|读取图像&#xff08;四十二&#xff…...

Flask数据的增删改查(CRUD)_flask删除数据自动更新

查询年龄小于17的学生信息 Student.query.filter(Student.s_age < 17) students Student.query.filter(Student.s_age.__lt__(17))模糊查询&#xff0c;使用like&#xff0c;查询姓名中第二位为花的学生信息 like ‘_花%’,_代表必须有一个数据&#xff0c;%任何数据 st…...

kamailio-ACC模块介绍【kamailio6.0. X】

Acc 模块 作者 Jiri Kuthan iptel.org jiriiptel.org Bogdan-Andrei Iancu Voice Sistem SRL bogdanvoice-system.ro Ramona-Elena Modroiu rosdev.ro ramonarosdev.ro 编辑 Bogdan-Andrei Iancu Voice Sistem SRL bogdanvoice-system.ro Sven Knoblich 1&1 Internet …...

数据库对象

数据库对象 数据库对象是构成数据库结构的基本单位&#xff0c;它们定义了数据库存储的数据类型、数据的组织方式以及数据之间的关系。在数据库中&#xff0c;对象可以包括表&#xff0c;视图&#xff0c;索引&#xff0c;触发器&#xff0c;存储过程&#xff0c;函数等多种类…...

EtherCAT主站IGH-- 27 -- IGH之globals.h文件解析

EtherCAT主站IGH-- 27 -- IGH之globals.h文件解析 0 预览一 该文件功能宏定义数据结构打印宏三 h文件翻译四 c文件翻译该文档修改记录:总结0 预览 一 该文件功能 该文件包含了一些全局定义和宏,用于 IgH EtherCAT 主站(EtherCAT Master)的实现。包括了一些超时设定、宏定义…...

2025多目标优化创新路径汇总

多目标优化是当下非常热门且有前景的方向&#xff01;作为AI领域的核心技术之一&#xff0c;其专注于解决多个相互冲突的目标的协同优化问题&#xff0c;核心理念是寻找一组“不完美但均衡”的“帕累托最优解”。在实际中&#xff0c;几乎处处都有它的身影。 但随着需求场景的…...

15JavaWeb——Maven高级篇

Maven高级 Web开发讲解完毕之后&#xff0c;我们再来学习Maven高级。其实在前面的课程当中&#xff0c;我们已经学习了Maven。 我们讲到 Maven 是一款构建和管理 Java 项目的工具。经过前面 10 多天 web 开发的学习&#xff0c;相信大家对于 Maven 这款工具的基本使用应该没什…...