目录
一、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开头那年。或者我也活不到那个时候啊,哈哈哈
注意: 三星把星期和日的地址写反了
对于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;
}