对于2440的实时时钟操作还是比较简单的,难点的地方在于用设置串口通信来控制时钟时钟的读写设置时间和闹铃。但是用串口控制时钟终将只能用于测试,对于产品的话必然要用到显示器,或者lcd或者数码管,不过现代的时钟更加趋向于用lcd 况且能显示更多的信息。
1. 时钟的数据已经存到寄存器中了,只有读取寄存器的值就可以读出时钟,注意当秒钟为0的时候需要重新读取寄存器的值,这里有个一秒的问题。
2.数据的格式为BCD码,用4位二进制表示出十进制数,其本质还是二进制编码。
3. 数据的格式适合用结构体,还有多命令控制时用枚举类型比较好,以后要多用习惯这样的用法。
4.闹铃中断的发生,当设定的闹铃时间和时钟的时间相同时闹铃中断,其中可以有选择的使能year mon date hour min sec ,匹配时从year到sec。例如 只使能分和秒的时候,当时钟的值和设定闹铃的分和秒相同时闹铃中断,即每个小时的多少分多少秒时中断发生。这样一来就可以很灵活的运用闹铃功能了。
代码
enum {idle, write, read} cmd ; //UART control write&read
enum {set, Nset, alarm} settime ; //预设时钟 闹铃
enum {right, wrong} setformat ; //settime format flag
int setcount = -1 ; //用于设定时间闹铃计数
enum {start, end} uartrtcflag ; //串口设定时间闹铃数据开始结束标志
typedef struct time
{
char year ;
char mon ;
char date ;
char day ; // day of week
char hour ;
char mini ;
char sec ;
} RTC ;
char RTCstr[17] = "00-00-00 00:00:00" ;
/***********************************
UART_int初始化led IO端口GPBCON5-8
初始化GPBHCON为串口通信
配置串口通信寄存器
配置中断寄存器
************************************/
void UART_int_init(void)
{
//configuration LED IO port
rGPBCON &= ~(0xff<<10) ;
rGPBCON |= 0x55<<10 ;
//configuration GPHCON to UART
rGPHCON &= ~(0xf<<4) ;
rGPHCON |= 0xa<<4 ;
//rGPHCON = 0x00faaa;
//rGPHUP = 0x7ff ;
//configuration UART0 communication register
//8-bits,1 stop bit, no parity
rULCON0 = 0x03 ;
rUCON0 = 0x05 ;
//configuration UART baudrate
rUBRDIV0= (int)(PCLK/baudrate/16) -1 ;
//clean interrupt bit
rSUBSRCPND |= 0x1 ;
rSRCPND |= 1<<28 ;
rINTPND |= 1<<28 ;
//open UART interrupt
rINTSUBMSK &= ~(0x1) ;
rINTMSK &= ~(0x1<<28) ;
}
void UART_send_byte(char Tx_data)
{
while(!(rUTRSTAT0&0x2)) ;//wait Tx empty
if(Tx_data == '/n') //Tx '/n'
{
rUTXH0 = 0x0d ;
while(!(rUTRSTAT0&0x2)) ;
rUTXH0 = 0x0a ;
}
else
{
rUTXH0 = Tx_data ;
}
}
void UART_send_string(const char *str)
{
while(*str)
{
UART_send_byte(*str) ;
str++ ;
}
}
char UART_receive_byte(void)
{
//char temp ;
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 ;
}
上一篇:2440的flash、linux、bootloader
下一篇:裸机系列——IIC
推荐阅读最新更新时间:2024-11-05 11:23
设计资源 培训 开发板 精华推荐
- LTC3126EFE 汽车和光伏供电 5V USB 电源的典型应用电路
- study stm32f103rct6
- LT3089IFE 升压固定输出线性稳压器的典型应用电路
- 使用 NXP Semiconductors 的 TDA8580J 的参考设计
- 随身WiFi改侧弹Nano转接板/自弹转接板
- 使用 NXP Semiconductors 的 TJA1044 的参考设计
- BTS716G智能高端电源开关典型应用电路
- 使用 ON Semiconductor 的 LA4820M 的参考设计
- LTC3588IMSE-1 交流线路供电 3.6V 降压稳压器的典型应用电路,具有大输出电容器以支持重负载
- 使用具有 B 类 EMI 滤波(单输出)的 RP10-4824SA DC/DC 转换器的典型应用