新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > s3c2440實時時鐘的應用

s3c2440實時時鐘的應用

作者: 時間:2016-11-19 來源:網(wǎng)絡 收藏
實時時鐘RTC)的主要功能是在系統(tǒng)掉電的情況下,利用后備電源使時鐘繼續(xù)運行,從而不會丟失時間信息。

s3c2440內部集成了RTC模塊,而且用起來也十分簡單。其內部的寄存器BCDSEC,BCDMIN,BCDHOUR,BCDDAY,BCDDATE,BCDMON和BCDYEAR分別存儲了當前的秒,分,小時,星期,日,月和年,表示時間的數(shù)值都是BCD碼。這些寄存器的內容可讀可寫,并且只有在寄存器RTCCON的第0位為1時才能進行讀寫操作。為了防止誤操作,當不進行讀寫時,要把該位清零。當讀取這些寄存器時,能夠獲知當前的時間;當寫入這些寄存器時,能夠改變當前的時間。另外需要注意的是,因為有所謂的“一秒誤差”,因此當讀取到的秒為0時,需要重新再讀取一遍這些寄存器的內容,才能保證時間的正確。

下面的程序就是一個簡單的RTC的例子。系統(tǒng)上電,或按鍵時,會在LCD上顯示當前時間的全部信息。并且可以通過UART,在PC機上改變RTC,它們之間的協(xié)議為:當PC機發(fā)送0xAA時,表示其后的7個數(shù)據(jù)分別為年、月、日、星期、小時、分和秒,在s3c2440接收到這些數(shù)據(jù)后,發(fā)送0xAA以示確認;當PC機發(fā)送其他數(shù)據(jù)時,對于s3c2440來說沒有任何意義,s3c2440只是把該數(shù)據(jù)再傳回給PC機。為了簡潔和突出重點,在下面程序中,會省略掉以前文章中介紹過的內容,如不清楚,請翻看本博客中的其他相關內容。


unsigned char date_buffer[7];//分別表示年、月、日、星期、小時、分、秒
unsigned char flag;//用于表示更新LCD顯示時間的標志

//獲取時間
void get_date(void)
{
rRTCCON = 1;

date_buffer[0] = rBCDYEAR;//年
date_buffer[1] = rBCDMON;//月
date_buffer[2] = rBCDDATE;//日
date_buffer[3] = rBCDDAY;//星期
date_buffer[4] = rBCDHOUR;//小時
date_buffer[5] = rBCDMIN;//分
date_buffer[6] = rBCDSEC;//秒
//當秒為0時,重新讀取
if(date_buffer[6]==0)
{
date_buffer[0] = rBCDYEAR;//年
date_buffer[1] = rBCDMON;//月
date_buffer[2] = rBCDDATE;//日
date_buffer[3] = rBCDDAY;//星期
date_buffer[4] = rBCDHOUR;//小時
date_buffer[5] = rBCDMIN;//分
date_buffer[6] = rBCDSEC;//秒
}

rRTCCON = 0;
}

//設置時間
void set_date(void)
{
rRTCCON = 1 ;

rBCDYEAR = date_buffer[0] ;//年
rBCDMON= date_buffer[1] ;//月
rBCDDATE = date_buffer[2] ;//日
rBCDDAY= date_buffer[3] ;//星期
rBCDHOUR = date_buffer[4] ;//小時
rBCDMIN= date_buffer[5] ;//分
rBCDSEC= date_buffer[6] ;//秒

rRTCCON = 0 ;
}

//在LCD上顯示時間
void show_date(void)
{
unsigned char String[ ]="當前時間:";
unsigned char String_Y[ ]="年";
unsigned char String_M[ ]="月";
unsigned char String_D[ ]="日";

unsigned char ToWeek[ ][7] = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};

unsigned char qh,wh;
const unsigned char *mould;
int length = sizeof(String);
int k,xx;

get_date();//獲取時間

//在LCD上寫“當前時間:”這幾個字
for(k=0,xx=0;k{
qh=String[k]-0xa0;
wh=String[k+1]-0xa0;
mould = & __HZK[ (( qh - 1 )*94 + wh- 1 )*32 ];
Draw_Text16(30+xx,50,0x0f,mould);
xx+=16;
k++;
}

//在下一行顯示具體的時間,形式如:2010年04月03日星期六21:52:28
//年
//人為加上“20”
mould = & __ASCII[2*16];
Draw_ASCII(30,70,0x0,mould);
mould = & __ASCII[0*16];
Draw_ASCII(38,70,0x0,mould);

qh=(date_buffer[0]>>4)+48;
wh=(date_buffer[0]&0x0f)+48;
mould = & __ASCII[qh*16];
Draw_ASCII(46,70,0x0,mould);
mould = & __ASCII[wh*16];
Draw_ASCII(54,70,0x0,mould);

qh=String_Y[0]-0xa0;
wh=String_Y[1]-0xa0;
mould = & __HZK[ (( qh - 1 )*94 + wh- 1 )*32 ];
Draw_Text16(62,70,0x0f,mould);

//月
qh=(date_buffer[1]>>4)+48;
wh=(date_buffer[1]&0x0f)+48;
mould = & __ASCII[qh*16];
Draw_ASCII(78,70,0x0,mould);
mould = & __ASCII[wh*16];
Draw_ASCII(86,70,0x0,mould);

qh=String_M[0]-0xa0;
wh=String_M[1]-0xa0;
mould = & __HZK[ (( qh - 1 )*94 + wh- 1 )*32 ];
Draw_Text16(94,70,0x0f,mould);

//日
qh=(date_buffer[2]>>4)+48;
wh=(date_buffer[2]&0x0f)+48;
mould = & __ASCII[qh*16];
Draw_ASCII(110,70,0x0,mould);
mould = & __ASCII[wh*16];
Draw_ASCII(118,70,0x0,mould);

qh=String_D[0]-0xa0;
wh=String_D[1]-0xa0;
mould = & __HZK[ (( qh - 1 )*94 + wh- 1 )*32 ];
Draw_Text16(126,70,0x0f,mould);

//星期
for(k=0,xx=0;k<7-1;k++)
{
qh=ToWeek[date_buffer[3]][k]-0xa0;
wh=ToWeek[date_buffer[3]][k+1]-0xa0;
mould = & __HZK[ (( qh - 1 )*94 + wh- 1 )*32 ];
Draw_Text16(142+xx,70,0x0f,mould);
xx+=16;
k++;
}

//小時
qh=(date_buffer[4]>>4)+48;
wh=(date_buffer[4]&0x0f)+48;
mould = & __ASCII[qh*16];
Draw_ASCII(194,70,0x0,mould);
mould = & __ASCII[wh*16];
Draw_ASCII(202,70,0x0,mould);

mould = & __ASCII[ :*16 ];
Draw_ASCII(210,70,0x0f,mould);

//分
qh=(date_buffer[5]>>4)+48;
wh=(date_buffer[5]&0x0f)+48;
mould = & __ASCII[qh*16];
Draw_ASCII(218,70,0x0,mould);
mould = & __ASCII[wh*16];
Draw_ASCII(226,70,0x0,mould);

mould = & __ASCII[ :*16 ];
Draw_ASCII(234,70,0x0f,mould);

//秒
qh=(date_buffer[6]>>4)+48;
wh=(date_buffer[6]&0x0f)+48;
mould = & __ASCII[qh*16];
Draw_ASCII(242,70,0x0,mould);
mould = & __ASCII[wh*16];
Draw_ASCII(250,70,0x0,mould);
}

//按鍵中斷,用于更新LCD上顯示的時間
void __irq Key4_ISR(void)
{
rSRCPND = rSRCPND | 0x1;
rINTPND = rINTPND | 0x1;
flag=1;//置標志
}

//UART中斷,用于修改時間
void __irq uartISP(void)
{
char ch;
static char temp;
static char count;
rSUBSRCPND |= 0x3;
rSRCPND |= 0x1<<28;
rINTPND |= 0x1<<28;

if(rUTRSTAT0 & 1)//接收數(shù)據(jù)處理部分
{

ch = rURXH0;//接收字節(jié)數(shù)據(jù)
if(ch==0xaa&&temp==0)//表示接收到修改時間的命令
{
temp=1;
count=0;
}
else if(temp==1)//接收時間數(shù)據(jù)
{
date_buffer[count]=ch;//依次存入時間數(shù)組內
count++;
if(count==7)//7個時間數(shù)據(jù)全部接收完畢
{
rUTXH0=0xaa;//發(fā)送0xAA
set_date();//設置時間
count=0;
temp=0;
flag=1;//更新LCD上顯示的時間
}
}
else
rUTXH0=ch;//不是接收時間的命令

}
}

void Main(void)
{
//初始化寄存器,內容省略
……
Brush_Background(0xffffff);//LCD背景為白色
show_date();//在LCD上顯示時間

flag=0;//清標志

while(1)
{
if(flag)//需要更新LCD上的顯示時間
{
Brush_Background(0xffffff);
show_date();
flag=0;//清標志
}
}
}


關鍵詞: S3C2440實時時鐘RT

評論


技術專區(qū)

關閉