基於mini2440的RTC讀寫(裸機)
阿新 • • 發佈:2019-02-05
很多處理器都有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