實時時鐘(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); }