对于2440的实时时钟操作还是比较简单的,难点的地方在于用设置串口通信来控制时钟时钟的读写设置时间和闹铃。但是用串口控制时钟终将只能用于测试,对于产品的话必然要用到显示器,或者lcd或者数码管,不过现代的时钟更加趋向于用lcd 况且能显示更多的信息。
1. 时钟的数据已经存到寄存器中了,只有读取寄存器的值就可以读出时钟,注意当秒钟为0的时候需要重新读取寄存器的值,这里有个一秒的问题。
2.数据的格式为BCD码,用4位二进制表示出十进制数,其本质还是二进制编码。
3. 数据的格式适合用结构体,还有多命令控制时用枚举类型比较好,以后要多用习惯这样的用法。
4.闹铃中断的发生,当设定的闹铃时间和时钟的时间相同时闹铃中断,其中可以有选择的使能year mon date hour min sec ,匹配时从year到sec。例如 只使能分和秒的时候,当时钟的值和设定闹铃的分和秒相同时闹铃中断,即每个小时的多少分多少秒时中断发生。这样一来就可以很灵活的运用闹铃功能了。
代码
while(!(rUTRSTAT0&0x1)) ; //wait RX ready
//temp = rURXH0 ;
return rURXH0 ;
}
/*************read RTC***************
read RTC data
if secend is 0 re-read RTC data
**************read RTC**************/
void get_rtc(RTC *prtc)
{
rRTCCON = 1 ;
prtc->year = rBCDYEAR ;
prtc->mon = rBCDMON ;
prtc->date = rBCDDATE ;
prtc->day = rBCDDAY ;
prtc->hour = rBCDHOUR ;
prtc->mini = rBCDMIN ;
prtc->sec = rBCDSEC ;
if(prtc->sec==0) //one secend diviation
{
prtc->year = rBCDYEAR ;
prtc->mon = rBCDMON ;
prtc->date = rBCDDATE ;
prtc->day = rBCDDAY ;
prtc->hour = rBCDHOUR ;
prtc->mini = rBCDMIN ;
prtc->sec = rBCDSEC ;
}
rRTCCON = 0 ;
}
/******************************************************
convent RTC data to string
the form : xx-xx-xx xx:xx:xx
*******************************************************/
void rtc_to_str(char *str_time, RTC *rtctime)
{
//year
str_time[0] = (char)((rtctime->year >> 4) + 48 ) ;
str_time[1] = (char)((rtctime->year & 0x0f) + 48) ;
str_time[2] = '-' ;
//mon
str_time[3] = (char)((rtctime->mon >> 4) + 48 ) ;
str_time[4] = (char)((rtctime->mon & 0x0f) + 48) ;
str_time[5] = '-' ;
//date
str_time[6] = (char)((rtctime->date >> 4) + 48 ) ;
str_time[7] = (char)((rtctime->date & 0x0f) + 48) ;
str_time[8] = ' ' ;
//hour
str_time[9] = (char)((rtctime->hour >> 4) + 48 ) ;
str_time[10] = (char)((rtctime->hour & 0x0f) + 48) ;
str_time[11] = ':' ;
//mini
str_time[12] = (char)((rtctime->mini >> 4) + 48 ) ;
str_time[13] = (char)((rtctime->mini & 0x0f) + 48) ;
str_time[14] = ':' ;
//sec
str_time[15] = (char)((rtctime->sec >> 4) + 48 ) ;
str_time[16] = (char)((rtctime->sec & 0x0f) + 48) ;
str_time[17] = '/0' ;
}
void str_to_RTC(char *strtime, RTC *rtctime)
{
rtctime->year = ((strtime[0]-48)<<4) + (strtime[1]-48) ;
if(strtime[2] != '-')
{
setformat = wrong ;
UART_send_string("/n setting time form error please input 's' to re-set") ;
return ;
}
rtctime->mon = ((strtime[3]-48)<<4) + (strtime[4]-48) ;
if(strtime[5] != '-')
{
setformat = wrong ;
UART_send_string("/n setting time form error please input 's' to re-set") ;
return ;
}
rtctime->date = ((strtime[6]-48)<<4) + (strtime[7]-48) ;
if(strtime[8] != ' ')
{
setformat = wrong ;
UART_send_string("/n setting time form error please input 's' to re-set") ;
return ;
}
rtctime->hour = ((strtime[9]-48)<<4) + (strtime[10]-48) ;
if(strtime[11] != ':')
{
setformat = wrong ;
UART_send_string("/n setting time form error please input 's' to re-set") ;
return ;
}
rtctime->mini = ((strtime[12]-48)<<4) + (strtime[13]-48) ;
if(strtime[14] != ':')
{
setformat = wrong ;
UART_send_string("/n setting time form error please input 's' to re-set") ;
return ;
}
rtctime->sec = ((strtime[15]-48)<<4) + (strtime[16]-48) ;
setformat = right ; //set format right flag
}
void set_RTC(RTC *prtc)
{
rRTCCON = 1 ;
rBCDYEAR = prtc->year ;
rBCDMON = prtc->mon ;
rBCDDATE = prtc->date ;
rBCDDAY = prtc->day ;
rBCDHOUR = prtc->hour ;
rBCDMIN = prtc->mini ;
rBCDSEC = prtc->sec ;
rRTCCON = 0 ;
}
void alarm_init(void)
{
/****clear RTC alarm interrupt pending****/
rSRCPND |= 1<<30 ;
rINTPND |= 1<<30 ;
rINTMSK &= ~(1<<30) ; //open RTC alarm interrupt
rRTCALM = 0x41 ; //all alarm Enable
}
void set_alarm(RTC *prtc)
{
rRTCCON = 1 ;
rALMYEAR = prtc->year ;
rALMMON = prtc->mon ;
rALMDATE = prtc->date ;
rALMHOUR = prtc->hour ;
rALMMIN = prtc->mini ;
rALMSEC = prtc->sec ;
rRTCCON = 0 ;
}
void __irq RTC_alarm_interrupt(void)
{
/****clear RTC alarm interrupt pending****/
rSRCPND |= 1<<30 ;
rINTPND |= 1<<30 ;
rINTMSK &= ~(1<<30) ; //open RTC alarm interrupt
rGPBDAT &= ~(0xf<<5) ; //lighten led
UART_send_string("/nRTC alarm") ;
}
//UART0 interrupt
void __irq UART0_interrupt(void)
{
char value ;
/*********clean interrupt bit*********/
rSUBSRCPND |= 0x1 ; //注意顺序
rSRCPND |= 1<<28 ;
rINTPND |= 1<<28 ;
value = UART_receive_byte();
switch(value)
{
case 'w': //write
cmd = write ;
break ;
case 'r': //read
cmd = read ;
break ;
case 's': //settime
settime = set;
UART_send_string("/n please input settime data bxx-xx-xx xx:xx:xxew") ;
break ;
case 'a':
settime = alarm ; //set alarm
UART_send_string("/n please input set alarm data bxx-xx-xx xx:xx:xxew") ;
break ;
case 'b': // data format bxx-xx-xx xx:xx:xxew
uartrtcflag = start ;// set alarm start flag
setcount = -1 ;
break ;
case 'e' :
uartrtcflag = end ;
setcount = -1 ;
break ;
case 't': //turnoff alarm
rRTCALM = 0 ; //disable RTC alarm
rINTMSK |= 1<<30 ; //disable RTC alarm interrupt
break ;
}
if(uartrtcflag==start)
{
if(value != 'b')
{
RTCstr[setcount] = value ;
}
setcount++ ;
}
}
int Main(void)
{
RTC rtcdata ;
MMU_Init();
ChangeMPllValue(127,2,1); //405MHZ
ChangeClockDivider(13,12); //1:3:6 PCLK 67.5M
UART_int_init();
cmd = idle ; //idle model
settime = Nset ; //NO settime
setformat = wrong ; //NO right setformat
uartrtcflag = end ; //NO set data transination
pISR_UART0 = (U32)UART0_interrupt ;
pISR_RTC = (U32)RTC_alarm_interrupt ;
while(1)
{
if(cmd==write)
{
cmd = idle ;//clean write model to idle
str_to_RTC(RTCstr, &rtcdata) ;
if(settime==set)
{
settime = Nset ; //设置时间后清除设置标志,防止无意设置
if(setformat==right)
{
setformat = wrong ;
set_RTC(&rtcdata) ;
UART_send_string("/n set RTC time successful") ;
}
}
if(settime==alarm)
{
settime = Nset ; //设置闹铃后清除设置标志,防止无意设置
if(setformat==right)
{
setformat = wrong ;
alarm_init() ; //initial alarm register
set_alarm(&rtcdata) ;
UART_send_string("/n set RTC alarm successful") ;
}
}
}
if(cmd==read)
{
cmd = idle ; //clean read model to idle
get_rtc(&rtcdata) ;
rtc_to_str(RTCstr, &rtcdata) ;
UART_send_string("/n The current time is /t") ;
UART_send_string(RTCstr) ;
}
}
return 0 ;
}
参考了赵老师的博客,这里表示感谢,博客地址