1. 程式人生 > >基於mini2440的RTC讀寫(裸機)

基於mini2440的RTC讀寫(裸機)

很多處理器都有RTC實時時鐘功能,s3c2440也提供了這個功能,其功能主要是:實時時鐘、鬧鐘、tick中斷等。RTC的操作比較簡單。讀寫時RTCCON最低位應設定為1,不讀寫時設定為0以免誤修改RTC相應暫存器。

BCDSEC,BCDMIN,BCDHOUR,BCDDAY,BCDDATE,BCDMON,BCDYEAR可以設定和讀取RTC的值,在程式設計中需要注意一秒只差的問題(具體可檢視晶片手冊),所以在BCDSEC值為0時需要重新讀取RTC相應暫存器,防止誤差,這點需要特別注意。

tick中斷可為RTOS提供中斷時鐘,其週期計算如下:


可在TICNT設定相應位。達到週期產生中斷。

鬧鐘功能在RTCALM允許使能。在ALMSEC、ALMMIN、ALMHOUR、ALMDATE、ALMMON、ALMYEAR中設定鬧鐘值,到達時間後產生相應中斷。

還有一點需要注意,s3c2440的RTC以BCD碼進行讀寫,所以要以十進位制操作應做相應轉換。RTC操作比較簡單,這裡不再作詳細介紹,具體可檢視晶片手冊。測試:將相應時間寫入RTC、設定相應tick中斷和鬧鐘。通過串列埠顯示相應時間。

程式碼如下:

main.c部分

#define  GLOBAL_CLK 1

#include<string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "profile.h"
#include "mmu.h"

extern void RTC_Set(char year, char month, char week,
			char date, char hour, char min, char sec);
extern void RTC_Read(char *year, char *month, char *week,
			char *date, char *hour, char *min, char *sec);
extern void RTC_Alarm_Set(char year, char mon, char date,
			char hour, char min, char sec);
extern void RTC_Init(void);
extern void RTC_Tick(void);
extern void RTC_Alarm(void);

extern char tick_flag, alarm_flag;
void delay(int num);

void delay(int num)
{
	int i, j, k;
	for(i=0;i<num;i++)
		for(j=0;j<1000;j++)
			for(k=0;k<1000;k++);
}

void Main(void)
{
	char data[7] = {0};
	char *week_str[7] = {"Mon", "Tue", "Wed", 
						"Thu", "Fri", "Sat", "Sun"};
	char *week;
	int count = 0;
	
	rGPBCON=(1<<0);
    rGPBDAT=(0<<0);//關閉蜂鳴器
	
	MMU_Init();//地址的重對映
	RTC_Init();
	RTC_Tick();
	RTC_Alarm();
	
	RTC_Set(13, 9, 6, 7, 19, 59, 12);
	RTC_Alarm_Set(13, 9, 7, 20, 0, 0);
	
	while ( 1 ){
		RTC_Read(&data[0], &data[1], &data[2], 
			&data[3], &data[4], &data[5], &data[6]);
		
		switch ( data[2]){
			case 1 : week = week_str[0] ;
					break;
			case 2 : week = week_str[1];
					break;
			case 3 : week = week_str[2];
					break;
			case 4 : week = week_str[3];
					break;
			case 5 : week = week_str[4];
					break;
			case 6 : week = week_str[5];
					break;
			case 7 : week = week_str[6];
					break;
			default: break;
		}
		
		Uart_Printf("\n%d年,%d月,%d日,星期%s,%d點,%d分,%d秒\n",2000+data[0], 
			data[1], data[3], week, data[4], data[5], data[6]);
			
		if (1 == alarm_flag){
			Uart_Printf("\nALARM:%d年,%d月,%d日,%d點,%d分,%d秒\n",2000+data[0], 
			data[1], data[3], data[4], data[5], data[6]);
			alarm_flag = 0;
		}
		
		if (1 == tick_flag){
			count++;
			Uart_Printf("\nTICK:%d\n", count);
			tick_flag = 0;
		}
		
		delay(50);
	}
}

RTC.c部分
#include "2440addr.h"

/*定義使用者中斷標誌*/
char tick_flag = 0, alarm_flag = 0;
void __irq RTC_alarm_interrupt(void);
void __irq RTC_tick_interrupt(void);

/*RTC初始化*/
void RTC_Init(void)
{
	rINTMSK &= ~(1<<30 | 1<<8);//RTC中斷使能
	pISR_TICK = (unsigned)RTC_tick_interrupt;
	pISR_RTC = (unsigned)RTC_alarm_interrupt;
}

/*RTC設定*/
void RTC_Set(char year, char month, char week,
		char date, char hour, char min, char sec)
{
	rRTCCON = 1;
	
	rBCDYEAR = year;
	rBCDMON = ((month / 10)<<4) | (month % 10);
	rBCDDAY = week;
	rBCDDATE = ((date / 10)<<4) | (date % 10);
	rBCDHOUR = ((hour / 10)<<4) | (hour % 10);
	rBCDMIN = ((min / 10)<<4) | (min % 10);
	rBCDSEC = ((sec / 10)<<4) | (sec % 10);

	rRTCCON &= ~1;
}

/*讀取RTC*/
void RTC_Read(char *year, char *month, char *week,
		char *date, char *hour, char *min, char *sec)
{
	char i;
	
	rRTCCON = 1;
	
	*year = rBCDYEAR;
	*month = (rBCDMON>>4) * 10 + (rBCDMON & 0x0f);
	*week = rBCDDAY;
	*date = (rBCDDATE>>4) * 10 + (rBCDDATE & 0x0f);
	*hour = (rBCDHOUR>>4) * 10 + (rBCDHOUR & 0x0f);
	*min = (rBCDMIN>>4) * 10 + (rBCDMIN & 0x0f);
	
	if ((*sec = rBCDSEC) == 0){
		*year = rBCDYEAR;
		*month = (rBCDMON>>4) * 10 + (rBCDMON & 0x0f);
		*week = rBCDDAY;
		*date = (rBCDDATE>>4) * 10 + (rBCDDATE & 0x0f);
		*hour = (rBCDHOUR>>4) * 10 + (rBCDHOUR & 0x0f);
		*min = (rBCDMIN>>4) * 10 + (rBCDMIN & 0x0f);
	}
	
	*sec = (rBCDSEC>>4) * 10 + (rBCDSEC & 0x0f);
	
	rRTCCON &= ~1;
}

/*RTC tick時鐘設定*/
void RTC_Tick(void)
{
	rTICNT &= ~0xff;
	rTICNT |= (1<<7 | 63);
}

/*RTC 鬧鐘初始化*/
void RTC_Alarm(void)
{
	rRTCALM &= ~0xff;
	rRTCALM |= 0xff;
}

/*RTC 鬧鐘設定*/
void RTC_Alarm_Set(char year, char mon, char date,
		char hour, char min, char sec)
{
	rALMYEAR = year;
	rALMMON = ((mon / 10)<<4) | mon % 10;
	rALMDATE = ((date / 10)<<4) | date % 10;
	rALMHOUR = ((hour / 10)<<4) | hour % 10;
	rALMMIN = ((min / 10)<<4) | min % 10;
	rALMSEC = ((sec / 10)<<4) | sec % 10;
}

/*RTC 鬧鐘中斷服務*/
void __irq RTC_alarm_interrupt(void)
{
	rSRCPND |= 1<<30;//清除中斷
	rINTPND |= 1<<30;
	alarm_flag = 1;//設定使用者中斷標誌
}

/*RTC tick中斷服務*/
void __irq RTC_tick_interrupt(void)
{
	rSRCPND |= 1<<8;//清除中斷
	rINTPND |= 1<<8;
	tick_flag = 1;//設定使用者中斷標誌
}

執行結果如下:


原始碼下載地址:http://download.csdn.net/detail/a16839678/6232721