📄 timer.c
字号:
// Copyright (c)2005 - 2006 by Laser Electronics, All Rights Reserved.
/*----------------------------------------------------------------------------+
| File Name: Timer.c, v1.0.1 |
| Author: |
| Date: |
+-----------------------------------------------------------------------------+
| Description: 联网型智能楼宇对讲系统 -- 管理中心机实时时钟驱动程序 |
| 器件选择 -- STC89C58RD+, PQFP-44 |
| 时钟频率 -- 24.000 MHz |
+-----------------------------------------------------------------------------+
/*----------------------------------------------------------------------------+
| Include files |
+----------------------------------------------------------------------------*/
#include "Main.h"
#include "Timer.h"
#include "LCD.h"
/*----------------------------------------------------------------------------+
| Type Definition & Macro |
+----------------------------------------------------------------------------*/
// 与DS1302通信的管脚
#define SCLK P3_7
#define IO P3_6
#define nRST P3_5
/*----------------------------------------------------------------------------+
| Global Variables |
+----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------+
| Internal Variables |
+----------------------------------------------------------------------------*/
BYTE cSecond; // 0.01秒,初始为0,每次系统滴答一下则加1,加到60以后则向秒进位
idata t_Time Time; // 保存当前的时间
idata t_Time TempTime; // 临时保存时间的变量
idata BYTE Hour2Minute; // 小时和分钟之间的那个冒号, 有时为冒号, 有时不显示, 具体在TickCountAdd()中改变
// 定义各个月份的一个月的天数,按照BCD码来排列
code BYTE MonthTable[] = {0x00, 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x30, 0x31};
/*----------------------------------------------------------------------------+
| System Foundation Routines |
+----------------------------------------------------------------------------*/
//
// 复位DS1302
void DS1302_Reset(void)
{
SCLK = 0; // SCLK must be at a logic 0 when nRST is driven to a logic 1 state
nRST = 0;
nRST = 1;
}
//
// 向DS1302发送一个字节的数据
// nData: 需要写入的数据
void DS1302_WriteByte(BYTE nData)
{
BYTE i;
// 最低位在前, 上升沿写入数据
for (i=0; i<8; i++)
{
IO = nData & 0x01;
nData >>= 1;
SCLK = 0;
SCLK = 1;
}
IO = 1;
}
//
// 从DS1302读取一个字节的数据
// 返回: 读到的数据
BYTE DS1302_ReadByte(void)
{
BYTE i;
BYTE temp;
temp = 0x00;
// 最低位在前, 下降沿输出数据
for (i=0; i<8; i++)
{
temp >>= 1;
SCLK = 1;
SCLK = 0;
if (IO)
temp |= 0x80;
}
return temp;
}
/*
//
// 向DS1302发送一个字节的数据
// Addr: 需要读取的寄存器的地址, 只有最低5位有效
// nData: 需要写入的数据
BYTE DS1302_ReadData(BYTE Addr)
{
BYTE temp;
Addr <<= 1;
Addr &= 0x3E; // 保留bit1~bit5, 寄存器地址数据
Addr |= 0x81; // nCK, nWR
SCLK = 0; // SCLK must be at a logic 0 when nRST is driven to a logic 1 state
nRST = 0;
nRST = 1;
// 地址
DS1302_WriteByte(Addr);
// 数据
temp = DS1302_ReadByte();
SCLK = 0;
nRST = 0;
nRST = 1;
SCLK = 1;
IO = 0;
SCLK = 0;
nRST = 0;
return temp;
}
*/
//
// 向DS1302发送一个字节的数据
// Addr: 需要写入的寄存器的地址, 只有最低5位有效
// nData: 需要写入的数据
void DS1302_WriteData(BYTE Addr, BYTE nData)
{
Addr <<= 1;
Addr &= 0x3E; // 保留bit1~bit5, 寄存器地址数据
Addr |= 0x80; // nCK, nWR
SCLK = 0; // SCLK must be at a logic 0 when nRST is driven to a logic 1 state
nRST = 0;
nRST = 1;
// 地址
DS1302_WriteByte(Addr);
// 数据
DS1302_WriteByte(nData);
SCLK = 0;
nRST = 0;
nRST = 1;
SCLK = 1;
IO = 0;
SCLK = 0;
nRST = 0;
}
/*----------------------------------------------------------------------------+
| System Initialization Routines |
+----------------------------------------------------------------------------*/
//
// 初始化实时时钟
void InitRealTimer(void)
{
nRST = 0; // 平常nRST保持低电平
Hour2Minute = ':';
cSecond = 0x00;
DS1302_WriteData(0x07, 0x00); // 清除写保护位
DS1302_WriteData(0x08, 0xAB); // 选择电池充电模式, 高4位始终为1010, 选择2个二极管串联, 8KOhm限流电阻
DS1302_ReadTime();
}
/*----------------------------------------------------------------------------+
| General Subroutines |
+----------------------------------------------------------------------------*/
//
// 系统每10ms产生一次中断,每次中断之后都调用这个函数使时间数据增加0.01秒
void TickCountAdd(void)
{
cSecond ++;
if (cSecond == 50) // 0.5秒, 更新时间显示的冒号
{
Hour2Minute = ' '; // 半秒时候显示空字符
// 正常情况下每0.5秒更新一次显示的时间
SendMessage(MSG_TIME_DISPLAY);
}
else if (cSecond == 100) // 定时时间到了1秒,从DS1302时钟芯片中读取时间并显示
{
cSecond = 0;
Hour2Minute = ':';
DS1302_ReadTime();
SendMessage(MSG_TIME_DISPLAY);
}
}
//
// 从时钟芯片DS1302中读取当前时间
void DS1302_ReadTime(void)
{
// Burst Mode Read
DS1302_Reset();
DS1302_WriteByte(0xBF); // clock burst read (eight registers)
Time.Second = DS1302_ReadByte(); // Second
Time.Minute = DS1302_ReadByte();
Time.Hour = DS1302_ReadByte();
Time.Date = DS1302_ReadByte(); //date
Time.Month = DS1302_ReadByte();
DS1302_ReadByte(); // day of week
Time.Year = DS1302_ReadByte();
DS1302_ReadByte(); // must read control register in burst mode
SCLK = 0;
nRST = 0;
nRST = 1;
SCLK = 1;
IO = 0;
SCLK = 0;
nRST = 0;
/*
Time.Second = DS1302_ReadData(0x00);
Time.Minute = DS1302_ReadData(0x01);
Time.Hour = DS1302_ReadData(0x02);
Time.Date = DS1302_ReadData(0x03);
Time.Month = DS1302_ReadData(0x04);
Time.Year = DS1302_ReadData(0x06);
*/
}
//
// 将时间写入到DS1302时钟芯片中
void DS1302_WriteTime(void)
{
DS1302_WriteData(0x00, 0); // Second
DS1302_WriteData(0x01, Time.Minute);
DS1302_WriteData(0x02, Time.Hour);
DS1302_WriteData(0x03, Time.Date);
DS1302_WriteData(0x04, Time.Month);
DS1302_WriteData(0x06, Time.Year);
}
//
// 更新时间显示缓冲, 保存在一个16位的字符数组当中
void UpdateTimeBuffer(BYTE *Dest)
{
// 格式: "20xx-yy-zz AA:BB"
// 年份, 4位数
Dest[0] = 0x02+0x30;
Dest[1] = 0x00+0x30;
Dest[2] = (Time.Year >> 4) | 0x30;
Dest[3] = (Time.Year&0x0F) | 0x30;
Dest[4] = '-';
// 月份, 2位数
Dest[5] = (Time.Month >> 4) | 0x30;
Dest[6] = (Time.Month&0x0F) | 0x30;
Dest[7] = '-';
// 日期, 2位数
Dest[8] = (Time.Date >> 4) | 0x30;
Dest[9] = (Time.Date&0x0F) | 0x30;
Dest[10] = 0x20; // 空格
// 小时, 2位数
Dest[11] = (Time.Hour >> 4) | 0x30;
Dest[12] = (Time.Hour&0x0F) | 0x30;
Dest[13] = Hour2Minute;
// 分钟, 2位数
Dest[14] = (Time.Minute >> 4) | 0x30;
Dest[15] = (Time.Minute&0x0F) | 0x30;
}
/*----------------------------------------------------------------------------+
| 有关日历的函数
+----------------------------------------------------------------------------*/
//
// 修改时间并且将新的时间写入到时钟芯片DS1302中
// pDate: 一个指向保存有时间信息的字符串的指针,依次为年、月、日、小时、分、秒
BOOL ModifyTime(BYTE *pDate)
{
// 先判断输入是否正确
if (CheckBufferTime(pDate))
{
// 将得到的时间写入到DS1302中
Time.Year = TempTime.Year;
Time.Month = TempTime.Month;
Time.Date = TempTime.Date;
Time.Hour = TempTime.Hour;
Time.Minute = TempTime.Minute;
Time.Second = 0x00;
DS1302_WriteTime();
return TRUE;
}
return FALSE;
}
//
// 判断缓冲区中输入的时间是否正确
BOOL CheckBufferTime(BYTE *pDate)
{
BYTE temp;
// 年
temp = pDate[0] << 4;
temp += pDate[1];
if (temp > 0x99)
{
return FALSE;
}
TempTime.Year = temp;
// 月
temp = pDate[2] << 4;
temp += pDate[3];
if ((temp > 0x12) || (temp == 0x00))
{
return FALSE;
}
TempTime.Month = temp;
// 日
temp = pDate[4] << 4;
temp += pDate[5];
if ((temp > MonthTable[TempTime.Month]) || (temp == 0x00))
{
if (TempTime.Month == 0x02) // 如果是闰年的二月, 则又多出一天
{
if (IsLeapYear(TempTime.Year))
{
if (temp > 0x29) // 闰年二月, 超过了29天
{
return FALSE;
}
}
else
{
return FALSE;
}
}
else
{
return FALSE;
}
}
TempTime.Date = temp;
// 小时
temp = pDate[6] << 4;
temp += pDate[7];
if (temp > 0x24)
{
return FALSE;
}
TempTime.Hour = temp;
// 分
temp = pDate[8] << 4;
temp += pDate[9];
if (temp > 0x59)
{
return FALSE;
}
TempTime.Minute = temp;
return TRUE;
}
//
// 判断是否是闰年, 闰年2月为29天, 这一年为366天
// year: BCD码表示的年份的低2位, 如0x15表示2015年
BOOL IsLeapYear(BYTE year)
{
UINT temp;
temp = year & 0xF0; // 年份的十位数
temp *= 10;
temp += (year & 0x0F);
temp += 2000;
if ((!(temp % 4) && (temp % 100)) || !(temp % 400))
{
return TRUE;
}
return FALSE;
}
/*----------------------------------------------------------------------------+
| End of source file |
+----------------------------------------------------------------------------*/
/*------------------------ Nothing Below This Line --------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -