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

LV.12 D20 RTC实验 学习笔记

一、RTC简介

        RTC(Real Time Clock)即实时时钟,它是一个可以为系统提供精确的时间基准的元器件,RTC一般采用精度较高的晶振作为时钟源,有些RTC为了在主电源掉电时还可以工作,需要外加电池供电

二、Exynos4412下的 RTC控制器

它支持BCD Number,以BDC码的格式存储年月日、星期、时分秒。

BCD码举例: 12 用二进制表示是   1100    用BCD码表示就是       0001  0010

支持闰年(能判断闰年)

支持闹铃功能

支持滴答计数器,

支持独立电源引脚(RTCVDD)

滴答定时器还支持实时操作系统工作

这些东西32用的比较多,4412一般只用它来获取时间

左边是一个32.768KHz的时钟,经过一个2^15的分频器(32768),就获得了一个1Hz的时钟,来给秒使用

三、RTC寄存器详解

INTP:中断挂起寄存器

RTCCON: RTC的控制寄存器,用于控制相关功能

RTCALM:用于控制闹铃相关的功能

以BCD开头的寄存器:是用于存储RTC产生的时间的(以BCD码的形式进行存储的),读取和修改时,也必须以BCD码的形式进行读写。

以ALM开头的寄存器:用于设置一个预期时间,当预期时间与实际时间(以BCD开头的寄存器存储的)相等时,RTC寄存器就会产生一个中断信号,实现闹铃功能。

BCDTEAR寄存器有三块,用BCD码分别表示百位十位和个位,千位默认是2。

例如:2023年用BCD码表示就是000000100011

 BCDMON寄存器:月的十位只能是0和1,所以只占一位

 BCDDATY寄存器:日的十位只能是0-3,最大的3的BCD码为11,所以只占2位。

  BCDDATYWEEK寄存器:星期只能是是0-7,最大的7的BCD码为111,所以只占3位。

 

 

 

 

 

对于RTCCON这个寄存器我们只需要关注他的第0位就行,其它位使用默认设置。

这其实就是一把锁,只有把锁打开了我们才能修改时间,这是为了防止有些野指针,把内容修改了。

 

四、RTC编程

由于板子并没有备用电源,所以我们要先校准一下时间:

C语言只支持八进制、十进制、十六进制,由于BCD转换成10进制看起来怪怪的,所以我们要写一个转化函数。或者我们可以把BCD码转换成十六进制,因为它们都是4位二进制对应1位。

如果要把年写成2023,即RTC.BCDYEAR = 0x023;

#include "exynos_4412.h"

int main()
{
	/*使能RTC控制*/
	RTCCON = RTCCON | 1;
	/*校准时间信息*/
	RTC.BCDYEAR = 0x023;
	RTC.BCDMON = 0x12;
	RTC.BCDDAY = 0x7; 	//手册中BCDDAY和BCDWEEK地址写反了,所以这里需要反着写
	RTC.BCDWEEK = 0x31;
	RTC.BCDHOUR = 0x23;
	RTC.BCDMIN = 0x59;
	RTC.BCDSEC = 0x50;
	/*禁止RTC控制*/
	RTCCON = RTCCON & (~(1));

	while(1)
	{
		printf("20%x-%x-%x %x %x:%x:%x\n", RTC.BCDYEAR, RTC.BCDMON, RTC.BCDWEEK, RTC.BCDDAY, RTC.BCDHOUR, RTC.BCDMIN, RTC.BCDSEC);
	}

	return 0;
}

但是程序跳动的太快了,所以我们改一下让他一秒钟打印一次

#include "exynos_4412.h"

int main()
{
	unsigned int OldSec = 0, NewSec = 0;

	/*使能RTC控制*/
	RTCCON = RTCCON | 1;
	/*校准时间信息*/
	RTC.BCDYEAR = 0x023;
	RTC.BCDMON = 0x12;
	RTC.BCDDAY = 0x7; 	//手册中BCDDAY和BCDWEEK地址写反了,所以这里需要反着写
	RTC.BCDWEEK = 0x31;
	RTC.BCDHOUR = 0x23;
	RTC.BCDMIN = 0x59;
	RTC.BCDSEC = 0x50;
	/*禁止RTC控制*/
	RTCCON = RTCCON & (~(1));

	while(1)
	{
		NewSec = RTC.BCDSEC;
		if(OldSec != NewSec)
		{
			printf("20%x-%x-%x %x %x:%x:%x\n", RTC.BCDYEAR, RTC.BCDMON, RTC.BCDWEEK, RTC.BCDDAY, RTC.BCDHOUR, RTC.BCDMIN, RTC.BCDSEC);
			OldSec = NewSec;
		}
	}

	return 0;
}

五、作业 

1.编程实现通过LED状态显示当前电压范围,并打印产生低压警报时的时间

注:
电压在1501mv~1800mv时,LED2、LED3、LED4、LED5点亮
电压在1001mv~1500mv时,LED2、LED3、LED4点亮
电压在501mv~1000mv时,LED2、LED3点亮
电压在0mv~500mv时,LED2闪烁,且每隔一秒钟向终端打印一次当前的电压值及当前的时间

#include "exynos_4412.h"

void Delay(unsigned int Time)
{
	while(Time--);
}

int main()
{
	unsigned int AdcValue;
	unsigned int OldSec = 0, NewSec = 0;

	/*LED2*/
	GPX2.CON = GPX2.CON | (0x1 << 28);
	/*LED3*/
	GPX1.CON = GPX1.CON | 0x1;
	/*LED4*/
	GPF3.CON = GPF3.CON | (0x1 << 16);
	/*LED5*/
	GPF3.CON = GPF3.CON | (0x1 << 20);

	/*将ADC的精度设置为12bit*/
	ADCCON = ADCCON | (1 << 16);
	/*使能ADC的分频器*/
	ADCCON = ADCCON | (1 << 14);
	/*设置ADC的分频 ADC时钟频率=PLCK/(19+1)=5MHz,ADC的转换频率=5MHz/5=1MHz*/
	ADCCON = ADCCON & (~(0xFF << 6)) | (19 << 6);
	/*关闭待机模式,使能正常模式*/
	ADCCON = ADCCON & (~(1 << 2));
	/*关闭通过读使能AD转换*/
	ADCCON = ADCCON & (~(1 << 1));
	/*选择转换通道 3通道*/
	ADCMUX = 3;

	/*使能RTC控制*/
	RTCCON = RTCCON | 1;
	/*校准时间信息*/
	RTC.BCDYEAR = 0x023;
	RTC.BCDMON = 0x12;
	RTC.BCDDAY = 0x7; 	//手册中BCDDAY和BCDWEEK地址写反了,所以这里需要反着写
	RTC.BCDWEEK = 0x31;
	RTC.BCDHOUR = 0x23;
	RTC.BCDMIN = 0x59;
	RTC.BCDSEC = 0x50;
	/*禁止RTC控制*/
	RTCCON = RTCCON & (~(1));

	while(1)
	{
		/*开始转换*/
		ADCCON = ADCCON | 1;
		/*等待转换完成*/
		while(!(ADCCON & (1 << 15)));
		/*读取转换结果*/
		AdcValue = ADCDAT & 0xFFF;
		/*将结果转换成实际的电压值 =AdcValue*(15800/4096) mv*/
		AdcValue =AdcValue * 0.44;
		/*打印转换结果*/
		printf("AdcValue = %dmv\n", AdcValue);

		if(AdcValue > 1501)
		{
			GPX2.DAT = GPX2.DAT | (1 << 7);
			GPX1.DAT = GPX1.DAT | 1;
			GPF3.DAT = GPF3.DAT | (1 << 4);
			GPF3.DAT = GPF3.DAT | (1 << 5);
		}
		else if(AdcValue > 1001)
		{
			GPX2.DAT = GPX2.DAT | (1 << 7);
			GPX1.DAT = GPX1.DAT | 1;
			GPF3.DAT = GPF3.DAT | (1 << 4);
		}
		else if(AdcValue > 501)
		{
			GPX2.DAT = GPX2.DAT | (1 << 7);
			GPX1.DAT = GPX1.DAT | 1;
		}
		else
		{
			NewSec = RTC.BCDSEC;
			GPX2.DAT = GPX2.DAT | (1 << 7);
			Delay(1000000);
			GPX2.DAT = GPX2.DAT & (~(1 << 7));
			if(OldSec != NewSec)
			{
				printf("20%x-%x-%x %x %x:%x:%x\n", RTC.BCDYEAR, RTC.BCDMON, RTC.BCDWEEK, RTC.BCDDAY, RTC.BCDHOUR, RTC.BCDMIN, RTC.BCDSEC);
				OldSec = NewSec;
			}
		}
	}

	return 0;
}

 


http://www.kler.cn/a/145950.html

相关文章:

  • PTA NeuDs_数据库题目
  • 微机原理_5
  • 【代码随想录刷题】Day18 二叉树05
  • 【从删库到跑路 | MySQL总结篇】数据库基础(增删改查的基本操作)
  • 【古诗生成AI实战】之一——实战项目总览
  • HarmonyOS开发者工具DevEco Studio-汉化
  • 服务器tar压缩解压文件
  • 【MATLAB源码-第90期】基于matlab的OQPSKsimulink仿真,对比初始信号和解调信号输出星座图。
  • 处理数据中的缺失值--删除缺少值的行
  • java io 流,输入流和输出流;节点流和处理流;字节流和字符流
  • Qt/QML编程学习之心得:一个QML工程的学习笔记(十)
  • 【RTP】3: RTPSenderVideo::SendVideo 切片到发送
  • vscode导入STM32CubeIDE工程文件夹未定义警告清除方法
  • 【STL】string类 (下)
  • 【nlp】4.3 nlp中常用的预训练模型(BERT及其变体)
  • 【c++随笔14】虚函数表
  • S25FL系列FLASH读写的FPGA实现
  • # Panda3d 碰撞检测系统介绍
  • 离散化 与 哈希 之间的区别
  • [AutoSAR 存储] 汽车智能座舱的存储需求