目录
一、ADC小作业
二、RTC简介
三、Exynos_4412下的RTC控制器
四、RTC中的寄存器
五、RTC编程
六、RTC小作业
一、ADC小作业
电压在1501mv~1800mv时,LED2、LED3、LED4、LED5点亮
 电压在1001mv~1500mv时,LED2、LED3、LED4点亮
 电压在501mv~1000mv时,LED2、LED3点亮
 电压在0mv~500mv时,LED2闪烁
LED电路图和寄存器:
C工程与寄存器封装_宇努力学习的博客-CSDN博客
ADC电路图和寄存器:
Exynos_4412——ADC实验_宇努力学习的博客-CSDN博客
#include "exynos_4412.h"
void delay(unsigned int time)
{
	while(time --);
}
int main()
{
    unsigned int adc_value;
	unsigned int n = 0;
    //12
    ADCCON = ADCCON | (1 << 16);
    //使能ADC分频器
    ADCCON = ADCCON | (1 << 14);
    //100/(19+1)=5MHz 5 / 5 = 1MHz
    ADCCON = ADCCON & (~(0xFF << 6)) | (19 << 6);
    //关闭待机模式
    ADCCON = ADCCON & (~(1 << 2));
    //关闭通过读使能AD转换
    ADCCON = ADCCON & (~(1 << 1));
    ADCMUX = 3;
	GPX2.CON = GPX2.CON & (~(0xF << 28)) | (0x1 << 28);
	GPX1.CON = GPX1.CON & (~(0xF)) | (0x1);
	GPF3.CON = GPF3.CON & (~(0xFF << 16)) | (0x11 << 16);
    while(1)
    {
        //开始
        ADCCON = ADCCON | 1;
        while(!(ADCCON & (1 << 15)));
        //读取
        adc_value = ADCDAT & 0xFFF;
        // 1800mV/2^12=1800/4096=0.44
        adc_value = adc_value * 0.44;
		if(adc_value >= 0 & adc_value <= 500)
			n = 1;
		if(adc_value >= 501 & adc_value <= 1000)
			n = 2;
		if(adc_value >= 1001 & adc_value <= 1500)
			n = 3;
		if(adc_value >= 1501 & adc_value <= 1800)
			n = 4;
		switch(n)
		{
			case 1:
				GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ON
				delay(1000000);
				GPX2.DAT = GPX2.DAT & (~(1 << 7));//LED2_OFF
				delay(1000000);
				GPX1.DAT = GPX1.DAT & (~1);//LED3_OFF
				GPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFF
				GPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFF
				break;
			case 2:
				GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ON	
				GPX1.DAT = GPX1.DAT | 1;//LED3_ON
				GPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFF
				GPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFF
				break;
			case 3:
				GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ON
				GPX1.DAT = GPX1.DAT | 1;//LED3_ON
				GPF3.DAT = GPF3.DAT | (1 << 4);//LED4_ON
				GPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFF
				break;
			case 4:
				GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ON
				GPX1.DAT = GPX1.DAT | 1;//LED3_ON
				GPF3.DAT = GPF3.DAT | (1 << 4);//LED4_ON
				GPF3.DAT = GPF3.DAT | (1 << 5);//LED5_ON
				break;
			default:
				GPX2.DAT = GPX2.DAT & (~(1 << 7));//LED2_OFF
				GPX1.DAT = GPX1.DAT & (~1);//LED3_OFF
				GPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFF
				GPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFF
				break;
		}
        printf("adc_value = %d mV\n",adc_value);
    }
    return 0;
}
二、RTC简介
RTC(Real Time Clock)即实时时钟,它是一个可以为系统提供精确的时间基准的元器件,RTC一般采用精度较高的晶振作为时钟源,有些RTC为了在主电源掉电时还可以工作,需要外加电池供电

比如以前的手机,扣掉电池在安上时间就不准了,而现在的电子产品不会出现这个问题是因为他有备用电源。由于它只有一个RTC电路所以功耗很低,一般都是一个小的纽扣电池甚至一个电容就够了。
三、Exynos_4412下的RTC控制器

4412下的RTC还支持闹钟功能
它支持BCD number 年月日、星期、时分秒
https://baike.baidu.com/item/BCD%E7%A0%81/826461?fromtitle=bcd&fromid=13009167&fr=aladdin
举个栗子:
12 用二进制表示是 1100 用BCD码表示就是 0001 0010
支持闰年
支持告警功能即闹钟中断和低功耗模式 低功耗包括:空闲、深度空闲、停止、深度停止、休眠
支持滴答定时器,
支持独立电源引脚(RTCVDD)
滴答定时器还支持实时操作系统工作
这些东西32用的比较多,4412一般只用它来获取时间

32.768KHz的时钟 经过一个2^15的分频器(32768)就获得了一个1Hz的时钟,来给秒使用
四、RTC中的寄存器

 它有三块,用BCD码分别表示百位十位和个位,千位默认是2就行,估计这个单片机都用不到3开头那年。或者我也活不到那个时候啊,哈哈哈
 它有三块,用BCD码分别表示百位十位和个位,千位默认是2就行,估计这个单片机都用不到3开头那年。或者我也活不到那个时候啊,哈哈哈

 
 
注意: 三星把星期和日的地址写反了

 
 
对于RTCCON这个寄存器我们只需要关注他的第0位就行,其它位使用默认设置。
这其实就是一把锁,只有把锁打开了我们才能修改时间,这是为了防止有些野指针,把内容修改了。
五、RTC编程
还是先解压一个工程

由于板子并没有备用电源,所以我们要先校准一下时间:
由于BCD转化成10进制看起来怪怪的,所以我们要写一个转化函数,这里我偷懒一下,以为16进制和BCD需要转化的10进制刚好相等,直接写16进制数
同样读取的时候也需要我们写这样一个转化函数,这里再偷个懒
#include "exynos_4412.h"
int main()
{
    //使能RTC控制
    RTCCON = RTCCON | 1;
    //校准时间
    RTC.BCDYEAR = 0x023; //000000100011  2023
    RTC.BCDMON  = 0x1;   //1
    RTC.BCDDAY  = 0x5;   //5
    RTC.BCDWEEK = 0x4;   //星期四
    RTC.BCDHOUR = 0x11;  //11
    RTC.BCDMIN  = 0x32;  //32
    RTC.BCDSEC  = 0x50;  //50s
    //关闭RTC控制
    RTCCON = RTCCON & 0;
    while(1)
    {
        printf("%x-%x-%x %x %x:%x:%x\n",RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,RTC.BCDWEEK,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; //000000100011  2023
    RTC.BCDMON  = 0x1;   //1
    RTC.BCDDAY  = 0x5;   //5
    RTC.BCDWEEK = 0x7;   //星期四
    RTC.BCDHOUR = 0x11;  //11
    RTC.BCDMIN  = 0x32;  //32
    RTC.BCDSEC  = 0x50;  //50s
    //关闭RTC控制
    RTCCON = RTCCON & 0;
    while(1)
    {
		Newsec = RTC.BCDSEC;
		if(Newsec != Oldsec)
		{
        	printf("%x-%x-%x %x %x:%x:%x\n",RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,RTC.BCDWEEK,RTC.BCDHOUR,RTC.BCDMIN,RTC.BCDSEC);
		
			Oldsec = Newsec;				
		}   
	}
	return 0;
}
手动填个20看起来更好看一些

六、RTC小作业
电压在1501mv~1800mv时,LED2、LED3、LED4、LED5点亮
 电压在1001mv~1500mv时,LED2、LED3、LED4点亮
 电压在501mv~1000mv时,LED2、LED3点亮
 电压在0mv~500mv时,LED2闪烁,且每隔一秒钟向终端打印一次当前的电压值及当前的时间
#include "exynos_4412.h"
void RTC_Init()
{
	//使能RTC控制
    RTCCON = RTCCON | 1;
    //校准时间
    RTC.BCDYEAR = 0x023; //000000100011  2023
    RTC.BCDMON  = 0x1;   //1
    RTC.BCDDAY  = 0x5;   //5
    RTC.BCDWEEK = 0x4;   //星期四
    RTC.BCDHOUR = 0x11;  //11
    RTC.BCDMIN  = 0x32;  //32
    RTC.BCDSEC  = 0x50;  //50s
    //关闭RTC控制
    RTCCON = RTCCON & 0;
}
void ADC_Init()
{
	//12
    ADCCON = ADCCON | (1 << 16);
    //使能ADC分频器
    ADCCON = ADCCON | (1 << 14);
    //100/(19+1)=5MHz 5 / 5 = 1MHz
    ADCCON = ADCCON & (~(0xFF << 6)) | (19 << 6);
    //关闭待机模式
    ADCCON = ADCCON & (~(1 << 2));
    //关闭通过读使能AD转换
    ADCCON = ADCCON & (~(1 << 1));
    ADCMUX = 3;
}
void LED_Init()
{
	GPX2.CON = GPX2.CON & (~(0xF << 28)) | (0x1 << 28);
	GPX1.CON = GPX1.CON & (~(0xF)) | (0x1);
	GPF3.CON = GPF3.CON & (~(0xFF << 16)) | (0x11 << 16);
}
int main()
{
	unsigned int Oldsec = 0, Newsec = 0;	
	unsigned int adc_value;
	unsigned int n = 0;
	unsigned int flag = 1;
    RTC_Init();
	ADC_Init();
	LED_Init();
    while(1)
    {
		Newsec = RTC.BCDSEC;
		//开始
        ADCCON = ADCCON | 1;
        while(!(ADCCON & (1 << 15)));
        //读取
        adc_value = ADCDAT & 0xFFF;
        // 1800mV/2^12=1800/4096=0.44
        adc_value = adc_value * 0.44;
		if(adc_value >= 0 & adc_value <= 500)
			n = 1;
		if(adc_value >= 501 & adc_value <= 1000)
			n = 2;
		if(adc_value >= 1001 & adc_value <= 1500)
			n = 3;
		if(adc_value >= 1501 & adc_value <= 1800)
			n = 4;
		switch(n)
		{
			case 1:								
				GPX1.DAT = GPX1.DAT & (~1);//LED3_OFF
				GPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFF
				GPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFF
				if(Newsec != Oldsec)
				{
					if(flag == 1)
					{
        				printf("20%x-%x-%x %x %x:%x:%x  adc_value = %d mV\n",RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,RTC.BCDWEEK,RTC.BCDHOUR,RTC.BCDMIN,RTC.BCDSEC,adc_value);
						GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ON
						flag = 0;						
					}else{
						GPX2.DAT = GPX2.DAT & (~(1 << 7));//LED2_OFF
						printf("20%x-%x-%x %x %x:%x:%x  adc_value = %d mV\n",RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,RTC.BCDWEEK,RTC.BCDHOUR,RTC.BCDMIN,RTC.BCDSEC,adc_value);
						flag = 1;
					}	
					Oldsec = Newsec;			
				} 
				break;
			case 2:
				GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ON	
				GPX1.DAT = GPX1.DAT | 1;//LED3_ON
				GPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFF
				GPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFF
				break;
			case 3:
				GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ON
				GPX1.DAT = GPX1.DAT | 1;//LED3_ON
				GPF3.DAT = GPF3.DAT | (1 << 4);//LED4_ON
				GPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFF
				break;
			case 4:
				GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ON
				GPX1.DAT = GPX1.DAT | 1;//LED3_ON
				GPF3.DAT = GPF3.DAT | (1 << 4);//LED4_ON
				GPF3.DAT = GPF3.DAT | (1 << 5);//LED5_ON
				break;
			default:
				GPX2.DAT = GPX2.DAT & (~(1 << 7));//LED2_OFF
				GPX1.DAT = GPX1.DAT & (~1);//LED3_OFF
				GPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFF
				GPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFF
				break;
		}  
	}
	return 0;
}



















