TA的每日心情 | 奋斗 2015-1-22 18:04 |
---|
签到天数: 189 天 连续签到: 1 天 [LV.7]常住居民III
|
SAM4N的RTC使用非常简单,可惜板子上并没有带电池,所以断掉不能保持RTC数据。
驱动代码如下:- #include "drv_rtc.h"
- RTC_Time_TypeDef default_time={0x20,0x13,0x10,0x22,0x15,0x22,0x11,0x02,0x00};
- void rtc_init(Hour_Mode_Typedef mode)
- {
- /*禁止外设管理控制寄存器(PMC)写保护*/
- PMC->PMC_WPMR = 0x504D4300;
- /*使能RTC时钟*/
- PMC->PMC_PCER0 = (1UL << ID_RTC);
- /*使能外设管理控制寄存器(PMC)写保护*/
- PMC->PMC_WPMR = 0x504D4301;
- rtc_set_mode(mode);
- rtc_set_time(&default_time,BCD);
- }
- void rtc_set_mode(Hour_Mode_Typedef mode)
- {
- RTC->RTC_MR=mode;
- }
- Hour_Mode_Typedef rtc_get_mode(void)
- {
- Hour_Mode_Typedef mode;
- mode=(Hour_Mode_Typedef)(RTC->RTC_MR&0x01);
- return mode;
- }
- void rtc_set_time(RTC_Time_TypeDef *time,RTC_Time_Format format)
- {
- RTC->RTC_CR|=(RTC_CR_UPDCAL|RTC_CR_UPDTIM); //停止时间和日期更新
- while((RTC->RTC_SR&RTC_SR_ACKUPD)!=RTC_SR_ACKUPD); //等待允许更新时间和日期
- RTC->RTC_SCCR=RTC_SCCR_ACKCLR; //必须先清除状态寄存器ACK位
- if (BCD==format)
- {
- RTC->RTC_CALR=RTC_CALR_CENT(time->cent)|
- RTC_CALR_YEAR(time->year)|
- RTC_CALR_MONTH(time->month)|
- RTC_CALR_DATE(time->date)|
- RTC_CALR_DAY(time->day);
- RTC->RTC_TIMR=RTC_TIMR_HOUR(time->hour)|
- RTC_TIMR_MIN(time->minnute)|
- RTC_TIMR_SEC(time->second) |
- (time->am_pm<<22);
- }
- else if (BIN==format)
- {
- RTC->RTC_CALR=RTC_CALR_CENT(BIN2BCD(time->cent))|
- RTC_CALR_YEAR(BIN2BCD(time->year))|
- RTC_CALR_MONTH(BIN2BCD(time->month))|
- RTC_CALR_DATE(BIN2BCD(time->date))|
- RTC_CALR_DAY(BIN2BCD(time->day));
- RTC->RTC_TIMR=RTC_TIMR_HOUR(BIN2BCD(time->hour))|
- RTC_TIMR_MIN(BIN2BCD(time->minnute))|
- RTC_TIMR_SEC(BIN2BCD(time->second))|
- (time->am_pm<<22);
- }
- RTC->RTC_CR&=~(RTC_CR_UPDCAL|RTC_CR_UPDTIM); //重新允许更新时间和日期
- RTC->RTC_SCCR|=RTC_SCCR_SECCLR; //清除秒事件状态
- }
- void rtc_get_time(RTC_Time_TypeDef *time,RTC_Time_Format format)
- {
- if (BCD==format)
- {
- time->cent=((RTC->RTC_CALR&RTC_CALR_CENT_Msk)>>RTC_CALR_CENT_Pos);
- time->year=((RTC->RTC_CALR&RTC_CALR_YEAR_Msk)>>RTC_CALR_YEAR_Pos);
- time->month=((RTC->RTC_CALR&RTC_CALR_MONTH_Msk)>>RTC_CALR_MONTH_Pos);
- time->date=((RTC->RTC_CALR&RTC_CALR_DATE_Msk)>>RTC_CALR_DATE_Pos);
- time->day=((RTC->RTC_CALR&RTC_CALR_DAY_Msk)>>RTC_CALR_DAY_Pos);
- time->hour=((RTC->RTC_TIMR&RTC_TIMR_HOUR_Msk)>>RTC_TIMR_HOUR_Pos);
- time->minnute=((RTC->RTC_TIMR&RTC_TIMR_MIN_Msk)>>RTC_TIMR_MIN_Pos);
- time->second=((RTC->RTC_TIMR&RTC_TIMR_SEC_Msk)>>RTC_TIMR_SEC_Pos);
- time ->am_pm=((RTC->RTC_TIMR>>22)&0x01UL);
- }
- else if (BIN==format)
- {
- time->cent=BCD2BIN((RTC->RTC_CALR&RTC_CALR_CENT_Msk)>>RTC_CALR_CENT_Pos);
- time->year=BCD2BIN((RTC->RTC_CALR&RTC_CALR_YEAR_Msk)>>RTC_CALR_YEAR_Pos);
- time->month=BCD2BIN((RTC->RTC_CALR&RTC_CALR_MONTH_Msk)>>RTC_CALR_MONTH_Pos);
- time->date=BCD2BIN((RTC->RTC_CALR&RTC_CALR_DATE_Msk)>>RTC_CALR_DATE_Pos);
- time->day=BCD2BIN((RTC->RTC_CALR&RTC_CALR_DAY_Msk)>>RTC_CALR_DAY_Pos);
- time->hour=BCD2BIN((RTC->RTC_TIMR&RTC_TIMR_HOUR_Msk)>>RTC_TIMR_HOUR_Pos);
- time->minnute=BCD2BIN((RTC->RTC_TIMR&RTC_TIMR_MIN_Msk)>>RTC_TIMR_MIN_Pos);
- time->second=BCD2BIN((RTC->RTC_TIMR&RTC_TIMR_SEC_Msk)>>RTC_TIMR_SEC_Pos);
- time ->am_pm=((RTC->RTC_TIMR>>22)&0x01UL);
- }
- }
复制代码 时间和日期寄存器里面保存的值是BCD编码的,这里用两个宏定义实现二进制和BCD码的互换:- #define BCD2BIN(x) ((x>>4)*10+(x&0x0f))
- #define BIN2BCD(x) (((x/10)<<4)|(x%10))
复制代码 下面是相关的结构体定义:- typedef enum
- {
- Hour_Mode_24,
- Hour_Mode_12
- }Hour_Mode_Typedef;
- struct RTC_Time
- {
- uint8_t cent;
- uint8_t year;
- uint8_t month;
- uint8_t date;
- uint8_t hour;
- uint8_t minnute;
- uint8_t second;
- uint8_t day;
- uint8_t am_pm;
- } ;
- typedef struct RTC_Time RTC_Time_TypeDef;
- typedef enum
- {
- BCD,
- BIN,
- } RTC_Time_Format;
复制代码 这里需要注意的是RTC里面支持12小时模式和24小时模式,对于12小时模式,在时间寄存器中会有个AM/PM位分辨是上午还是下午,在24小时模式下,这个位是无效的。
在同时日期寄存器中还有个cent位,是多少世纪的意思,这个部分时钟芯片可能没有。
还要注意的是每次重新设置时间时,必须要去停止时间和日期的更新,然后等待ACKUPD清零才能进行重新设置时间日期操作。- int main(void)
- {
- RTC_Time_TypeDef time;
- systick_hw_init();
- led_hw_init();
- UART0_Init(115200);
- glcd_init();
- printf("this is a rtc demo!\r\n");
- rtc_init(Hour_Mode_24);
- while(1){
- rtc_get_time(&time,BIN);
- printf("%d-%d-%d %d:%d:%d\r\n",time.year,time.month,time.date,time.hour,time.minnute,time.second);
- PIOB->PIO_CODR=(0x01<<LED0_PIN);
- delay_ms(500);
- PIOB->PIO_SODR=(0x01<<LED0_PIN);
- delay_ms(500);
- }
- }
复制代码 这里是一个简单的时间读取程序,会定时的打印当前时间到串口,如下图:
10.rtc.rar
(1.07 MB, 下载次数: 3)
|
|