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

📄 clock.c

📁 可以调整时间的实时时钟
💻 C
字号:
#include "clock.h"

idata unsigned char aucDisplayBuff[8] = {0,0,10,0,0,10,0,0};
code unsigned char aucDisplayCode[12] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};


void Timer2Init(void)		//定时器2初始化,自动重装初值模式	,定时时间为1ms
{
RCAP2H = 0xfc;
RCAP2L = 0x18;
TR2 = 1;
ET2 = 1;
EA = 1;
}


void Delayms(unsigned char time)				//延时函数,实现延时一段时间,具体时间根据晶振调整
{
ucTimerDelay = time;
while(ucTimerDelay != 0);
}

void Display(void)						//显示函数,把显示缓冲区的时间数据送到数码管显示
{
unsigned char i;
for(i = 0;i < 8;i++)
	{
	PortDisplayBit &= 0xf0;			//关显示并清掉P1口低3位
	PortDisplayData = aucDisplayCode[aucDisplayBuff[i]];	//把显示数据送出显示数据口
	PortDisplayBit |= i;			//给P1低3位赋值选通显示器
	PortDisplayBit |= 0x08;			//打开显示
	Delayms(2);
	}
PortDisplayBit &= 0xf7;			//P1.3清零关显示
}

void DisplayReady(void)				//显示前的准备
{
if(ucClockStatu == RUNING)							//如果时钟正在运行,就把显示数据送到显示缓冲区
	{
	aucDisplayBuff[1] = OldHour & 0x0f;
	aucDisplayBuff[0] = OldHour >> 4;
	aucDisplayBuff[4] = OldMinute & 0x0f;
	aucDisplayBuff[3] = OldMinute >> 4;
	aucDisplayBuff[7] = OldSecond & 0x0f;
	aucDisplayBuff[6] = OldSecond >> 4;
	}
if(ucClockStatu == MODIFY_HOU)					//如果时钟正在修改小时,就让小时的数据闪烁显示
	{
	if(bFlagFlshTime)
		{
		aucDisplayBuff[1] = OldHour & 0x0f;
		aucDisplayBuff[0] = OldHour >> 4;
		}
	else
		{
		aucDisplayBuff[1] = 11;
		aucDisplayBuff[0] = 11;
		}
	aucDisplayBuff[4] = OldMinute & 0x0f;
	aucDisplayBuff[3] = OldMinute >> 4;
	aucDisplayBuff[7] = OldSecond & 0x0f;
	aucDisplayBuff[6] = OldSecond >> 4;
	}
else if(ucClockStatu == MODIFY_MIN)					//如果时钟正在修改分钟,就让分钟的数据闪烁显示
	{
	if(bFlagFlshTime)
		{
		aucDisplayBuff[4] = OldMinute & 0x0f;
		aucDisplayBuff[3] = OldMinute >> 4;
		}
	else
		{
		aucDisplayBuff[4] = 11;
		aucDisplayBuff[3] = 11;
		}
	aucDisplayBuff[1] = OldHour & 0x0f;
	aucDisplayBuff[0] = OldHour >> 4;
	aucDisplayBuff[7] = OldSecond & 0x0f;
	aucDisplayBuff[6] = OldSecond >> 4;
	}
else if(ucClockStatu == MODIFY_SEC)					//如果时钟正在修改秒,就让秒显示的数据闪烁显示
	{
	if(bFlagFlshTime)
		{
		aucDisplayBuff[7] = OldSecond & 0x0f;
		aucDisplayBuff[6] = OldSecond >> 4;
		}
	else
		{
		aucDisplayBuff[7] = 11;
		aucDisplayBuff[6] = 11;
		}
	aucDisplayBuff[1] = OldHour & 0x0f;
	aucDisplayBuff[0] = OldHour >> 4;
	aucDisplayBuff[4] = OldMinute & 0x0f;
	aucDisplayBuff[3] = OldMinute >> 4;
	}
}


/************************************************************
*函数名称:DS1302SendByte
*函数功能:向1302发送一个字节的数据
*输入参数:dat
*输出参数:无
*调用模块:无
*作    者:陈海超
*日    期:2007年1月29日
*************************************************************/
void DS1302SendByte(unsigned char dat)
{
unsigned char i;
for(i = 0; i < 8; i++)
	{
	if((dat & 0x01) == 1)
		{
		SDAT = 1;
		}
	else
		{
		SDAT = 0;
		}
	SCLK = 1;
	SCLK = 0;
	dat = dat >> 1;
	}
}

/************************************************************
*函数名称:DS1302GetByte
*函数功能:从1302接收一个字节的数据
*输入参数:无
*输出参数:dat
*调用模块:无
*作    者:陈海超
*日    期:2007年1月29日
*************************************************************/
unsigned char DS1302GetByte(void)
{
unsigned char i;
unsigned char dat = 0;
SDAT = 1;		//置为输入口
for(i = 0; i < 8; i++)
	{
	dat = dat >> 1;
	if(SDAT == 1)
		{
		dat |= 0x80;
		}
	SCLK = 1;
	SCLK = 0;
	}
return (dat);
}

/************************************************************
*函数名称:DS1302SendData
*函数功能:向1302发送数据
*输入参数:addr, dat
*输出参数:无
*调用模块:DS1302SendByte
*作    者:陈海超
*日    期:2007年1月29日
*************************************************************/
void DS1302SendData(unsigned char addr, unsigned char dat)
{
SRST = 0;
SCLK = 0;
SRST = 1;
DS1302SendByte(addr | W_OP);
DS1302SendByte(dat);
SCLK = 1;
SRST = 0;
}

/************************************************************
*函数名称:DS1302GetData
*函数功能:从1302接收数据
*输入参数:addr
*输出参数:无
*调用模块:DS1302SendByte, DS1302GetByte
*作    者:陈海超
*日    期:2007年1月29日
*************************************************************/
unsigned char DS1302GetData(unsigned char addr)
{
unsigned char dat;
SRST = 0;
SCLK = 0;
SRST = 1;
DS1302SendByte(addr | R_OP);
dat = DS1302GetByte();
SCLK = 1;
SRST = 0;
return (dat);
}

void ReadTimeData(void)					//读取当前时间函数
{
NewSecond = DS1302GetData(SEC);			//读秒寄存器
if((NewSecond & 0x7f) != OldSecond)		//如果时间没有更新就不更改显示数据
	{
	if(ucClockStatu != MODIFY_SEC)		//如果当前不是在设定秒时间数据状态就把当前的时间数据代替上一个时间数据
		{
		OldSecond = NewSecond & 0x7f;
		TempSecond = (((OldSecond & 0xf0) >> 4) * 10) + (OldSecond & 0x0f);
		}
	}
NewMinute = DS1302GetData(MIN);			//读分钟寄存器
if(NewMinute != OldMinute)
	{
	if(ucClockStatu != MODIFY_MIN)
		{
		OldMinute = NewMinute;
		TempMinute = (((OldMinute & 0xf0) >> 4) * 10) + (OldMinute & 0x0f);
		}
	}
NewHour = DS1302GetData(HOU);			//读小时寄存器
if((NewHour & 0x3f) != OldHour)
	{
	if(ucClockStatu != MODIFY_HOU)
		{
		OldHour = NewHour & 0x3f;
		TempHour = (((OldHour & 0xf0) >> 4) * 10) + (OldHour & 0x0f);
		}
	}
}



void ScanKeyborad(void)			//键盘扫描程序
{
if(FUNTION_KEY == 0)			//如果是功能键盘按下
	{
	Delayms(10);
	if(FUNTION_KEY == 0)
		{
		while(!FUNTION_KEY)			//等待键盘放开
			{
			ReadTimeData();					//读取时间数据
			DisplayReady();					//准备显示数据
			Display();						//显示
			}
		if(ucClockStatu != RUNING)
			{
			DS1302SendData(HOU,OldHour);
			DS1302SendData(MIN,OldMinute);
			DS1302SendData(SEC,OldSecond);
			}
		ucClockStatu++;
		if(ucClockStatu == 0x04)
			{
			ucClockStatu = RUNING;
			}
		}
	}
if(INCREASE_KEY == 0)			//如果是增加键按下
	{
	Delayms(10);
	if(INCREASE_KEY == 0)
		{
		DS1302SendData(HOU,OldHour);
		DS1302SendData(MIN,OldMinute);
		DS1302SendData(SEC,OldSecond);
		if(ucTimerKeyChange == 0)
			{
			ucTimerKeyChange = 200;
			if(ucClockStatu == MODIFY_HOU)			//如果当前状态在修改小时数据
				{
				TempHour++;
				if(TempHour >= 24)
					{
					TempHour = 0;
					}
				OldHour = ((TempHour / 10) << 4) | (TempHour %10);
				}
			else if(ucClockStatu == MODIFY_MIN)		//如果当前状态在修改分钟数据
				{
				TempMinute++;
				if(TempMinute >= 60)
					{
					TempMinute = 0;
					}
				OldMinute = ((TempMinute / 10) << 4) | (TempMinute %10);
				}
			else if(ucClockStatu == MODIFY_SEC)		//如果当前状态在修改秒钟数据
				{
				TempSecond++;
				if(TempSecond >= 60)
					{
					TempSecond = 0;
					}
				OldSecond = ((TempSecond / 10) << 4) | (TempSecond %10);
				}
			}
		}
	}
if(DECREASE_KEY == 0)			//如果是减少键按下
	{
	Delayms(10);				//延时10MS
	if(DECREASE_KEY == 0)
		{
		DS1302SendData(HOU,OldHour);
		DS1302SendData(MIN,OldMinute);
		DS1302SendData(SEC,OldSecond);
		if(ucTimerKeyChange == 0)
			{
			ucTimerKeyChange = 200;					//当一直按下该键盘时每隔200MS就改变一次数据
			if(ucClockStatu == MODIFY_HOU)			//如果当前状态是在修改小时数据
				{
				TempHour--;
				if(TempHour >= 24)
					{
					TempHour = 23;
					}
				OldHour = ((TempHour / 10) << 4) | (TempHour %10);
				}
			else if(ucClockStatu == MODIFY_MIN)		//如果当前状态是在修改分数据
				{
				TempMinute--;
				if(TempMinute >= 60)
					{
					TempMinute = 59;
					}
				OldMinute = ((TempMinute / 10) << 4) | (TempMinute %10);
				}
			else if(ucClockStatu == MODIFY_SEC)		//如果当前状态是在修改秒数据
				{
				TempSecond--;
				if(TempSecond >= 60)
					{
					TempSecond = 59;
					}
				OldSecond = ((TempSecond / 10) << 4) | (TempSecond %10);
				}
			}
		}
	}
}




main()
{
unsigned char temp;
DS1302SendData(WPR,0x00);			//关闭写保护
temp = DS1302GetData(SEC);			//读出时钟开关,SEC寄存器的第七位是时钟控制位,为0时时钟运行
temp &= 0x7f;						//打开时钟开关
DS1302SendData(SEC,temp);			//写入
temp = DS1302GetData(HOU);
temp &= 0x7f;
DS1302SendData(HOU,temp);			//选择24小时制
DS1302SendData(CHARGER,0xaa);		//开启充电功能,给备用电池充电,选择两个二极管和4K的电阻.
Timer2Init();
while(1)
	{
	ReadTimeData();					//读取时间数据
	DisplayReady();					//准备显示数据
	Display();						//显示
	ScanKeyborad();					//扫描键盘
	}
}



void Timer2Int(void) interrupt TF2_VECTOR using 1		//定时器2中断函数,定时时间为1ms
{
TF2 = 0;								//中断标志软件清零
if(ucTimerKeyChange > 0)
	{
	ucTimerKeyChange--;
	}
if(ucTimerDelay > 0)
	{
	ucTimerDelay--;
	}
uiTimerHalfSecond++;
if(uiTimerHalfSecond == 1000)
	{
	uiTimerHalfSecond = 0;
	}
if(uiTimerHalfSecond < 700)
	{
	bFlagFlshTime = 1;
	}
else 
	{
	bFlagFlshTime = 0;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -