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

📄 main_c.c

📁 实现时间定时功能 用DS1307芯片显示年月日 并有报警信息!可以下载来直接应用
💻 C
字号:
/*/////////////////////////////////////////////////////
	文件名	:	main.c
	功  能	:	Time helper 主模块
	控制器	:	AT89S52
	时钟	:	11.0592
	编译器	:	Keil C51 7.0
*/////////////////////////////////////////////////////

#include "common.h"

sbit LED   	=	P3^5;
sbit BEEP	=	P1^4;
sbit BEEP_EX=	P0^0;
sbit RADIO	=	P3^7;

#define SETLED	LED=0
#define CLRLED	LED=1
#define SETBEEP	BEEP_EX=BEEP=0
#define CLRBEEP BEEP_EX=BEEP=1
#define SETRADIO RADIO=0;
#define CLRRADIO RADIO=1;

uchar g_time[3];		//时间计数器   存储格式:h,m,s
uchar g_alarm_time[3];	//报警时间缓冲 存储格式:h,m,alarm index
uchar g_minflag=0;		//过分钟标记

//延时
void DelayMs(uint n)
{
	uint i;
	uchar j;
	for(i=0;i<n;i++)
	for(j=0;j<150;j++);
}

//初始化
void Initial(void)
{
	CLRLED;
	CLRBEEP;
	CLRRADIO;
	lcd_initial();
	lcd_clear();
	eep_init();
	RTC_Enable();
	Uart_Enable();
	EA=1;//总中断允许
}

/********计数模块*****************/

//time1-time2 返回分钟
//从TIME1到TIME2的时间
uint GetTimeDefference(uchar *time1,uchar *time2)
{
	uchar tmp=time2[0];
	uint ret=0;
	if(time2[0]<time1[0])
		tmp+=24;
	else if(time2[0]==time1[0])
	{
		if(time2[1]<=time1[1])
			tmp+=24;
	}
	
	ret=(tmp-time1[0])*60;
	ret+=time2[1];	
	ret-=time1[1];
	return ret;
}

//计数模块要检测报警时间
//获取下一次报警时间
void GetNextAlarmTime(void)
{
	uchar i,tmpbuf[2];
	uchar index=0;//记录最小时差的报警索引
	uint minval=24*60,tmp;

	for(i=0;i<5;i++)//找出在EEPROM五个记录中时间距离最近的一项
	{
		eep_readstring(i*24,tmpbuf,2);
		tmp=GetTimeDefference(g_time,tmpbuf);
		if(tmp<minval)
		{
			minval=tmp;
			index=i;
		}
	}
	eep_readstring(index*24,g_alarm_time,2);
	g_alarm_time[2]=index;//报警信息在EEPROM里存的索引
}

//在计时模式时格式化显示时间
void BeginDisplayTime(uchar *p)
{
	//将年月日、星期、时分显示到LCD
	uchar disbuf[6];
	lcd_clear();
	
	disbuf[0]=(p[6]>>4)+48;//年高
	disbuf[1]=(p[6]&0x0f)+48;//年低
	
	disbuf[2]='-';
	
	disbuf[3]=(p[5]>>4)+48;//月高
	disbuf[4]=0;
	
	lcd_displaystring(disbuf,0);
	
	disbuf[0]=(p[5]&0x0f)+48;//月低
	disbuf[1]='-';
	
	disbuf[2]=(p[4]>>4)+48;//日高
	disbuf[3]=(p[4]&0x0f)+48;//日低
	disbuf[4]=0;
	lcd_displaystring(disbuf,2);
	
	disbuf[0]=32;
	disbuf[1]=p[3]+48;
	disbuf[2]='d';
	disbuf[3]='a';
	disbuf[4]='y';
	disbuf[5]=0;
	lcd_displaystring(disbuf,4);
	
	disbuf[0]=((p[2]&0x3f)>>4)+48;//小时
	disbuf[1]=(p[2]&0x0f)+48;
	
	disbuf[2]=':';
	disbuf[3]=' ';
	disbuf[4]=0;
	lcd_displaystring(disbuf,7);
	
	disbuf[0]=(p[1]>>4)+48;
	disbuf[1]=(p[1]&0x0f)+48;
	disbuf[2]=0;
	lcd_displaystring(disbuf,9);
}
//进入计时模式功能函数
void EnterClockMode(void)
{
	uchar *p=RTC_GetBuffer();
	while(1)
	{
		RTC_ClearError();
		RTC_UpdateData(1);
		if(RTC_GetError())
		{
			lcd_displaystring("RTC error! retry...",0);
			SETLED;
			DelayMs(500);
			CLRLED;
			DelayMs(500);
		}
		else
			break;
	}
	
	g_time[0]=((p[2]&0x3f)>>4)*10+(p[2]&0x0f);//h
	g_time[1]=(p[1]>>4)*10+(p[1]&0x0f);//m
	g_time[2]=0;//s		
	
	BeginDisplayTime(p);
	GetNextAlarmTime();
	
	RTC_SetSQWOutput(1,1);//1Hz output
	
	IT1=1;//外部中断1边沿触发
	EX1=1;//外部中断1允许
}

//离开计时模式
void LeaveClockMode(void)
{
	EX1=0;//外部中断1禁止
	RTC_SetSQWOutput(0,0);//1Hz output disable
	
}
//外部中断1,信号来自DS1307 1Hz 输出
void IntSQW1Hz() interrupt 2 
{
	g_time[2]++;
	if(g_time[2]==60)
	{
		g_time[2]=0;
		g_minflag=1;
	}
}
////////////////////////////////////////////////////

/*为串口操作存储器提供的6个函数*/
void WriteEeprom(void)
{
	uchar i,addr;
	uchar *p=Uart_GetBuffer();

	p[0]=0xaa;
	Uart_Send(1);//回应
	Uart_Recv(10,UART_WAIT);	
	
	addr=p[0]*24;

	eep_writestring(addr,p+1,4);
	addr+=4;
	
	for(i=0;i<2;i++)
	{
		p[0]=0xaa;
		Uart_Send(1);//回应
		Uart_Recv(10,UART_WAIT);	
		
		eep_writestring(addr,p,10);
		addr+=10;
	}
	
	p[0]=0xaa;
	Uart_Send(1);//回应	
}
void ReadEeprom(void)
{
	uchar i;
	uchar *p=Uart_GetBuffer();
	for(i=0;i<120;)
	{
		eep_readstring(i,p,2);
		Uart_Send(2);
		i+=2;
	}
}
//写DS1307 ram
void WriteRTCRam(void)
{
	uchar i;
	uchar *p=Uart_GetBuffer();
	
	for(i=0;i<5;i++)
	{
		p[0]=0xaa;
		Uart_Send(1);
		Uart_Recv(10,UART_WAIT);
		RTC_WriteRAM(i*10,p,10);
	}
	p[0]=0xaa;
	Uart_Send(1);
}
//读DS1307 ram
void ReadRTCRam(void)
{
	uchar i;
	uchar *p=Uart_GetBuffer();
	
	for(i=0;i<5;i++)
	{	
		RTC_ReadRAM(i*10,p,10);
		Uart_Send(10);
	}	
}
//设置当前时间
void SetCurrentTime()
{
	uchar i;
	uchar *p=Uart_GetBuffer();
	uchar *p1=RTC_GetBuffer();
	
	p[0]=0xaa;
	Uart_Send(1);//确认准备好
	
	Uart_Recv(7,UART_WAIT);//读时间数据
	for(i=0;i<7;i++)
		p1[i]=p[i];
	
	RTC_UpdateData(0);//写ds1307
	
	p[0]=0xaa;//确认操作成功
	Uart_Send(1);
}
//获取当前时间
void GetCurrentTime()
{
	uchar i;
	uchar *p=Uart_GetBuffer();
	uchar *p1=RTC_GetBuffer();
	
	RTC_UpdateData(1);//从DS1307读时间数据
	
	for(i=0;i<7;i++)
		p[i]=p1[i];	
		
	Uart_Send(7);
}
///////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////
//报警功能函数////////////////////////////////////////////
void Alarm(uchar index)
{
	uchar temp[5],i;
	uint *p=(uint *)temp;
	
	//显示报警字符
	lcd_clear();	
	for(i=0;i<5;i++)
	{
		eep_readstring(index*24+4+i*4,temp,4);
		temp[4]=0;
		lcd_displaystring(temp,i*2);
	}
	
	//读报警类型及持续时间
	eep_readstring(index*24+2,temp,2);
	
	if(temp[0]==1)//led alarm
	{
		for(i=0;i<temp[1];i++)
		{
			SETLED;
			DelayMs(800);
			CLRLED;
			DelayMs(800);
		}
	}
	else if(temp[0]>1 &&temp[0]<6)//play music
	{
		for(i=0;i<temp[1];i++)
			MusicPlay(temp[0]-2);
	}
	else if(temp[0]==6)//beep
	{
		for(i=0;i<temp[1];i++)
		{
			SETBEEP;
			DelayMs(500);
			CLRBEEP;
			DelayMs(800);
		}		
	}
	else if(temp[0]==7)//radio alarm
	{
		SETRADIO;
		for(i=0;i<temp[1];i++)
			DelayMs(1200);
		CLRRADIO;
	}
}

//主入口////////////////////////////////////////////////////
int main(void)
{
	uchar *p;
	
	//等待系统稳定
	DelayMs(2000);
	
	//初始化各功能
	Initial();
	
	//串行口异步接收一字节
	Uart_Recv(1,UART_NO_WAIT);
	
	//进入计时模式
	EnterClockMode();	
	
	//主循环
	while(1)
	{
		//根据分钟标记更新计数器并更新显示
		if(g_minflag)
		{
			if(++g_time[1]==60)
			{
				if(++g_time[0]==24)
				{
					g_time[0]=0;
				}
				lcd_displaynum(g_time[0],7);
				g_time[1]=0;
			}
			lcd_displaynum(g_time[1],9);
			g_minflag=0;
		}
		
		//报警检测、如果满足条件进入报警状态
		if((g_time[1]==g_alarm_time[1]) && (g_time[0]==g_alarm_time[0]))
		{
			LeaveClockMode();
			Uart_Disable();
			Alarm(g_alarm_time[2]);
			Uart_Enable();
			EnterClockMode();
		}
		
		//串口是否有数据//////////////////////////////////////
		if(!Uart_IsWaitRecv())
		{
			p=Uart_GetBuffer();
			LeaveClockMode();
			//lcd_clear();
			switch(p[0])
			{
			case 0xAA: //写EEPROM
				//lcd_displaystring("write eeprom...",0);
				WriteEeprom();
				break;
			case 0xAB://读EEPROM
				//lcd_displaystring("read eeprom...",0);
				ReadEeprom();
				break;
			case 0xac://写DS1307 RAM
				//lcd_displaystring("write ram...",0);
				WriteRTCRam();
				break;
			case 0xad://读DS1307 RAM
				//lcd_displaystring("read ram...",0);
				ReadRTCRam();
				break;
			case 0xae:
				//lcd_displaystring("set time...",0);
				SetCurrentTime();
				break;
			case 0xaf:
				//lcd_displaystring("get time...",0);
				GetCurrentTime();
				break;
			case 1:
				//p[0]=g_alarm_time[0];
				//p[1]=g_alarm_time[1];
				//Uart_Send(2);
				break;
			default:
				//lcd_displaystring("Recved:",0);
				//p[0]%=100;
				//lcd_displaynum(p[0],9);
				break;
			}
			Uart_Recv(1,UART_NO_WAIT);//异步接收下一命令字节
			EnterClockMode();
		}//switch (uart)
		//////////////////////////////////////////////////////
	}//while
}//main
//////////////////////////////////////////////////////////////

 

⌨️ 快捷键说明

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