很多处理器都有RTC实时时钟功能,s3c2440也提供了这个功能,其功能主要是:实时时钟、闹钟、tick中断等。RTC的操作比较简单。读写时RTCCON最低位应设置为1,不读写时设置为0以免误修改RTC相应寄存器。
BCDSEC,BCDMIN,BCDHOUR,BCDDAY,BCDDATE,BCDMON,BCDYEAR可以设置和读取RTC的值,在编程中需要注意一秒只差的问题(具体可查看芯片手册),所以在BCDSEC值为0时需要重新读取RTC相应寄存器,防止误差,这点需要特别注意。
tick中断可为RTOS提供中断时钟,其周期计算如下:
可在TICNT设置相应位。达到周期产生中断。
闹钟功能在RTCALM允许使能。在ALMSEC、ALMMIN、ALMHOUR、ALMDATE、ALMMON、ALMYEAR中设置闹钟值,到达时间后产生相应中断。
还有一点需要注意,s3c2440的RTC以BCD码进行读写,所以要以十进制操作应做相应转换。RTC操作比较简单,这里不再作详细介绍,具体可查看芯片手册。测试:将相应时间写入RTC、设置相应tick中断和闹钟。通过串口显示相应时间。
代码如下:
main.c部分
#define GLOBAL_CLK 1
#include<string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "profile.h"
#include "mmu.h"
extern void RTC_Set(char year, char month, char week,
char date, char hour, char min, char sec);
extern void RTC_Read(char *year, char *month, char *week,
char *date, char *hour, char *min, char *sec);
extern void RTC_Alarm_Set(char year, char mon, char date,
char hour, char min, char sec);
extern void RTC_Init(void);
extern void RTC_Tick(void);
extern void RTC_Alarm(void);
extern char tick_flag, alarm_flag;
void delay(int num);
void delay(int num)
{
int i, j, k;
for(i=0;i<num;i++)
for(j=0;j<1000;j++)
for(k=0;k<1000;k++);
}
void Main(void)
{
char data[7] = {0};
char *week_str[7] = {"Mon", "Tue", "Wed",
"Thu", "Fri", "Sat", "Sun"};
char *week;
int count = 0;
rGPBCON=(1<<0);
rGPBDAT=(0<<0);//关闭蜂鸣器
MMU_Init();//地址的重映射
RTC_Init();
RTC_Tick();
RTC_Alarm();
RTC_Set(13, 9, 6, 7, 19, 59, 12);
RTC_Alarm_Set(13, 9, 7, 20, 0, 0);
while ( 1 ){
RTC_Read(&data[0], &data[1], &data[2],
&data[3], &data[4], &data[5], &data[6]);
switch ( data[2]){
case 1 : week = week_str[0] ;
break;
case 2 : week = week_str[1];
break;
case 3 : week = week_str[2];
break;
case 4 : week = week_str[3];
break;
case 5 : week = week_str[4];
break;
case 6 : week = week_str[5];
break;
case 7 : week = week_str[6];
break;
default: break;
}
Uart_Printf("\n%d年,%d月,%d日,星期%s,%d点,%d分,%d秒\n",2000+data[0],
data[1], data[3], week, data[4], data[5], data[6]);
if (1 == alarm_flag){
Uart_Printf("\nALARM:%d年,%d月,%d日,%d点,%d分,%d秒\n",2000+data[0],
data[1], data[3], data[4], data[5], data[6]);
alarm_flag = 0;
}
if (1 == tick_flag){
count++;
Uart_Printf("\nTICK:%d\n", count);
tick_flag = 0;
}
delay(50);
}
}
RTC.c部分
#include "2440addr.h"
/*定义用户中断标志*/
char tick_flag = 0, alarm_flag = 0;
void __irq RTC_alarm_interrupt(void);
void __irq RTC_tick_interrupt(void);
/*RTC初始化*/
void RTC_Init(void)
{
rINTMSK &= ~(1<<30 | 1<<8);//RTC中断使能
pISR_TICK = (unsigned)RTC_tick_interrupt;
pISR_RTC = (unsigned)RTC_alarm_interrupt;
}
/*RTC设置*/
void RTC_Set(char year, char month, char week,
char date, char hour, char min, char sec)
{
rRTCCON = 1;
rBCDYEAR = year;
rBCDMON = ((month / 10)<<4) | (month % 10);
rBCDDAY = week;
rBCDDATE = ((date / 10)<<4) | (date % 10);
rBCDHOUR = ((hour / 10)<<4) | (hour % 10);
rBCDMIN = ((min / 10)<<4) | (min % 10);
rBCDSEC = ((sec / 10)<<4) | (sec % 10);
rRTCCON &= ~1;
}
/*读取RTC*/
void RTC_Read(char *year, char *month, char *week,
char *date, char *hour, char *min, char *sec)
{
char i;
rRTCCON = 1;
*year = rBCDYEAR;
*month = (rBCDMON>>4) * 10 + (rBCDMON & 0x0f);
*week = rBCDDAY;
*date = (rBCDDATE>>4) * 10 + (rBCDDATE & 0x0f);
*hour = (rBCDHOUR>>4) * 10 + (rBCDHOUR & 0x0f);
*min = (rBCDMIN>>4) * 10 + (rBCDMIN & 0x0f);
if ((*sec = rBCDSEC) == 0){
*year = rBCDYEAR;
*month = (rBCDMON>>4) * 10 + (rBCDMON & 0x0f);
*week = rBCDDAY;
*date = (rBCDDATE>>4) * 10 + (rBCDDATE & 0x0f);
*hour = (rBCDHOUR>>4) * 10 + (rBCDHOUR & 0x0f);
*min = (rBCDMIN>>4) * 10 + (rBCDMIN & 0x0f);
}
*sec = (rBCDSEC>>4) * 10 + (rBCDSEC & 0x0f);
rRTCCON &= ~1;
}
/*RTC tick时钟设置*/
void RTC_Tick(void)
{
rTICNT &= ~0xff;
rTICNT |= (1<<7 | 63);
}
/*RTC 闹钟初始化*/
void RTC_Alarm(void)
{
rRTCALM &= ~0xff;
rRTCALM |= 0xff;
}
/*RTC 闹钟设置*/
void RTC_Alarm_Set(char year, char mon, char date,
char hour, char min, char sec)
{
rALMYEAR = year;
rALMMON = ((mon / 10)<<4) | mon % 10;
rALMDATE = ((date / 10)<<4) | date % 10;
rALMHOUR = ((hour / 10)<<4) | hour % 10;
rALMMIN = ((min / 10)<<4) | min % 10;
rALMSEC = ((sec / 10)<<4) | sec % 10;
}
/*RTC 闹钟中断服务*/
void __irq RTC_alarm_interrupt(void)
{
rSRCPND |= 1<<30;//清除中断
rINTPND |= 1<<30;
alarm_flag = 1;//设置用户中断标志
}
/*RTC tick中断服务*/
void __irq RTC_tick_interrupt(void)
{
rSRCPND |= 1<<8;//清除中断
rINTPND |= 1<<8;
tick_flag = 1;//设置用户中断标志
}
运行结果如下:
源代码下载地址:http://download.csdn.net/detail/a16839678/6232721