⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timer.c

📁 程序概述: 这是个具体产品程序
💻 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 + -