/*
****************************************************************************************
源程序文件名: RTC_DS12887.C
源程序名称: 实时时钟芯片 DS12887 接口驱动的源程序文件
程序功能:
本程序是用 ATmega16 控制实时时钟芯片 DS12887 接口驱动的源程序文件。
程序说明:
函数入口参数:
函数出口参数:
编译工具软件: CodeVision AVR C 版本:1.24.6 以上
*/
/*======================================================================================
本源程序包括的头部文件
======================================================================================*/
#include "LCDM_Day_Time.h" /* 包含在液晶上显示日期和时间信息的头部文件 */
#include "RTC_DS12887.h" /* 本程序的头部文件 */
/*======================================================================================
程序指令代码清单
======================================================================================*/
/*----------------------------------------------------------------------------
全局静态变量定义:
----------------------------------------------------------------------------*/
static volatile Uchar8 tasks_time=0; /* 时间消息的任务变量 */
/* 时间消息的任务变量的各位定义如下:
┏━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┓
┃ BIT7 ┃ BIT6 ┃ BIT5 ┃ BIT4 ┃ BIT3 ┃ BIT2 ┃ BIT1 ┃ BIT0 ┃
┣━━━━╋━━━━╋━━━━╋━━━━╋━━━━╋━━━━╋━━━━╋━━━━┫
┃ 保留 ┃ 保留 ┃ 保留 ┃ 保留 ┃ 保留 ┃蜂鸣声响┃闹钟告警┃时间更新┃
┗━━━━┻━━━━┻━━━━┻━━━━┻━━━━┻━━━━┻━━━━┻━━━━┛
*/
static volatile Uint16 buzzer_alarm_counter=0; /* 蜂鸣器发出声响次数 */
static volatile BCD_TIME time=BCD_TIME_defaults; /* 系统时间结构变量 */
/*----------------------------------------------------------------------------
函数功能: 本函数用于控制蜂鸣器发出声响告警的操作,设定蜂鸣器频率为 2000Hz 。
备注: 蜂鸣器设置为相应的控制引脚高电平时,蜂鸣器发出声响。
----------------------------------------------------------------------------*/
void Buzzer(void)
{
Buzzer_DDR |= Buzzer_PINNum; /* 设置蜂鸣器控制端口为输出引脚 */
Buzzer_PORT |= Buzzer_PINNum; /* 打开蜂鸣器 */
delay_us(500); /* 延时 500us */
Buzzer_PORT &= ~Buzzer_PINNum; /* 关闭蜂鸣器 */
}
#ifdef MCU_No_ExtendedParallelBus /* 无扩展并行总线结构单片机的条件编译 */
/*----------------------------------------------------------------------------
函数功能: 本函数用于虚拟扩展并行总线结构的向外围器件写入数据操作。
函数入口参数:AccessAddress ------ 访问的外围器件地址。
WriteData ---------- 写入的数据。
备注: 本函数仅可访问外围器件的地址数不超过256个。
----------------------------------------------------------------------------*/
void VEPB_WriteData(volatile Uchar8 AccessAddress, volatile Uchar8 WriteData)
{
VEPB_AD_DDR = 0xFF; /* 设置虚拟总线地址/数据总线的数据方向为输出 */
VEPB_AD_PORT = AccessAddress; /* 写入访问的外围器件地址到总线上 */
VEPB_ALE_PORT |= VEPB_ALE_PINNum; /* 地址锁存到外围器件 */
VEPB_ALE_PORT &= ~VEPB_ALE_PINNum;
VEPB_AD_PORT = WriteData; /* 写入数据 */
VEPB_WR_PORT &= ~VEPB_WR_PINNum; /* 使能写入数据 */
VEPB_WR_PORT |= VEPB_WR_PINNum;
}
/*----------------------------------------------------------------------------
函数功能: 本函数用于虚拟扩展并行总线结构的从外围器件读取数据操作。
函数入口参数:AccessAddress ------ 访问的外围器件地址。
函数出口参数:读取的数据。
备注: 本函数仅可访问外围器件的地址数不超过256个。
----------------------------------------------------------------------------*/
Uchar8 VEPB_ReadData(volatile Uchar8 AccessAddress)
{
volatile Uchar8 temp; /* 出口参数寄存器变量 */
VEPB_AD_DDR = 0xFF; /* 设置虚拟总线地址/数据总线的数据方向为输出 */
VEPB_AD_PORT = AccessAddress; /* 写入访问的外围器件地址到总线上 */
VEPB_ALE_PORT |= VEPB_ALE_PINNum; /* 地址锁存到外围器件 */
VEPB_ALE_PORT &= ~VEPB_ALE_PINNum;
VEPB_AD_DDR = 0x00; /* 设置虚拟总线地址/数据总线的数据方向为输入 */
VEPB_AD_PORT = 0xFF; /* 使能虚拟总线地址/数据总线的上拉电阻 */
VEPB_RD_PORT &= ~VEPB_RD_PINNum; /* 使能读取数据 */
temp = VEPB_AD_PIN; /* 读取数据 */
temp = VEPB_AD_PIN; /* 加大读取数据脉冲信号的宽度 */
VEPB_RD_PORT |= VEPB_RD_PINNum;
return (temp);
}
#endif /* "MCU_No_ExtendedParallelBus" 条件编译结束 */
/*----------------------------------------------------------------------------
函数功能: 本函数用于外部中断请求0中断向量的初始化操作。
备注: ①.本函数仅在主函数中调用一次即可。
②.要使能中断还必须在主程序中打开全局中断使能功能,推荐其指令如下:
SREG |= BIT7; / * 使能全局中断 * /
----------------------------------------------------------------------------*/
void external_INT0_initialization(void)
{
#ifdef _MEGA16_INCLUDED_ /* 目标器件芯片为 ATMega16 的条件编译 */
MCUCR &= ~BIT0; /* 设置外部中断请求0的触发方式为:下降沿触发 */
MCUCR |= BIT1;
GICR |= BIT6; /* 使能外部中断请求0 */
GIFR |= BIT6; /* 外部中断请求0标志位清零 */
#endif /* "_MEGA16_INCLUDED_" 条件编译结束 */
#ifdef _MEGA128_INCLUDED_ /* 目标器件芯片为 ATMega128 的条件编译 */
EICRA &= ~BIT0; /* 设置外部中断请求0的触发方式为:下降沿触发 */
EICRA |= BIT1;
EIMSK |= BIT0; /* 使能外部中断请求0 */
EIFR |= BIT6; /* 外部中断请求0标志位清零 */
#endif /* "_MEGA128_INCLUDED_" 条件编译结束 */
}
/*----------------------------------------------------------------------------
函数功能: 本函数用于 DS12887 闹钟中断请求和更新周期结束中断请求处理的中断服务程序。
备注: ①.注意:由于本函数为中断函数,故在调用和返回时无法进行明式数值传递,
因此将在函数体中隐式修改下面这几个全局静态变量数值。
⑴.时间消息的任务变量(tasks_time),用以通知系统执行相应的处理操作。
⑵.系统时间结构变量(time),从 DS12887 中读取更新的系统时间数值。
②.本函数需在设置的 DS12887 中断请求的中断向量函数中调用。在调用之前
需对该中断向量进行初始化,以使能该中断。例:如使用外部中断请求0,
可使用上面提供的 external_INT0_initialization() 函数进行初始化,
而将本本函数放在外部中断请求0服务程序中。
----------------------------------------------------------------------------*/
void DS12887_INT_ISR(void)
{
register Uchar8 temp; /* 临时寄存器变量 */
register Uchar8 temp2; /* 临时寄存器变量2 */
DS12887_CS_PORT &= ~DS12887_CS_PINNum;/* 置 DS12887 片选控制引脚为L */
#ifdef MCU_No_ExtendedParallelBus /* 无扩展并行总线结构单片机的条件编译 */
/* 读取 DS12887 寄存器C(中断标志寄存器)的内容,访问该寄存器后将自动清零所有
标志位,否则芯片将无法产生下一次中断请求。其次可对读取的中断标志位进行判断。 */
temp = VEPB_ReadData(DS12887_REG_C);
#else
temp = DS12887_REG_C;
#endif /* "MCU_No_ExtendedParallelBus" 条件编译结束 */
temp2 = temp;
/* 检查是否为闹钟中断?是,则通知系统对闹钟请求执行相应的处理 */
if ((temp&BIT5)==BIT5)
{
tasks_time |= BIT1; /* 闹钟告警消息任务位置位 */
}
/* 检查是否为更新周期结束中断?是,则通知系统对更新周期结束请求执行相应的处理 */
if ((temp2&BIT4)==BIT4)
{
/* 读取 DS12887 中更新的系统时间数值 */
#ifdef MCU_No_ExtendedParallelBus /* 无扩展并行总线结构单片机的条件编译 */
time.BCD_Second = VEPB_ReadData(DS12887_Second);
time.BCD_Minute = VEPB_ReadData(DS12887_Minute);
time.BCD_Hour = VEPB_ReadData(DS12887_Hour);
time.BCD_Date = VEPB_ReadData(DS12887_Date);
time.BCD_Month = VEPB_ReadData(DS12887_Month);
time.BCD_Year = VEPB_ReadData(DS12887_Year);
time.BCD_Year_H = VEPB_ReadData(DS12887_Year_H);
time.BCD_Week = VEPB_ReadData(DS12887_Week);
#else
time.BCD_Second = DS12887_Second;
time.BCD_Minute = DS12887_Minute;
time.BCD_Hour = DS12887_Hour;
time.BCD_Date = DS12887_Date;
time.BCD_Month = DS12887_Month;
time.BCD_Year = DS12887_Year;
time.BCD_Year_H = DS12887_Year_H;
time.BCD_Week = DS12887_Week;
#endif /* "MCU_No_ExtendedParallelBus" 条件编译结束 */
tasks_time |= BIT0; /* 时间更新消息任务位置位 */
}
DS12887_CS_PORT |= DS12887_CS_PINNum;/* 置 DS12887 片选控制引脚为H */
}
/*----------------------------------------------------------------------------
函数功能: 本函数用于 DS12887 的各控制输入/输出引脚定义和初始状态设置的初始化操作。
备注: 本函数仅在主函数中调用一次即可。
----------------------------------------------------------------------------*/
void RTC_DS12887_initialization(void)
{
register Uchar8 temp; /* 临时寄存器变量 */
/* 下面这些语句用于设置 DS12887 的各控制引脚与MCU的连接定义和初始状态 */
DS12887_CS_DDR |= DS12887_CS_PINNum; /* 设置 DS12887 片选控制为输出引脚 */
DS12887_CS_PORT |= DS12887_CS_PINNum; /* 置 DS12887 片选控制引脚为H */
DS12887_IRQ_DDR &= ~DS12887_IRQ_PINNum;/* 设置 DS12887 中断请求为输入引脚 */
DS12887_IRQ_PORT |= DS12887_IRQ_PINNum;/* 使能 DS12887 中断请求引脚的上拉电阻 */
#ifdef MCU_No_ExtendedParallelBus /* 无扩展并行总线结构单片机的条件编译 */
VEPB_ALE_DDR |= VEPB_ALE_PINNum; /* 设置虚拟总线控制线地址锁存使能为输出引脚 */
VEPB_ALE_PORT &= ~VEPB_ALE_PINNum;
VEPB_WR_DDR |= VEPB_WR_PINNum; /* 设置虚拟总线控制线写使能信号为输出引脚 */
VEPB_WR_PORT |= VEPB_WR_PINNum;
VEPB_RD_DDR |= VEPB_RD_PINNum; /* 设置虚拟总线控制线读锁存信号为输出引脚 */
VEPB_RD_PORT |= VEPB_RD_PINNum;
VEPB_AD_DDR = 0x00; /* 设置虚拟总线地址/数据总线的数据方向为输入 */
VEPB_AD_PORT = 0xFF; /* 使能虚拟总线地址/数据总线的上拉电阻 */
#else
MCUCR |= BIT7; /* 使能外部存储器接口 */
#endif /* "MCU_No_ExtendedParallelBus" 条件编译结束 */
/* 下面这些语句用于 DS12887 初始化操作 */
DS12887_CS_PORT &= ~DS12887_CS_PINNum;/* 置 DS12887 片选控制引脚为L */
#ifdef MCU_No_ExtendedParallelBus /* 无扩展并行总线结构单片机的条件编译 */
/* 启动晶体振荡器,关闭周期中断方波输出 */
VEPB_WriteData(DS12887_REG_A, 0x20);
/* 芯片处于正常工作状态、允许更新周期结束中断、闹钟中断保持原设置状态、
关闭周期中断、关闭方波输出、采用 BCD 码数据格式和 24 小时制模式 */
temp = VEPB_ReadData(DS12887_REG_B);
temp &= 0x32;
temp |= 0x12;
VEPB_WriteData(DS12887_REG_B, temp);
/* 检查内置电池能量状态?如果电池耗尽,系统将进行告警 */
temp = VEPB_ReadData(DS12887_REG_D);
if ((temp&BIT7)==0)
{
Buzzer();
}
/* 写入年前两位数据为 20 */
VEPB_WriteData(DS12887_Year_H, 0x20);
/* 读取 DS12887 寄存器C(中断标志寄存器)的内容,使该寄存器清零所有标志位 */
temp = VEPB_ReadData(DS12887_REG_C);
#else
/* 启动晶体振荡器,关闭周期中断方波输出 */
DS12887_REG_A = 0x20;
/* 芯片处于正常工作状态、允许更新周期结束中断、关闭周期中断和闹钟中断、
关闭方波输出、采用 BCD 码数据格式和 24 小时制模式 */
temp = DS12887_REG_B;
temp &= 0x32;
temp |= 0x12;
DS12887_REG_B = temp;
/* 检查内置电池能量状态?如果电池耗尽,系统将进行告警 */
temp = DS12887_REG_D;
if ((temp&BIT7)==0)
{
Buzzer();
}
/* 写入年前两位数据为 20 */
DS12887_Year_H = 0x20;
/* 读取 DS12887 寄存器C(中断标志寄存器)的内容,使该寄存器清零所有标志位 */
temp = DS12887_REG_C;
#endif /* "MCU_No_ExtendedParallelBus" 条件编译结束 */
DS12887_CS_PORT |= DS12887_CS_PINNum;/* 置 DS12887 片选控制引脚为H */
}