目录
一、ADC小作业
二、RTC简介
三、Exynos_4412下的RTC控制器
四、RTC中的寄存器
五、RTC编程
六、RTC小作业
电压在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;//12ADCCON = ADCCON | (1 << 16);//使能ADC分频器ADCCON = ADCCON | (1 << 14);//100/(19+1)=5MHz 5 / 5 = 1MHzADCCON = 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.44adc_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_ONdelay(1000000);GPX2.DAT = GPX2.DAT & (~(1 << 7));//LED2_OFFdelay(1000000);GPX1.DAT = GPX1.DAT & (~1);//LED3_OFFGPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFFGPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFFbreak;case 2:GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ON GPX1.DAT = GPX1.DAT | 1;//LED3_ONGPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFFGPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFFbreak;case 3:GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ONGPX1.DAT = GPX1.DAT | 1;//LED3_ONGPF3.DAT = GPF3.DAT | (1 << 4);//LED4_ONGPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFFbreak;case 4:GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ONGPX1.DAT = GPX1.DAT | 1;//LED3_ONGPF3.DAT = GPF3.DAT | (1 << 4);//LED4_ONGPF3.DAT = GPF3.DAT | (1 << 5);//LED5_ONbreak;default:GPX2.DAT = GPX2.DAT & (~(1 << 7));//LED2_OFFGPX1.DAT = GPX1.DAT & (~1);//LED3_OFFGPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFFGPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFFbreak;}printf("adc_value = %d mV\n",adc_value);}return 0;
}
RTC(Real Time Clock)即实时时钟,它是一个可以为系统提供精确的时间基准的元器件,RTC一般采用精度较高的晶振作为时钟源,有些RTC为了在主电源掉电时还可以工作,需要外加电池供电

比如以前的手机,扣掉电池在安上时间就不准了,而现在的电子产品不会出现这个问题是因为他有备用电源。由于它只有一个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的时钟,来给秒使用

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



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

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

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

电压在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 2023RTC.BCDMON = 0x1; //1RTC.BCDDAY = 0x5; //5RTC.BCDWEEK = 0x4; //星期四RTC.BCDHOUR = 0x11; //11RTC.BCDMIN = 0x32; //32RTC.BCDSEC = 0x50; //50s//关闭RTC控制RTCCON = RTCCON & 0;}
void ADC_Init()
{//12ADCCON = ADCCON | (1 << 16);//使能ADC分频器ADCCON = ADCCON | (1 << 14);//100/(19+1)=5MHz 5 / 5 = 1MHzADCCON = 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.44adc_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_OFFGPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFFGPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFFif(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_ONflag = 0; }else{GPX2.DAT = GPX2.DAT & (~(1 << 7));//LED2_OFFprintf("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_ONGPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFFGPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFFbreak;case 3:GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ONGPX1.DAT = GPX1.DAT | 1;//LED3_ONGPF3.DAT = GPF3.DAT | (1 << 4);//LED4_ONGPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFFbreak;case 4:GPX2.DAT = GPX2.DAT | (1 << 7);//LED2_ONGPX1.DAT = GPX1.DAT | 1;//LED3_ONGPF3.DAT = GPF3.DAT | (1 << 4);//LED4_ONGPF3.DAT = GPF3.DAT | (1 << 5);//LED5_ONbreak;default:GPX2.DAT = GPX2.DAT & (~(1 << 7));//LED2_OFFGPX1.DAT = GPX1.DAT & (~1);//LED3_OFFGPF3.DAT = GPF3.DAT & (~(1 << 4));//LED4_OFFGPF3.DAT = GPF3.DAT & (~(1 << 5));//LED5_OFFbreak;} }return 0;
}
