|
发表于 2011-4-22 01:28:28
|
显示全部楼层
here is what I put together quickly.
===========================
#include <regx51.h> //we use keil c51
#include <stdio.h> //we use sprintf
#include "gpio.h"
#include "delay.h" //we use delay routines
#include "rtc0.h" //we use tmr0
#include "lcd_4bit.h" //we use lcd1602, 4bit mode
//hardware configuration
#define RTC_PERIOD RTC_500ms //rtc runs at 500ms to generate halfsec clicks
//end hardware configuration
typedef struct {
unsigned char halfsec; //half a second: 0=1st half, 1=2nd half
unsigned char sec; //second
unsigned char min; //minute
unsigned char hour; //hour
unsigned char day; //day. 0=starting day
} RTC_TIME_t; //rtc time type
//global variable
code const unsigned char str0[]="AT89C51 RTC Demo";
code const unsigned char str1[]="time= ";
unsigned char vRAM[17]; //display buffer
volatile RTC_TIME_t _rtc_time; //global variable updated by rtc_update()
//update _rtc_time in the isr
void rtc_update(void) { //update time
if (_rtc_time.halfsec==0) { //1st half?
_rtc_time.halfsec=1; //make it 2nd half
} else {
_rtc_time.halfsec=0;
_rtc_time.sec+=1; //increment to the next second
if (_rtc_time.sec>=60) { //second overflown?
_rtc_time.sec-=60; //reset the second
_rtc_time.min+=1; //increment min
if (_rtc_time.min>=60) { //min overflown?
_rtc_time.min-=60; //reset min
_rtc_time.hour+=1; //increment hour
if (_rtc_time.hour>=24) { //hour overflown
_rtc_time.hour-=24; //reset hour
_rtc_time.day+=1; //increment day
}
}
}
}
}
//set rtc_time
void rtc_set(RTC_TIME_t time) {
_rtc_time.day=time.day;
_rtc_time.hour=time.hour;
_rtc_time.min=time.min;
_rtc_time.sec=time.sec;
_rtc_time.halfsec=time.halfsec;
//alternatively, use memcpy()
}
//read the rtc
void rtc_get(RTC_TIME_t * time_ptr) {
time_ptr->halfsec=_rtc_time.halfsec;
time_ptr->sec=_rtc_time.sec;
time_ptr->min=_rtc_time.min;
time_ptr->hour=_rtc_time.hour;
time_ptr->day=_rtc_time.day;
//alternatively, use memcpy()
}
void mcu_init(void) { //reset the mcu
}
int main(void) {
RTC_TIME_t time ={0, 58, 59, 23, 0}; //rtc time
mcu_init(); //reset the mcu
//set up the lcd
lcd_init(); //reset the lcd
//display the first line on the lcd
lcd_display(LCD_Line0, str0); //display str0
//set up the rtc
rtc0_init(RTC_PERIOD); //reset the rtc to run isr every 0.5 second
rtc0_act(rtc_update); //run rtc_update() in the tmr0 isr
ei(); //enable global interrupt
//initialize rtc
rtc_set(time); //initialize rtc
while (1) {
rtc_get(&time); //read the rtc
if (time.halfsec==0) sprintf(vRAM, "time=%2d-%02d:%02d:%02d", (unsigned short) time.day, (unsigned short) time.hour, (unsigned short) time.min, (unsigned short) time.sec);
else sprintf(vRAM, "time=%2d-%02d:%02d %02d", (unsigned short) time.day, (unsigned short) time.hour, (unsigned short) time.min, (unsigned short) time.sec);
lcd_display(LCD_Line1, vRAM);
delay_ms(100);
}
}
========================
the code runs tmr0 to interrupt once every RTC_PERIOD(=500ms). the time is kept in _rtc_time. two routines, rtc_set() and rtc_get() writes/reads from rtc_time. the time is then displayed via lcd_display().
at this level, the code doesn't directly touch the hardware so it is 100% portable to any mcu: all you need is to write your own low-level routines.
the code doesn't keep a calendar or alarm but that's not difficult to add. |
|