📄 rtc.c
字号:
/****************************************************************************/
/* */
/* FILE NAME VERSION */
/* */
/* RTC.C 1.0 */
/* */
/* DESCRIPTION */
/* */
/* JX44B0(S3C44B0X)实时时钟实验 */
/* */
/* */
/* DATA STRUCTURES */
/* */
/* FUNCTIONS : */
/* 在JX44B0教学实验箱进行PWM方式驱动蜂蜜器的实验 */
/* */
/* DEPENDENCIES */
/* JX44B0-1 */
/* JX44B0-2 */
/* JX44B0-3 */
/* */
/* */
/* NAME: */
/* REMARKS: */
/* */
/* Copyright (C) 2003 Wuhan CVTECH CO.,LTD */
/****************************************************************************/
/****************************************************************************/
/* 学习S3C44B0X处理器中的实时时钟处理方法: */
/****************************************************************************/
/* 包含文件 */
#include "44b.h"
#include "44blib.h"
#include "rtc.h"
/* 表示日期、时间的数据结构 */
typedef struct ST_DATE
{
short year; // 年
char mon; // 月
char day; // 日
char week_day; // 星期
char hour; // 时
char min; // 分
char sec; // 秒
} st_date;
typedef (*ISR_ROUTINE_ENTRY)(void);
/* 全局变量 */
int led_index = 0;
int ext0_count = 0;
/* 数码管显示码表,请参考led实验 */
unsigned char seg7table[16] =
{
0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8,
0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e,
};
/* functions */
void rtc_tick_isr(void);
void rtc_int_isr(void);
void IsrIRQ() __attribute__ ((interrupt("IRQ")));
/*****************************************************************************
// Function name : IsrIRQ
// Description : 非矢量方式下中断的查表处理
// 中断地址表位于0x0c7fff00开始的256字节
// Return type : void
// Argument : void
*****************************************************************************/
void IsrIRQ()
{
int count = 0;
unsigned int isr_pending;
unsigned int isr_mask = 0x00000001;
unsigned int isr_mask_set = rINTMSK;
ISR_ROUTINE_ENTRY isr_routine_entry = (ISR_ROUTINE_ENTRY)0x0;
__asm__ (
"STMFD SP!, {r1,r4-r8} @ SAVE r1,r4-r10 \n"
"nop \n");
isr_pending = (rINTPND & ~isr_mask_set);
while(isr_mask)
{
if(isr_pending&isr_mask)
{
isr_routine_entry = (ISR_ROUTINE_ENTRY)(*(int*)(HandleADC+count));
break;
}
count+=4;
isr_mask <<= 1;
}
if(isr_routine_entry) (*isr_routine_entry)();
__asm__ (
"LDMFD SP!, {r1,r4-r8} @ RESTORE r1,r4-r10 \n"
"nop \n");
}
/*****************************************************************************
// Function name : init_interrupt_handler
// Description : 非矢量方式下中断向量表初始化处理
// Return type : void
// Argument : irq_handler
// 中断处理函数入口
*****************************************************************************/
void init_interrupt_handler(unsigned int irq_handler)
{
int i;
rINTPND = 0x00000000; /* 清除所有未决的中断 */
rI_ISPC = 0x03FFFFFF;
for( i = 0; i < 256; i+=4) /* 清除中断表 */
*(unsigned int*)(_ISR_STARTADDRESS+i) = 0;
*(unsigned int*)(HandleIRQ) = irq_handler; /* 设置IRQ模式处理函数 */
}
/*****************************************************************************
// Function name : install_isr_handler
// Description : 非矢量方式下中断向量的安装
// Return type : void
// Argument : irq_no, 中断号
// irq_routine, 中断处理函数地址
*****************************************************************************/
void install_isr_handler(int irq_no, void* irq_routine)
{
*(unsigned int*)(irq_no) = (unsigned int)irq_routine;
}
/*****************************************************************************
// Function name : rtc_set_date
// Description : 修改实时时钟当前时间、日期
// Return type : void
// Argument : p_date, 待设置的日期
*****************************************************************************/
void rtc_set_date(st_date* p_date)
{
rRTCCON = 0x01;
rBCDYEAR = p_date->year;
rBCDMON = p_date->mon;
rBCDDAY = p_date->day;
rBCDDATE = p_date->week_day;
rBCDHOUR = p_date->hour;
rBCDMIN = p_date->min;
rBCDSEC = p_date->sec;
rRTCCON = 0x00;
}
/*****************************************************************************
// Function name : rtc_get_date
// Description : 获取实时时钟当前时间、日期
// Return type : void
// Argument : p_date, 返回日期的指针
*****************************************************************************/
void rtc_get_date(st_date* p_date)
{
rRTCCON = 0x01;
p_date->year = rBCDYEAR ;
p_date->mon = rBCDMON ;
p_date->day = rBCDDAY ;
p_date->week_day= rBCDDATE ;
p_date->hour = rBCDHOUR ;
p_date->min = rBCDMIN ;
p_date->sec = rBCDSEC ;
rRTCCON = 0x00;
}
/*****************************************************************************
// Function name : rtc_tick_init
// Description : 初始化S3C44B0的TICK定时器
// Return type : void
// Argument : tick, 设置的TICK频率(时钟滴答的周期为 (1+tick)/128秒)
*****************************************************************************/
void rtc_tick_init( char tick )
{
rRTCCON = 0x01;
rTICINT = (tick&0x7f)|0x80; /*TICK 中断使能,周期为(1+tick)/128秒*/
rRTCCON = 0x00;
}
/*****************************************************************************
// Function name : rtc_alarm_set
// Description : 设置S3C44B0的告警时间以及方式
// Return type : void
// Argument : p_date, 告警的时间
// mode, 告警模式
*****************************************************************************/
void rtc_alarm_set(st_date* p_date, unsigned char mode)
{
rRTCCON = 0x01;
rALMYEAR = p_date->year;
rALMMON = p_date->mon;
rALMDAY = p_date->day;
rALMHOUR = p_date->hour;
rALMMIN = p_date->min;
rALMSEC = p_date->sec;
rRTCALM = mode;
rRTCCON = 0x00;
}
/*****************************************************************************
// Function name : Main
// Description : 测试程序主函数
// 完成功能:
// 时钟滴答:每秒钟刷新数码管显示
// 设置当前日期、时间
// 动态刷新当前日期、时间,通过串口打印出来
// 时间告警功能:每分钟的第5秒告警,并进行跑马灯显示
// Return type : int
// Argument : void
*****************************************************************************/
int Main(void)
{
int old_index ;
st_date m_date;
/* 采用BCD编码,如2004年需要设置的值为0x2004 */
m_date.year = 0x2000+0x04 ;
m_date.mon = 0x03 ;
m_date.day = 0x02 ;
m_date.week_day = 0x02 ;
m_date.hour = 0x15 ;
m_date.min = 0x40 ;
m_date.sec = 0x00 ;
/* 修改当前日期和时间 */
rtc_set_date(&m_date);
m_date.sec = 0x05 ;
/* 设置告警的时间及方式,0x41表示使能RTC告警,以及使能秒时钟告警 */
rtc_alarm_set(&m_date, 0x41);
rtc_tick_init(127);
rINTCON=0x7; /* Non-vect,IRQ disable,FIQ disable */
init_interrupt_handler((unsigned int)IsrIRQ);
install_isr_handler(HandleTICK, (void*)rtc_tick_isr);
install_isr_handler(HandleRTC, (void*)rtc_int_isr);
rINTMOD=0x0; /*设置所有中断为IRQ模式 */
rINTMSK=0x07ffffff &~ /*使能TICK中断 */
(BIT_GLOBAL|BIT_TICK|BIT_RTC);
rINTCON=0x5; /*打开IRQ模式的中断 */
old_index = led_index;
Uart_Printf("\r\n");
while(1)
{
if(old_index != led_index) /* 每隔一秒更新一次数据 */
{
rtc_get_date(&m_date);
old_index = led_index;
Uart_Printf( /* 时钟数据为BCD码格式,以16进制显示 */
"\r%02x:%02x:%02x", m_date.hour, m_date.min, m_date.sec);
}
};
}
/*****************************************************************************
// Function name : rtc_tick_isr
// Description : TICK中断处理程序,程序中设置每秒钟引发一次中断
// Return type : int
// Argument : void
*****************************************************************************/
void rtc_tick_isr(void)
{
rI_ISPC=BIT_TICK; /*清除时钟滴答中断标志 */
*((unsigned char*) 0x02000006) = 0x00;
*(unsigned char*)0x02000004 = seg7table[led_index%10];
led_index++;
}
/*****************************************************************************
// Function name : rtc_int_isr
// Description : rtc中断处理程序,程序中设置每分钟的第5秒引发该中断
// Return type : int
// Argument : void
*****************************************************************************/
void rtc_int_isr(void)
{
rI_ISPC=BIT_RTC; /*清除RTC中断 */
if(ext0_count&1)
*(unsigned char*)0x2000000 = 0x0f;
else
*(unsigned char*)0x2000000 = 0xff;
ext0_count++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -