实时时钟RTC新型设计.docx

上传人:b****3 文档编号:5354912 上传时间:2022-12-15 格式:DOCX 页数:17 大小:162.06KB
下载 相关 举报
实时时钟RTC新型设计.docx_第1页
第1页 / 共17页
实时时钟RTC新型设计.docx_第2页
第2页 / 共17页
实时时钟RTC新型设计.docx_第3页
第3页 / 共17页
实时时钟RTC新型设计.docx_第4页
第4页 / 共17页
实时时钟RTC新型设计.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

实时时钟RTC新型设计.docx

《实时时钟RTC新型设计.docx》由会员分享,可在线阅读,更多相关《实时时钟RTC新型设计.docx(17页珍藏版)》请在冰豆网上搜索。

实时时钟RTC新型设计.docx

实时时钟RTC新型设计

关于RTC的万年历实验

一.目的:

1.通过实验加深对实时时钟RTC结构和工作原理的理解和相关寄存器的应用;

2.通过UART传输数据并由PC机终端软件EasyARM.exe显示,复习异步串行口UART内容;

3.通过对《深入浅出ARM7》中万年历显示实验程序的修改添加,实现闹钟功能,以及通过按键可实现时钟和闹钟时间的调整。

二.仪器:

ARM开发板一块、

装有ADS1.2及EasyJTAG仿真器的电脑一台

三.实验原理:

1.RTC功能结构如下图所示:

2.相关寄存器描述:

(1)中断位置寄存器—InterruptLocationRegister(ILR–0xE0024000)

(2)时钟控制寄存器—ClockControlRegister(CCR–0xE0024008)

(3)计数器增量中断寄存器—CounterIncrementInterruptRegister(CIIR–0xE002400C)

计数器增量中断寄存器可使计数器每次增加时产生一次中断。

在中断位置寄存器的位0(ILR[0])写入1之前,该中断一直保持有效。

(4)报警屏蔽寄存器—AlarmMaskRegister(AMR–0xE0024010)

对于报警功能来说,要产生中断,非屏蔽的报警寄存器必须匹配对应的时间计数器。

只有当计数器之间的比较第一次从不匹配到匹配时,才会产生中断。

向中断位置寄存器(ILR)的位写入1,会清除相应的中断。

如果所有屏蔽位都置位,报警将被禁止。

四.实验程序:

(见附录。

五.实验结果:

通过EasyARM的万年历功能实现了实时时钟和闹钟时间的显示。

同时LED1每秒间隔闪烁,到预设的闹钟时间(即报警时间)时,LED8闪烁三次后蜂鸣器开始播放“虹彩妹妹”的音乐,播放音乐同时LED1跟随音乐节奏闪烁。

按键KEY1按一次,实时时钟计数停止,LED1长亮指示秒调整状态,可通过KEY3(减一)、KEY4(加一)调节秒。

KEY1按两次,进入分钟调整状态,可通过KEY3(减一)、KEY4(加一)调节分钟。

依次类推,可依次调整秒、分、时、星期、日、月、年;按键KEY2按一次,EasyARM显示闹钟时间,类似实时时钟调整功能,可通过按KEY2依次调整闹钟时间(由于程序中报警屏蔽寄存器AMR只是没屏蔽秒报警值,故只要所设的秒报警值与时钟秒计数值相等就会产生报警)。

每次按键时,都有LED8闪烁一次和BEEP蜂鸣一声提示。

六.调试总结和体会:

经过整整一天的努力和老师同学的帮助,终于将实验调试成功了。

一开始,经过反复的调试终于实现了报警功能,然后在实验室通过老师的指导,实现了播放音乐过程中时钟实时更新功能以及实现LED灯跟随音乐节奏闪烁。

再经过程序的改进,实现了实时时钟和闹钟调整功能。

在同学建议下,添加了LED灯指示调整时间点(秒、分、时、星期、日、月、年)功能。

在调试过程中,总结了一些错误原因分析以及编程注意点:

①刚开始时,由于没注意格式书写,程序看起来很乱,在老师的建议下,将程序中函数的正反大括号对齐,这样程序变得更直观。

②经过调试以及和同学的探讨,成功实现了KEY3和KEY4按键在最小值和最大值的变化。

其中关键是使用类似if(SEC==0)SEC=59;elseSEC--;和if(SEC==59)SEC=0;elseSEC++;而自己原来是将类似SEC--和SEC++放在前面,由于SEC寄存器不能取-1值,所以SEC--放在前面时,不能减到00的状态,直接从01到59了。

原来只是个顺序问题,让程序变得如此微妙。

③在调试时,由于错在将#defineKEY11<<16后面多加了“;”导致调试时显示很多错误。

从中发现,有时会因一个地方出错导致显示很多错误。

同样的,有时也会是调试时只显示一个错误,但其实有多个地方有错。

以后要注意这点。

④在调整星期时发现,当7加一时竟变成0了。

和同学讨论后得知原来星期寄存器只用了3为(26:

24),所以当7加一时为8但第四位没被获取故只得0。

以后多了解寄存器地址、结构等内部原理知识,这样一些问题就会迎刃而解。

⑤调试时发现,当双击“{”或“}”所在行,则其所包含的函数体会用黑色显示,如下图,这样即可快速找到“{”或“}”的匹配括号,因此也可以很方便用来查错。

⑥通过调试,掌握了按键释放程序的应用。

程序中采用类似while((IO0PIN&KEY4)==0);语句,其作用与while(!

(IO0PIN&KEY4));等价得知“!

(IO0PIN&KEY4)”并不是取反的意思。

程序中KEY1和KEY2采用等待按键释放,而为了按住按键时自动快速加减,KEY3和KEY4不用等待按键释放程序。

这次实验,我习得了不少,从中体会到多调试多实际操作练习将会发现很多的问题,同时在解决问题过程中可以获得很多知识。

再次,感谢老师的指导和同学的帮助。

 

附录:

#include"config.h"

#include"music.h"

#defineBEEP1<<7

constuint32KEY1=1<<16;

constuint32KEY2=1<<17;

constuint32KEY3=1<<18;

constuint32KEY4=1<<19;

constuint32LED8=1<<25;

constuint32LED1=1<<18;

constuint32LED2=1<<19;

constuint32LED3=1<<20;

constuint32LED4=1<<21;

constuint32LED5=1<<22;

constuint32LED6=1<<23;

constuint32LED7=1<<24;

constuint32LEDS8=0xFF<<18;

//定义串口模式设置的数据结构

constuint32HCMM[]=

{

_LA,_SO,_MI,_LA,_SO,_MI,

_LA,_LA,_SO,_LA,

_LA,_SO,_MI,_LA,_SO,_MI,

_RE,_RE,_DO,_RE,

_MI,_MI,_SO,_LA,_DO1,_LA,_SO,

_MI,_MI,_SO,_DO,

_MI,_MI,_MI,_MI,_MI,

_1LA,_1LA,_1SO,_1LA,

};

/*歌曲节拍*/

constuint32HCMM_L[]=

{

_4,_8,_8,_4,_8,_8,

_8,_4,_8,_2,

_4,_8,_8,_4,_8,_8,

_8,_4,_8,_2,

_4,_8,_8,_8,_8,_8,_8,

_8,_4,_8,_2,

_4,_4,_4,_8,_8,

_8,_4,_8,_2,

};

typedefstructUartMode

{

uint8datab;//字长度5/6/7/8

uint8stopb;//停止位1/2

uint8parity;//奇偶校验0-无校验,1-奇校验,2-偶校验

}UARTMODE;

voidDelay(uint8dly)

{

uint32i;

for(;dly>0;dly--)

{for(i=0;i<0x7FFFF;i++);}

}

uint8UART0_Init(uint32baud,UARTMODEset)

{

uint32bak;

//参数过滤

if((0==baud)||(baud>115200))return(0);

if((set.datab<5)||(set.datab>8))return(0);

if((0==set.stopb)||(set.stopb>2))return(0);

if(set.parity>4)return(0);

//设置串口波特率

U0LCR=0x80;//DLAB=1

bak=(Fpclk>>4)/baud;

U0DLM=bak>>8;

U0DLL=bak&0xff;

//设置串口模式

bak=set.datab-5;

if(2==set.stopb)bak|=0x04;

if(0!

=set.parity)

{

set.parity=set.parity-1;

bak|=0x08;

}

bak|=set.parity<<4;

U0LCR=bak;

return(0);

}

voidSendByte(uint8data)

{

U0THR=data;

while((U0LSR&0X20)==0);//等待数据发送

}

voidPC_DispChar(uint8no,uint8chr)

{

SendByte(0xff);

SendByte(0x81);

SendByte(no);

SendByte(chr);

SendByte(0x00);

}

voidabd(void)

{

IO0CLR=BEEP;

IO1CLR=LED8;

Delay(5);

IO0SET=BEEP;

IO1SET=LED8;

}

uint8constSHOWTABLE[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

voidSendTimeRtc(void)

{

uint32datas;

uint32times;

uint32bak;

times=CTIME0;//读取完整的时钟寄存器

datas=CTIME1;

bak=(datas>>16)&0xfff;//获取年

PC_DispChar(0,SHOWTABLE[bak/1000]);

bak=bak%1000;

PC_DispChar(1,SHOWTABLE[bak/100]);

bak=bak%100;

PC_DispChar(2,SHOWTABLE[bak/10]);

PC_DispChar(3,SHOWTABLE[bak%10]);

bak=(datas>>8)&0x0f;//获取月

PC_DispChar(4,SHOWTABLE[bak/10]);

PC_DispChar(5,SHOWTABLE[bak%10]);

bak=datas&0x1f;//获取日

PC_DispChar(6,SHOWTABLE[bak/10]);

PC_DispChar(7,SHOWTABLE[bak%10]);

bak=(times>>24)&0x07;//获取星期

PC_DispChar(8,SHOWTABLE[bak]);

bak=(times>>16)&0x1f;//获取小时

PC_DispChar(9,SHOWTABLE[bak/10]);

PC_DispChar(10,SHOWTABLE[bak%10]);

bak=(times>>8)&0x3f;//获取分钟

PC_DispChar(11,SHOWTABLE[bak/10]);

PC_DispChar(12,SHOWTABLE[bak%10]);

bak=times&0x3f;//获取秒钟

PC_DispChar(13,SHOWTABLE[bak/10]);

PC_DispChar(14,SHOWTABLE[bak%10]);

}

voidSendTimeRtc1(void)

{

PC_DispChar(0,SHOWTABLE[ALYEAR/1000]);

ALYEAR=ALYEAR%1000;

PC_DispChar(1,SHOWTABLE[ALYEAR/100]);

ALYEAR=ALYEAR%100;

PC_DispChar(2,SHOWTABLE[ALYEAR/10]);

PC_DispChar(3,SHOWTABLE[ALYEAR%10]);

PC_DispChar(4,SHOWTABLE[ALMON/10]);

PC_DispChar(5,SHOWTABLE[ALMON%10]);

PC_DispChar(6,SHOWTABLE[ALDOM/10]);

PC_DispChar(7,SHOWTABLE[ALDOM%10]);

PC_DispChar(8,SHOWTABLE[ALDOW]);

PC_DispChar(9,SHOWTABLE[ALHOUR/10]);

PC_DispChar(10,SHOWTABLE[ALHOUR%10]);

PC_DispChar(11,SHOWTABLE[ALMIN/10]);

PC_DispChar(12,SHOWTABLE[ALMIN%10]);

PC_DispChar(13,SHOWTABLE[ALSEC/10]);

PC_DispChar(14,SHOWTABLE[ALSEC%10]);

}

void__irqRTC_Int(void)

{

uint32i,num1;

if((IO1SET&LED1)==0)IO1SET=LED1;

elseIO1CLR=LED1;

if(num1!

=0)SendTimeRtc1();

elseSendTimeRtc();

if(ILR==0x03)

{

for(i=0;i<3;i++)

{

IO1CLR=LED8;

Delay(3);

IO1SET=LED8;

Delay(3);

}

PINSEL0=(PINSEL0&0xFFFF3FFF)|(0x02<<14);//P0.7选择PWM2功能

for(i=0;i

{

if((IO1SET&LED1)==0)IO1SET=LED1;

elseIO1CLR=LED1;

PWMMR0=Fpclk/HCMM[i];//设置输出频率

PWMLER=0x05;//更新匹配值后,必须锁存

Delay(HCMM_L[i]);//延时,控制播放速度

if(num1!

=0)SendTimeRtc1();

elseSendTimeRtc();

}

PINSEL0=(PINSEL0&0xFFFF3FFF)|(0x00<<14);//P0.7取消PWM2功能

}

ILR=0x03;

VICVectAddr=0;

}

voidRTCInit(void)

{

YEAR=2011;

MONTH=04;

DOM=28;

DOW=4;

HOUR=10;

MIN=29;

SEC=50;

ALYEAR=2003;

ALMON=04;

ALDOM=01;

ALDOW=4;

ALHOUR=06;

ALMIN=42;

ALSEC=20;

AMR=0xFE;//设置报警屏蔽寄存器,设置秒值与报警寄存器比较。

CIIR=0x01;//设置秒值的增量产生1次中断

ILR=0x03;

CCR=0x11;//启动RTC

}

intmain(void)

{

uint8i,num=0,num1=0;

UARTMODEuart0_set;

PINSEL0=0x00000005;//连接IO到UART0

PINSEL2=PINSEL2&(~0x08);

IO1DIR=LEDS8;

IO1SET=LEDS8;

IO0DIR=BEEP;

IO0SET=BEEP;

PWMPR=0x00;//不分频,计数频率为Fpclk

PWMMCR=0x02;//设置PWMMR0匹配时复位PWMTC

PWMPCR=0x0400;//允许PWM2输出,单边PWM

PWMMR0=Fpclk/1000;

PWMMR2=PWMMR0/2;//50%占空比

PWMLER=0x05;//PWM0和PWM2匹配锁存

PWMTCR=0x02;//复位PWMTC

PWMTCR=0x09;//启动PWM输出

//IRQEnable();//中断使能,程序可用查询方式,也可以用中断方式。

VICIntSelect=0x00;//设置所有中断连接IRQ中断

VICVectCntl0=0x20|13;//分配通道0

VICVectAddr0=(int)RTC_Int;//设置中断服务程序地址

VICIntEnable=(1<<13);//使能RTC中断

uart0_set.datab=8;

uart0_set.stopb=1;

uart0_set.parity=0;

UART0_Init(115200,uart0_set);

U0FCR=0x01;//FIFO使能

RTCInit();

while

(1)

{

if(ILR==0x01)

{

if((IO1SET&LED1)==0)IO1SET=LED1;

elseIO1CLR=LED1;

if(num1!

=0)SendTimeRtc1();

elseSendTimeRtc();

if(ILR==0x03)

{

for(i=0;i<3;i++)

{

IO1CLR=LED8;

Delay(3);

IO1SET=LED8;

Delay(3);

}

PINSEL0=(PINSEL0&0xFFFF3FFF)|(0x02<<14);//P0.7选择PWM2功能

for(i=0;i

{

if((IO1SET&LED1)==0)IO1SET=LED1;

elseIO1CLR=LED1;

PWMMR0=Fpclk/HCMM[i];//设置输出频率

PWMLER=0x05;//更新匹配值后,必须锁存

Delay(HCMM_L[i]);//延时,控制播放速度

if(num1!

=0)SendTimeRtc1();

elseSendTimeRtc();

}

PINSEL0=(PINSEL0&0xFFFF3FFF)|(0x00<<14);//P0.7取消PWM2功能

}

ILR=0x03;

}

if((IO0PIN&KEY1)==0)

{

Delay

(1);

if((IO0PIN&KEY1)==0)

{

abd();

CCR=0x00;

num++;

switch(num)

{

case1:

IO1CLR=LED1;break;

case2:

IO1SET=LED1;IO1CLR=LED2;break;

case3:

IO1SET=LED2;IO1CLR=LED3;break;

case4:

IO1SET=LED3;IO1CLR=LED4;break;

case5:

IO1SET=LED4;IO1CLR=LED5;break;

case6:

IO1SET=LED5;IO1CLR=LED6;break;

case7:

IO1SET=LED6;IO1CLR=LED7;break;

case8:

IO1SET=LED7;num=0;CCR=0x01;break;

}

}

while((IO0PIN&KEY1)==0);//等待按键释放

}

if((IO0PIN&KEY2)==0)

{

Delay

(1);

if((IO0PIN&KEY2)==0)

{

abd();

num1++;

SendTimeRtc1();

switch(num1)

{

case1:

IO1CLR=LED1;break;

case2:

IO1SET=LED1;IO1CLR=LED2;break;

case3:

IO1SET=LED2;IO1CLR=LED3;break;

case4:

IO1SET=LED3;IO1CLR=LED4;break;

case5:

IO1SET=LED4;IO1CLR=LED5;break;

case6:

IO1SET=LED5;IO1CLR=LED6;break;

case7:

IO1SET=LED6;IO1CLR=LED7;break;

case8:

IO1SET=LED7;num1=0;break;

}

}

while((IO0PIN&KEY2)==0);//等待按键释放

}

if((IO0PIN&KEY3)==0)

{

Delay

(1);

if((IO0PIN&KEY3)==0)

{

abd();

switch(num)

{

case1:

if(SEC==0)SEC=59;elseSEC--;break;

case2:

if(MIN==0)MIN=59;elseMIN--;break;

case3:

if(HOUR==0)HOUR=23;elseHOUR--;break;

case4:

if(DOW==1)DOW=7;elseDOW--;break;

case5:

if(DOM==1)DOM=31;elseDOM--;break;

case6:

if(MONTH==1)MONTH=12;elseMONTH--;break;

case7:

if(YEAR==0)YEAR=4095;elseYEAR--;break;

case8:

break;

}

switch(num1)

{

case1:

if(ALSEC==0)ALSEC=59;elseALSEC--;break;

case2:

if(ALMIN==0)ALMIN=59;elseALMIN--;break;

case

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 成人教育 > 电大

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1