原文http://blog.csdn.net/z2200903505/article/details/7549556
实时时钟(RTC)单元可以在当系统电源关闭后通过备用电池工作。RTC可以通过使用STRB/LDRB ARM操
作发送8位二-十进制交换码(BCD)值数据给CPU。这些数据包括年、月、日、星期、时、分和秒的时间信息。
RTC 单元工作在外部32.768kHz晶振并且可以执行闹钟功能。
RTC操作比较简单,寄存器的设置在数据手册上写的很详细,就不写了,贴一个RTC代码,该程序参考了天翔的RTC程序代码,主要是他写的比较好,都模块化了,我修改了他的代码,有闹钟(利用蜂鸣器),在TQ2440 板子上能运行,程序功能:串口每秒显示一次时间并且LED1闪一次,在闹钟设置中,秒为20时,显示闹钟时间并蜂鸣器发声几秒钟。
- #include "2440addr.h"
- #include "Option.h"
- #include "2440lib.h"
- #include "def.h"
- #define LED1_ON (rGPBDAT &=~(1<<5))
- #define LED1_OFF (rGPBDAT |=(1<<5) )
- void __irq RTC_tickHandler(void);
- void __irq RTC_alarmHandler(void);
- U8 alarmflag=0;
- typedef struct Date //定义一个表示日期时间的结构体
- { U16 year;
- U8 month;
- U8 day;
- U8 week_day;
- U8 hour;
- U8 minute;
- U8 second;
- }date;
- date C_date;
- char *week_num[7]={ "SUN","MON", "TUES", "WED", "THURS","FRI", "SAT" };//定义一个指针数组
- void Beep_Freq_Set( U32 freq )
- {
- rGPBCON &=~3;
- rGPBCON |=2; //设置GPB0为OUT0
- rGPBUP=0x0; //使能上拉
- rTCFG0 &=~0xff;
- rTCFG0 |=15; //预分频值为15
- rTCFG1 &=~0x0f;
- rTCFG1 |=0x02; //分频值为8
- rTCNTB0 = (PCLK>>7)/freq; //设定定时器0计数缓冲器的值
- rTCMPB0 = rTCNTB0>>1; // 定时器0比较缓冲器的值,PWM输出占空比50%
- rTCON &= ~0x1f;
- rTCON |= 0xb; //自动重载,关闭变相,手动更新,开启定时器0
- rTCON &= ~2; //清除手动更新位
- }
- void Beep_Stop( void )
- {
- rGPBCON &= ~3; //set GPB0 as output
- rGPBCON |= 1;
- rGPBDAT &= ~1; //输出低电平
- }
- void delay(int x)
- {
- int i,j;
- for(i=0;i<x;i++)
- for(j=0;j<1000000;j++);
- }
- /********************************
- *
- * 设置实时时钟日期、 时间
- *
- *********************************/
- void RTC_setdate(date *p_date)
- {
- rRTCCON=0x01; //RTC读写使能,BCD时钟、计数器、无复位
- rBCDYEAR = p_date->year;
- rBCDMON = p_date->month;
- rBCDDATE = p_date->day;
- rBCDDAY = p_date->week_day; //设置日期时间
- rBCDHOUR = p_date->hour;
- rBCDMIN = p_date->minute;
- rBCDSEC = p_date->second;
- rRTCCON=0x00; //RTC读写禁止,BCD时钟、计数器、无复位
- }
- /********************************
- *
- * 读取实时时钟日期、 时间
- *
- *********************************/
- void RTC_getdate(date *p_date)
- {
- rRTCCON=0x01; //RTC读写使能,BCD时钟、计数器、无复位
- p_date->year = rBCDYEAR+0x2000;
- p_date->month = rBCDMON;
- p_date->day = rBCDDATE;
- p_date->week_day = rBCDDAY; //读取日期时间
- p_date->hour = rBCDHOUR;
- p_date->minute = rBCDMIN;
- p_date->second = rBCDSEC;
- rRTCCON=0x00; //RTC读写禁止,BCD时钟、计数器、无复位
- }
- /********************************
- *
- * TICK中断初始化
- *
- *********************************/
- void RTC_tickIRQ_Init(U8 tick)
- {
- ClearPending(BIT_TICK); //清除标志位
- EnableIrq(BIT_TICK); //使能中断源
- pISR_TICK=(unsigned)RTC_tickHandler; //中断函数入口地址
- rRTCCON=0x00;
- rTICNT=(tick&0x7f)|0x80; //使能中断
- }
- /********************************
- *
- * 设置闹钟日期、 时间及其闹钟唤醒模式
- *
- *********************************/
- void RTC_alarm_setdate(date *p_date,U8 mode)
- {
- rRTCCON = 0x01;
- rALMYEAR = p_date->year;
- rALMMON = p_date->month;
- rALMDATE = p_date->day;
- rALMHOUR = p_date->hour;
- rALMMIN = p_date->minute;
- rALMSEC = p_date->second;
- rRTCALM = mode; //RTC闹钟控制寄存器
- rRTCCON = 0x00;
- ClearPending(BIT_RTC); //清除标志位
- EnableIrq(BIT_RTC); //open RTC alarm INTERRUPT
- pISR_RTC = (unsigned)RTC_alarmHandler;
- }
- void Main(void)
- {
- SelectFclk(2); //设置系统时钟 400M
- ChangeClockDivider(2, 1); //设置分频 1:4:8
- CalcBusClk(); //计算总线频率
- rGPHCON &=~((3<<4)|(3<<6));
- rGPHCON |=(2<<4)|(2<<6); //GPH2--TXD[0];GPH3--RXD[0]
- rGPHUP=0x00; //使能上拉功能
- Uart_Init(0,115200);
- Uart_Select(0);
- rGPBCON &=~((3<<10)|(3<<12)|(3<<14)|(3<<16)); //对GPBCON[10:17]清零
- rGPBCON |=((1<<10)|(1<<12)|(1<<14)|(1<<16)); //设置GPB5~8为输出
- rGPBUP &=~((1<<5)|(1<<6)|(1<<7)|(1<<8)); //设置GPB5~8的上拉功能
- rGPBDAT |=(1<<5)|(1<<6)|(1<<7)|(1<<8); //关闭LED
- Beep_Stop(); //蜂鸣器停止发声,蜂鸣器用作闹钟声
- C_date.year = 0x12;
- C_date.month = 0x05;
- C_date.day = 0x09;
- C_date.week_day = 0x03; //设置当前日期时间
- C_date.hour = 0x12;
- C_date.minute = 0x00;
- C_date.second = 0x10;
- RTC_setdate(&C_date);
- C_date.second=0x20;
- RTC_alarm_setdate(&C_date,0x41);//0x41表示使能RTC闹钟,以及使能秒时钟闹钟
- RTC_tickIRQ_Init(127); // 设置1秒钟tick一次
- Uart_Printf("\n ---实时时钟测试程序---\n");
- while(Uart_GetKey()!= ESC_KEY)
- {
- LED1_OFF;
- RTC_getdate(&C_date);
- if(alarmflag)
- {
- alarmflag=0;
- Uart_Printf("\nRTC ALARM %02x:%02x:%02x \n",C_date.hour,C_date.minute,C_date.second);
- Beep_Freq_Set(1000);
- delay(5);
- Beep_Stop();
- }
- }
- }
- /********************************
- *
- * TICK中断
- *
- *********************************/
- void __irq RTC_tickHandler(void)
- {
- ClearPending(BIT_TICK);
- LED1_ON; //刷新LED1
- Delay(500);
- RTC_getdate(&C_date);
- Uart_Printf("RTC TIME: %04x-%02x-%02x %s %02x:%02x:%02x\n", C_date.year,C_date.month,C_date.day,week_num[C_date.week_day], C_date.hour, C_date.minute, C_date.second );
- }
- /********************************
- *
- * TICK中断
- *
- *********************************/
- void __irq RTC_alarmHandler(void)
- {
- alarmflag = 1;
- ClearPending(BIT_RTC);
- }
#include "2440addr.h"
#include "Option.h"
#include "2440lib.h"
#include "def.h"
#define LED1_ON (rGPBDAT &=~(1<<5))
#define LED1_OFF (rGPBDAT |=(1<<5) )
void __irq RTC_tickHandler(void);
void __irq RTC_alarmHandler(void);
U8 alarmflag=0;
typedef struct Date //定义一个表示日期时间的结构体
{ U16 year;
U8 month;
U8 day;
U8 week_day;
U8 hour;
U8 minute;
U8 second;
}date;
date C_date;
char *week_num[7]={ "SUN","MON", "TUES", "WED", "THURS","FRI", "SAT" };//定义一个指针数组
void Beep_Freq_Set( U32 freq )
{
rGPBCON &=~3;
rGPBCON |=2; //设置GPB0为OUT0
rGPBUP=0x0; //使能上拉
rTCFG0 &=~0xff;
rTCFG0 |=15; //预分频值为15
rTCFG1 &=~0x0f;
rTCFG1 |=0x02; //分频值为8
rTCNTB0 = (PCLK>>7)/freq; //设定定时器0计数缓冲器的值
rTCMPB0 = rTCNTB0>>1; // 定时器0比较缓冲器的值,PWM输出占空比50%
rTCON &= ~0x1f;
rTCON |= 0xb; //自动重载,关闭变相,手动更新,开启定时器0
rTCON &= ~2; //清除手动更新位
}
void Beep_Stop( void )
{
rGPBCON &= ~3; //set GPB0 as output
rGPBCON |= 1;
rGPBDAT &= ~1; //输出低电平
}
void delay(int x)
{
int i,j;
for(i=0;i<x;i++)
for(j=0;j<1000000;j++);
}
/********************************
*
* 设置实时时钟日期、 时间
*
*********************************/
void RTC_setdate(date *p_date)
{
rRTCCON=0x01; //RTC读写使能,BCD时钟、计数器、无复位
rBCDYEAR = p_date->year;
rBCDMON = p_date->month;
rBCDDATE = p_date->day;
rBCDDAY = p_date->week_day; //设置日期时间
rBCDHOUR = p_date->hour;
rBCDMIN = p_date->minute;
rBCDSEC = p_date->second;
rRTCCON=0x00; //RTC读写禁止,BCD时钟、计数器、无复位
}
/********************************
*
* 读取实时时钟日期、 时间
*
*********************************/
void RTC_getdate(date *p_date)
{
rRTCCON=0x01; //RTC读写使能,BCD时钟、计数器、无复位
p_date->year = rBCDYEAR+0x2000;
p_date->month = rBCDMON;
p_date->day = rBCDDATE;
p_date->week_day = rBCDDAY; //读取日期时间
p_date->hour = rBCDHOUR;
p_date->minute = rBCDMIN;
p_date->second = rBCDSEC;
rRTCCON=0x00; //RTC读写禁止,BCD时钟、计数器、无复位
}
/********************************
*
* TICK中断初始化
*
*********************************/
void RTC_tickIRQ_Init(U8 tick)
{
ClearPending(BIT_TICK); //清除标志位
EnableIrq(BIT_TICK); //使能中断源
pISR_TICK=(unsigned)RTC_tickHandler; //中断函数入口地址
rRTCCON=0x00;
rTICNT=(tick&0x7f)|0x80; //使能中断
}
/********************************
*
* 设置闹钟日期、 时间及其闹钟唤醒模式
*
*********************************/
void RTC_alarm_setdate(date *p_date,U8 mode)
{
rRTCCON = 0x01;
rALMYEAR = p_date->year;
rALMMON = p_date->month;
rALMDATE = p_date->day;
rALMHOUR = p_date->hour;
rALMMIN = p_date->minute;
rALMSEC = p_date->second;
rRTCALM = mode; //RTC闹钟控制寄存器
rRTCCON = 0x00;
ClearPending(BIT_RTC); //清除标志位
EnableIrq(BIT_RTC); //open RTC alarm INTERRUPT
pISR_RTC = (unsigned)RTC_alarmHandler;
}
void Main(void)
{
SelectFclk(2); //设置系统时钟 400M
ChangeClockDivider(2, 1); //设置分频 1:4:8
CalcBusClk(); //计算总线频率
rGPHCON &=~((3<<4)|(3<<6));
rGPHCON |=(2<<4)|(2<<6); //GPH2--TXD[0];GPH3--RXD[0]
rGPHUP=0x00; //使能上拉功能
Uart_Init(0,115200);
Uart_Select(0);
rGPBCON &=~((3<<10)|(3<<12)|(3<<14)|(3<<16)); //对GPBCON[10:17]清零
rGPBCON |=((1<<10)|(1<<12)|(1<<14)|(1<<16)); //设置GPB5~8为输出
rGPBUP &=~((1<<5)|(1<<6)|(1<<7)|(1<<8)); //设置GPB5~8的上拉功能
rGPBDAT |=(1<<5)|(1<<6)|(1<<7)|(1<<8); //关闭LED
Beep_Stop(); //蜂鸣器停止发声,蜂鸣器用作闹钟声
C_date.year = 0x12;
C_date.month = 0x05;
C_date.day = 0x09;
C_date.week_day = 0x03; //设置当前日期时间
C_date.hour = 0x12;
C_date.minute = 0x00;
C_date.second = 0x10;
RTC_setdate(&C_date);
C_date.second=0x20;
RTC_alarm_setdate(&C_date,0x41);//0x41表示使能RTC闹钟,以及使能秒时钟闹钟
RTC_tickIRQ_Init(127); // 设置1秒钟tick一次
Uart_Printf("\n ---实时时钟测试程序---\n");
while(Uart_GetKey()!= ESC_KEY)
{
LED1_OFF;
RTC_getdate(&C_date);
if(alarmflag)
{
alarmflag=0;
Uart_Printf("\nRTC ALARM %02x:%02x:%02x \n",C_date.hour,C_date.minute,C_date.second);
Beep_Freq_Set(1000);
delay(5);
Beep_Stop();
}
}
}
/********************************
*
* TICK中断
*
*********************************/
void __irq RTC_tickHandler(void)
{
ClearPending(BIT_TICK);
LED1_ON; //刷新LED1
Delay(500);
RTC_getdate(&C_date);
Uart_Printf("RTC TIME: %04x-%02x-%02x %s %02x:%02x:%02x\n", C_date.year,C_date.month,C_date.day,week_num[C_date.week_day], C_date.hour, C_date.minute, C_date.second );
}
/********************************
*
* TICK中断
*
*********************************/
void __irq RTC_alarmHandler(void)
{
alarmflag = 1;
ClearPending(BIT_RTC);
}