LV.12 D20 RTC实验 学习笔记

一、RTC简介

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

LV.12 D20 RTC实验 学习笔记_第1张图片

二、Exynos4412下的 RTC控制器

LV.12 D20 RTC实验 学习笔记_第2张图片

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

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

支持闰年(能判断闰年)

支持闹铃功能

支持滴答计数器,

支持独立电源引脚(RTCVDD)

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

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

LV.12 D20 RTC实验 学习笔记_第3张图片

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

三、RTC寄存器详解

LV.12 D20 RTC实验 学习笔记_第4张图片

INTP:中断挂起寄存器

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

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

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

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

LV.12 D20 RTC实验 学习笔记_第5张图片

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

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

LV.12 D20 RTC实验 学习笔记_第6张图片

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

LV.12 D20 RTC实验 学习笔记_第7张图片

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

LV.12 D20 RTC实验 学习笔记_第8张图片

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

 LV.12 D20 RTC实验 学习笔记_第9张图片

LV.12 D20 RTC实验 学习笔记_第10张图片 

 LV.12 D20 RTC实验 学习笔记_第11张图片

 LV.12 D20 RTC实验 学习笔记_第12张图片

 

对于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;
}

LV.12 D20 RTC实验 学习笔记_第13张图片

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

#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;
}

LV.12 D20 RTC实验 学习笔记_第14张图片

五、作业 

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;
}

 

你可能感兴趣的:(学习,笔记,arm开发)