📄 main.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 + -