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

📄 main.c

📁 新手上路
💻 C
字号:
/***************************
**采用LCD显示时间
**使用T2的16位自动重装模式来精确计时
**clock:18.432M
***************************/
#include "STC89C51RC.H"
#include "intrins.h"
#include "lcd.h"

sbit SW    = P1^0;
sbit BMSW1 = P2^3;
sbit BMSW2 = P2^4;
sbit BMSW  = P2^5;

#define FLASH_BYTE_READ 1
#define FLASH_BYTE_WRITE 2
#define FLASH_SECTOR_CLR 3
#define ISP_TRIG1 0x46
#define ISP_TRIG2 0xb9
#define ISP_EN_T 0x81//设置等待时间和ISP使能
#define FLASH_ADDR_SEC 0x2000//这是第1个扇区,每个扇区512字节,共有10个扇区
#define FLASH_ADDR_MIN 0x2200//这是第2个扇区
#define FLASH_ADDR_HOUR 0x2400//这是第3个扇区

struct time //定义一个存储时间结构
{
	unsigned char hour,min,sec;
};
struct time curtime = {0,0,0};//用于存放当前时间
struct time disptime = {24,60,60};//用于存放显示时间,赋个不正确的值,上电时用来刷新显示
extern unsigned char pdata disp_buffer[15];
unsigned char delayNs;
unsigned char delayN33ms;


/***********************************************
功能:时钟计时中断
描述:定时器2的中断服务程序,每33ms重装一次定时器
     18.432M晶振,30次中断为1秒
参数:无
返回:无
***********************************************/
void timer2_int() interrupt 5 using 3
{
	static unsigned char time2_count = 0;
	TF2 = 0;//time2需要软件清除中断标志位
	time2_count++;
	delayN33ms--;
	if(time2_count >= 30)
	{
		time2_count = 0;
		delayNs--;
		curtime.sec++;
	}
	if(curtime.sec >= 60)
	{
		curtime.sec = 0;
		curtime.min++;
	}
	if(curtime.min >= 60)
	{
		curtime.min = 0;
		curtime.hour++;
	}
	if(curtime.hour >= 24)curtime.hour = 0;
}

/***********************************************
功能:FLASH扇区擦除
描述:擦除1个扇区
参数:扇区地址
返回:无
***********************************************/
void flash_clr(unsigned int sector_addr)
{
	ISP_ADDRH = sector_addr >> 8;
	ISP_ADDRL = sector_addr & 0x00ff;
	ISP_CONTR = ISP_EN_T;
	ISP_CMD = FLASH_SECTOR_CLR;
	ISP_TRIG = 0x46;
	ISP_TRIG = 0xb9;//0x46,0xb9是特定的触发信号
	_nop_();
}


/***********************************************
功能:FLASH写
描述:写1个字节至FLASH
参数:地址,要写的1个字节数据
返回:无
***********************************************/
void flash_write(unsigned int addr,unsigned char byte)
{
	ISP_DATA = byte;
	ISP_ADDRH = addr >> 8;
	ISP_ADDRL = addr & 0x00ff;
	ISP_CONTR = ISP_EN_T;
	ISP_CMD = FLASH_BYTE_WRITE;
	ISP_TRIG = 0x46;
	ISP_TRIG = 0xb9;//0x46,0xb9是特定的触发信号
	_nop_();
}

/***********************************************
功能:FLASH读
描述:读1个字节从FLASH
参数:地址
返回:读出的1个字节数据
***********************************************/
unsigned char flash_read(unsigned int addr)
{
	ISP_ADDRH = addr >> 8;
	ISP_ADDRL = addr & 0x00ff;
	ISP_CONTR = ISP_EN_T;
	ISP_CMD = FLASH_BYTE_READ;
	ISP_TRIG = 0x46;
	ISP_TRIG = 0xb9;//0x46,0xb9是特定的触发信号
	_nop_();
	return(ISP_DATA);
}

/***********************************************
功能:主函数
描述:主函数
参数:无
返回:无
***********************************************/
void main (void)
{
	unsigned char i,j;
	unsigned char stat = 0;
	bit bmsw_temp,wink;
	IE = 0xa0;//中断允许ET2
	RCAP2H = 0x38;//自动重装数
	RCAP2L = 0x00;//33MS中断一次
	T2CON = 0x04;//T2工作在16位自动重装模式并开始计时

	P0 = 0xff;
	P1 = 0xff;
	P2 = 0xff;
	P3 = 0xff;

	bmsw_temp = BMSW1;//
	lcd_init();//LCD 初始化
//	while(delay3s);
//	write_char(1,37);//第一个字符全显
	disp_buffer[0] = 0x12;//显示两处间隔秒点
	lcd_update(0,1);
	if(SW)//这样来控制上电时是否读FLASH
	{
		curtime.sec = flash_read(FLASH_ADDR_SEC);//读FLASH,
		curtime.min = flash_read(FLASH_ADDR_MIN);//读FLASH,
		curtime.hour = flash_read(FLASH_ADDR_HOUR);//读FLASH,
	}
	do//主循环
	{
		if(disptime.sec != curtime.sec)
		{
			disptime.sec = curtime.sec;
			flash_clr(FLASH_ADDR_SEC);//flash扇区擦除
			flash_write(FLASH_ADDR_SEC,curtime.sec);//flash写
			i = disptime.sec / 10;
			j = disptime.sec % 10;
			write_char(7,i);
			write_char(8,j);
		}
		if(disptime.min != curtime.min)
		{
			disptime.min = curtime.min;
			flash_clr(FLASH_ADDR_MIN);//flash扇区擦除
			flash_write(FLASH_ADDR_MIN,curtime.min);//flash写
			i = disptime.min / 10;
			j = disptime.min % 10;
			write_char(5,i);
			write_char(6,j);
		}
		if(disptime.hour != curtime.hour)
		{
			disptime.hour = curtime.hour;
			flash_clr(FLASH_ADDR_HOUR);//flash扇区擦除
			flash_write(FLASH_ADDR_HOUR,curtime.hour);//flash写
			i = disptime.hour / 10;
			j = disptime.hour % 10;
			write_char(3,i);
			write_char(4,j);
		}
//		disptime = curtime;//把系统时间送去显示.为什么用这句话代码大了266字节,而且刷新LCD太不及时???

		if(bmsw_temp != BMSW1)
		{
			if(bmsw_temp == BMSW2)
			{
				switch(stat)
				{
					case 1: curtime.hour++;//顺时针加
							delayN33ms = 10;//333毫秒,调节时闪烁
							delayNs = 6;
							if(curtime.hour >= 24)curtime.hour = 0;
							break;
					case 2: curtime.min++;//顺时针加
							delayN33ms = 10;//333毫秒,调节时闪烁
							delayNs = 6;
							if(curtime.min >= 60)curtime.min = 0;
							break;
					case 3: curtime.sec++;//顺时针加
							delayN33ms = 10;//333毫秒,调节时闪烁
							delayNs = 6;
							if(curtime.sec >= 60)curtime.sec = 0;
							break;
					default:break;
				}
			}
			else
			{
				switch(stat)
				{
					case 1: curtime.hour--;//逆时针减
							delayN33ms = 10;//333毫秒,调节时闪烁
							delayNs = 6;
							if(curtime.hour >= 24)curtime.hour = 23;
							break;
					case 2: curtime.min--;//逆时针减
							delayN33ms = 10;//333毫秒,调节时闪烁
							delayNs = 6;
							if(curtime.min >= 60)curtime.min = 59;
							break;
					case 3: curtime.sec--;//逆时针减
							delayN33ms = 10;//333毫秒,调节时闪烁
							delayNs = 6;
							if(curtime.sec >= 60)curtime.sec = 59;
							break;
					default:break;
				}
			}
//			while(BMSW1 == BMSW2);
			bmsw_temp = BMSW1;
		}
		if(!BMSW)
		{
			stat++;
			if(stat > 3)stat = 0;
			wink = 0;//调时闪烁标记
			disptime.hour = 24;//为了防止退出调节时间时显示空
			disptime.min = 60;
			disptime.sec = 60;
/*			switch(stat)
			{
				case 1: write_char(1,'H');//第一位显示H代表当前调节时
						delayNs = 6;
						break;
				case 2: write_char(1,'M');//第一位显示M代表当前调节分
						delayNs = 6;
						break;
				case 3: write_char(1,'S');//第一位显示S代表当前调节秒
						delayNs = 6;
						break;
				default:write_char(1,37);//第一位全显代表当前不在调节状态
						break;
			}*/
		}
		while(!BMSW){delayNs = 6;delayN33ms = 0;}
		if(!delayN33ms && stat)
		{
			wink = !wink;
			delayN33ms = 10;//333毫秒,调节时闪烁
			switch(stat)
			{
				case 1: if(wink)
						{	disptime.hour = 24;}
						else
						{
							write_char(3,10);
							write_char(4,10);
						}
						break;
				case 2: if(wink)
						{	disptime.min = 60;}
						else
						{
							write_char(5,10);
							write_char(6,10);
						}
						break;
				case 3: if(wink)
						{	disptime.sec = 60;}
						else
						{
							write_char(7,10);
							write_char(8,10);
						}
						break;
				default:break;
			}
		}
		if(!delayNs)
		{
			stat = 0;
			disptime.hour = 24;//为了退出调节时间时刷新显示
			disptime.min = 60;
			disptime.sec = 60;
		}
	}
	while(1);
}

⌨️ 快捷键说明

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