目录
一:介绍
1:具体介绍
2:DS1302总结
3:RTC
二:使用说明
1:电路图和内部结构
A:电路图
B:内部结构
C:CE
D:时钟/日历(SCLK)
E:写保护位
2:命令字节
3:寄存器地址/定义
4:时序图与数据读写
A:单字节写步骤代码(Write)
B: 单字节读步骤代码(Read)
5、BCD码
三:实例代码
1:不可调时钟
2:可调节时钟
DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能
RTC(Real Time Clock):实时时钟,是一种集成电路,通常称为时钟芯片
内部结构框图
作用说明
引脚 | 作用 | 说明 |
VCC2 | 主电源 | |
VCC1 | 备用电源 |
低功率工作在单电源和电池工作系统和低功率备用电池.在使用涓流
充电的系统中,这个管脚连接到可再充能量源.
|
GND | 电源接地 |
电源地
|
X1,X2 |
32.768kHz晶振
|
|
CE | 芯片使能 |
输入.CE信号在读写时必须保持高电平.
|
IO | 数据输入/输出 |
输入/推挽输出.I/O 管脚是三线接口的双向数据管脚.
|
SCLK | 串行时钟 |
输入. SCLK 用来同步串行接口上的数据动作
|
其中,第一行的CH表示时钟暂停控制位,置1表示时钟暂停,置0表示时钟静止;倒数第二行的WP表示write protect(写保护),置1表示写入操作无效;最后一行的TCS用于控制涓流充电,一般不进行设置
xxh(读或写的命令字) eg:80h写入秒的命令字 0x80=1000 0000
1------MSB (位 7)必须是逻辑 1. 如果是 0, 则禁止对 DS1302写入
0-----位 6 在逻辑 0时规定为时钟/日历数据,逻辑 1时为 RAM数据.
00 000----位 1 至 位 5 表示了输入输出的指定寄存器.
0:LSB (位 0) 在逻辑0时为写操作(输出),逻辑 1时为读操作(输入).命令字以 LSB (位 0)开始总是输入
从上述时序图中可以看出,单字节写(Write)有16个脉冲,而单字节读(Read)只有15个脉冲,因为当最后一个命令字的上升沿之后的下降沿数据马上就读出来了
//一般来说&是用来清零的;
//一般来说|是用来值一的;
void DS1302_WriteByte(unsigned char Command,Data)
{
//Command为命令字(地址),Data为要写入的数据
unsigned char i;
DS1302_CE=1; //首先要给CE为1才可以进行写入读出操作
for(i=0;i<8;i++)
{
DS1302_IO=Command&(0x01<
解释:
void DS1302_WriteByte(unsigned char Command,Data){
//一般来说&是用来清零的;
//一般来说|是用来值一的;
DS1302_CE=1; //首先要给CE为1才可以进行写入读出操作
DS1302_IO=Command&0x01; 0x01:0000 0001 取出最低位;将1~7位全部清零
DS1302_SCLK=1;
DS1302_SCLK=0;
DS1302_IO=Command&0x02; 0x01:0000 0010 取出最次位;将0,2~7位全部清零
DS1302_SCLK=1;
DS1302_SCLK=0;
DS1302_IO=Command&0x04; 0x01:0000 0100 取出最2位;将0,1,3~7位全部清零
DS1302_SCLK=1;
DS1302_SCLK=0;
DS1302_CE=0;
/*所以直接使用循环+位移解决全部的问题*/
}
unsigned char DS1302_ReadByte(unsigned char Command){
unsigned char i,Data=0x00;
DS1302_CE=1; //首先要给CE为1才可以进行写入读出操作
for(i=0;i<8;i++){
DS1302_IO=Command&(0x01<
需要把他分为2半, 如果先1后0在第段结束时已经读取到了第二段的开头
BCD码转十进制:DEC=BCD/16*10+BCD%16; (2位BCD)
十进制转BCD码:BCD=DEC/10*16+DEC%10; (2位BCD)
三:实例代码
1:不可调时钟
main.c
#include
#include "LCD1602.h"
#include "Delay.h"
#include "DS1302.h"
void main()
{
LCD_Init();
DS1302_Init();
LCD_ShowString(1,1," - - ");//静态字符初始化显示
LCD_ShowString(2,1," : : ");
DS1302_SetTime();//设置时间
while(1)
{
DS1302_ReadTime();//读取时间
LCD_ShowNum(1,1,DS1302_Time[0],2);//显示年
LCD_ShowNum(1,4,DS1302_Time[1],2);//显示月
LCD_ShowNum(1,7,DS1302_Time[2],2);//显示日
LCD_ShowNum(2,1,DS1302_Time[3],2);//显示时
LCD_ShowNum(2,4,DS1302_Time[4],2);//显示分
LCD_ShowNum(2,7,DS1302_Time[5],2);//显示秒
}
}
DS1302.c
#include
//引脚定义
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;
//寄存器写入地址/指令定义(都为读的命令字)
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_DATE 0x86
#define DS1302_MONTH 0x88
#define DS1302_DAY 0x8A
#define DS1302_YEAR 0x8C
#define DS1302_WP 0x8E
//一般来说&是用来清零的;
//一般来说|是用来值一的;
//时间数组,索引0~6分别为年、月、日、时、分、秒、星期
unsigned char DS1302_Time[]={23,7,16,11,35,55,7};
void DS1302_Init(void)
{
DS1302_CE=0;
DS1302_SCLK=0;
}
//单字节写,Command为命令字(地址),Data为要写入的数据
void DS1302_WriteByte(unsigned char Command,Data){
unsigned char i;
DS1302_CE=1; //首先要给CE为1才可以进行写入读出操作
for(i=0;i<8;i++){
DS1302_IO=Command&(0x01<
DS1302.h
#ifndef __DS1302_H__
#define __DS1302_H__
//用户调用函数:
extern unsigned char DS1302_Time[]; //声明数组位外部可以调用的
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_Init(void);
void DS1302_SetTime(void);
void DS1302_ReadTime(void);
#endif
LCD1602.c
#include
//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0
//函数定义:
/**
* @brief LCD1602延时函数,12MHz调用可延时1ms
* @param 无
* @retval 无
*/
void LCD_Delay()
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
/**
* @brief LCD1602写命令
* @param Command 要写入的命令
* @retval 无
*/
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602写数据
* @param Data 要写入的数据
* @retval 无
*/
void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602设置光标位置
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @retval 无
*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}
/**
* @brief LCD1602初始化函数
* @param 无
* @retval 无
*/
void LCD_Init()
{
LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01);//光标复位,清屏
}
/**
* @brief 在LCD1602指定位置上显示一个字符
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @param Char 要显示的字符
* @retval 无
*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
/**
* @brief 在LCD1602指定位置开始显示所给字符串
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串
* @retval 无
*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}
/**
* @brief 返回值=X的Y次方
*/
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i0;i--)
{
LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD1602指定位置开始以有符号十进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:-32768~32767
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
unsigned char i;
unsigned int Number1;
LCD_SetCursor(Line,Column);
if(Number>=0)
{
LCD_WriteData('+');
Number1=Number;
}
else
{
LCD_WriteData('-');
Number1=-Number;
}
for(i=Length;i>0;i--)
{
LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD1602指定位置开始以十六进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~0xFFFF
* @param Length 要显示数字的长度,范围:1~4
* @retval 无
*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i,SingleNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber=Number/LCD_Pow(16,i-1)%16;
if(SingleNumber<10)
{
LCD_WriteData(SingleNumber+'0');
}
else
{
LCD_WriteData(SingleNumber-10+'A');
}
}
}
/**
* @brief 在LCD1602指定位置开始以二进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~1111 1111 1111 1111
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
}
}
LCD1602.h
#ifndef __LCD1602_H__
#define __LCD1602_H__
//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
#endif
Delay.c
void Delay(unsigned int xms)
{
unsigned char i, j;
while (xms--){
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
Delay.h
#ifndef __DElAY_H__
#define __DElAY_H__
//用户调用函数:
void Delay(unsigned int xms);
#endif
主要是多了2个文件,和主函数的文件,其他的都一样
Key.c
#include
#include "Delay.h"
/**
* @brief 获取独立按键键码
* @param 无
* @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
*/
unsigned char Key()
{
unsigned char KeyNumber=0;
if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
return KeyNumber;
}
Key.h
#ifndef __KEY_H__
#define __KEY_H__
unsigned char Key();
#endif
Timer.c
#include
/**
* @brief 定时器0初始化,1毫秒@12.000MHz 每一毫秒调用一次中段函数
* @param 无
* @retval 无
*/
void Timer0Init(void) //默认的为:定时器时钟12T模式
{
TMOD是不可位寻址,必须8位同时赋值 TMOD=0000 0001
TMOD &= 0xF0; //设置定时器模式 TMOD=TMOD & 1111 0000
/*
TMOD的低四位清零,高四位保持不变;
TMOD=1010 0011
1010 0011 & 1111 0000(0xF0)= 1010 0000
*/
TMOD |= 0x01; //设置定时器模式 TMOD=TMOD | 0000 0001
/*
TMOD的最低位置1,高四位保持不变;
TMOD=1010 0000
1010 0000 | 0000 0001(0x01)= 1010 0001
*/
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
//TCON是可位寻址可以给一个位单独赋值
TF0 = 0; //清除TF0标志;定时器0的溢出标志位
TR0 = 1; //定时器0开始计时
//中断的设置
ET0=1; //打开中断允许位
EA=1; //使能总开关
PT0=0; //中断优先级默认为低
}
//void Timer0Init(void) //1毫秒@12.000MHz
//{
//
// TMOD &= 0xF0; //设置定时器模式
// TMOD |= 0x01; //设置定时器模式
// TL0 = 0x18; //设置定时初值
// TH0 = 0xFC; //设置定时初值
// TF0 = 0; //清除TF0标志
// TR0 = 1; //定时器0开始计时
//} stc自动生成
/*
在这段代码中,定时器的计时和中断调用的过程如下:
1. `Timer0Init()` 函数中的配置和启动操作使得定时器0开始计时。
2. 定时器0以设定的频率进行计数,每次计数器增加一次。
3. 当定时器0的计数器达到设定的初值(0xFC18)时,定时器0会发生溢出。
4. 溢出会导致定时器0的溢出标志 `TF0` 被置位为1,表示发生了溢出事件。
5. 此时,如果定时器0的中断使能位 `ET0` 为1,则中断系统会检测到定时器0的溢出事件。
6. 中断系统会暂停当前的程序执行,跳转到中断向量表中对应定时器0中断的中断向量。
7. 执行定时器0中断服务程序 `Timer0_Routine()`。
8. 在 `Timer0_Routine()` 中,首先进行一些操作,如设置定时器的初值、更新计数变量等。
9. 根据代码逻辑,在每秒(根据计数频率和初值设定)触发一次定时器0中断时,进行时间的更新操作,即将秒数 `Sec` 自增,如果秒数达到60,则将秒数清零,同时将分钟数 `Min` 自增,以此类推。
10. 中断服务程序执行完毕后,返回到原来被中断的地方,继续执行被中断的程序。
11. 上述步骤循环重复,定时器0不断计时并触发中断,中断服务程序周期性地更新时间变量,实现时钟的计时和更新。
总结而言,定时器的调用过程是通过定时器的计数器不断进行计数,当计数器达到设定的初值时发生溢出,触发定时器的中断。中断系统检测到中断标志后,会执行相应的中断服务程序,在服务程序中进行一系列操作,如时间的更新。这样,定时器的计时和中断的调用形成了一个周期性的循环,实现了定时功能。
*/
/*
这是一个用于初始化定时器0的函数 `Timer0Init()` 的代码。让我们逐行解释它的执行过程:
1. `TMOD &= 0xF0;` 是对定时器模式寄存器 `TMOD` 进行位操作,使用位与运算符和掩码 `0xF0`,将 `TMOD` 寄存器的低四位清零。这是为了清除原先的定时器模式设置。
2. `TMOD |= 0x01;` 是对 `TMOD` 进行位操作,使用位或运算符和掩码 `0x01`,将 `TMOD` 寄存器的最低位设置为1。这是为了设置定时器0为模式1,即16位定时/计数模式。
3. `TL0 = 0x18;` 将定时器0的低8位计数器 `TL0` 的值设置为0x18,作为定时器的初值。
4. `TH0 = 0xFC;` 将定时器0的高8位计数器 `TH0` 的值设置为0xFC,作为定时器的初值。
5. `TF0 = 0;` 将定时器0的溢出标志 `TF0` 清零,以确保定时器0初始状态下没有发生溢出。
6. `TR0 = 1;` 启动定时器0,将其置为1,开始计时。
7. `ET0 = 1;` 允许定时器0中断。将定时器0中断使能位 `ET0` 设置为1,以允许定时器0溢出时触发中断。
8. `EA = 1;` 允许总中断。将总中断使能位 `EA` 设置为1,以允许所有中断的触发。
9. `PT0 = 0;` 将定时器0的中断优先级位 `PT0` 设置为0,表示定时器0中断具有标准优先级。
通过以上操作,`Timer0Init()` 函数完成了对定时器0的初始化配置,包括模式设置、初值设置、中断使能等。这样,在程序执行后续操作时,定时器0会按照设定的模式和初值进行计时,并在溢出时触发中断,从而实现定时功能。
*/
/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=1000)
{
T0Count=0;
}
}
*/
Timer.h
#idndef __TIMER_H__
#define __TIMER_H__
void Timer0Init(void);
#endif
main.c
#include
#include "LCD1602.h"
#include "DS1302.h"
#include "Key.h"
#include "Timer.h"
unsigned char KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag;
void TimeShow(void)//时间显示功能
{
DS1302_ReadTime();//读取时间
LCD_ShowNum(1,1,DS1302_Time[0],2);//显示年
LCD_ShowNum(1,4,DS1302_Time[1],2);//显示月
LCD_ShowNum(1,7,DS1302_Time[2],2);//显示日
LCD_ShowNum(2,1,DS1302_Time[3],2);//显示时
LCD_ShowNum(2,4,DS1302_Time[4],2);//显示分
LCD_ShowNum(2,7,DS1302_Time[5],2);//显示秒
}
void TimeSet(void)//时间设置功能
{
if(KeyNum==2)//按键2按下
{
TimeSetSelect++;//设置选择位加1
TimeSetSelect%=6;//越界清零
}
if(KeyNum==3)//按键3按下
{
DS1302_Time[TimeSetSelect]++;//时间设置位数值加1
if(DS1302_Time[0]>99){DS1302_Time[0]=0;}//年越界判断
if(DS1302_Time[1]>12){DS1302_Time[1]=1;}//月越界判断
if( DS1302_Time[1]==1 || DS1302_Time[1]==3 || DS1302_Time[1]==5 || DS1302_Time[1]==7 ||
DS1302_Time[1]==8 || DS1302_Time[1]==10 || DS1302_Time[1]==12)//日越界判断
{
if(DS1302_Time[2]>31){DS1302_Time[2]=1;}//大月
}
else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 || DS1302_Time[1]==9 || DS1302_Time[1]==11)
{
if(DS1302_Time[2]>30){DS1302_Time[2]=1;}//小月
}
else if(DS1302_Time[1]==2)
{
if(DS1302_Time[0]%4==0)
{
if(DS1302_Time[2]>29){DS1302_Time[2]=1;}//闰年2月
}
else
{
if(DS1302_Time[2]>28){DS1302_Time[2]=1;}//平年2月
}
}
if(DS1302_Time[3]>23){DS1302_Time[3]=0;}//时越界判断
if(DS1302_Time[4]>59){DS1302_Time[4]=0;}//分越界判断
if(DS1302_Time[5]>59){DS1302_Time[5]=0;}//秒越界判断
}
if(KeyNum==4)//按键3按下
{
DS1302_Time[TimeSetSelect]--;//时间设置位数值减1
if(DS1302_Time[0]<0){DS1302_Time[0]=99;}//年越界判断
if(DS1302_Time[1]<1){DS1302_Time[1]=12;}//月越界判断
if( DS1302_Time[1]==1 || DS1302_Time[1]==3 || DS1302_Time[1]==5 || DS1302_Time[1]==7 ||
DS1302_Time[1]==8 || DS1302_Time[1]==10 || DS1302_Time[1]==12)//日越界判断
{
if(DS1302_Time[2]<1){DS1302_Time[2]=31;}//大月
if(DS1302_Time[2]>31){DS1302_Time[2]=1;}
}
else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 || DS1302_Time[1]==9 || DS1302_Time[1]==11)
{
if(DS1302_Time[2]<1){DS1302_Time[2]=30;}//小月
if(DS1302_Time[2]>30){DS1302_Time[2]=1;}
}
else if(DS1302_Time[1]==2)
{
if(DS1302_Time[0]%4==0)
{
if(DS1302_Time[2]<1){DS1302_Time[2]=29;}//闰年2月
if(DS1302_Time[2]>29){DS1302_Time[2]=1;}
}
else
{
if(DS1302_Time[2]<1){DS1302_Time[2]=28;}//平年2月
if(DS1302_Time[2]>28){DS1302_Time[2]=1;}
}
}
if(DS1302_Time[3]<0){DS1302_Time[3]=23;}//时越界判断
if(DS1302_Time[4]<0){DS1302_Time[4]=59;}//分越界判断
if(DS1302_Time[5]<0){DS1302_Time[5]=59;}//秒越界判断
}
//更新显示,根据TimeSetSelect和TimeSetFlashFlag判断可完成闪烁功能
if(TimeSetSelect==0 && TimeSetFlashFlag==1){LCD_ShowString(1,1," ");}
else {LCD_ShowNum(1,1,DS1302_Time[0],2);}
if(TimeSetSelect==1 && TimeSetFlashFlag==1){LCD_ShowString(1,4," ");}
else {LCD_ShowNum(1,4,DS1302_Time[1],2);}
if(TimeSetSelect==2 && TimeSetFlashFlag==1){LCD_ShowString(1,7," ");}
else {LCD_ShowNum(1,7,DS1302_Time[2],2);}
if(TimeSetSelect==3 && TimeSetFlashFlag==1){LCD_ShowString(2,1," ");}
else {LCD_ShowNum(2,1,DS1302_Time[3],2);}
if(TimeSetSelect==4 && TimeSetFlashFlag==1){LCD_ShowString(2,4," ");}
else {LCD_ShowNum(2,4,DS1302_Time[4],2);}
if(TimeSetSelect==5 && TimeSetFlashFlag==1){LCD_ShowString(2,7," ");}
else {LCD_ShowNum(2,7,DS1302_Time[5],2);}
}
void main()
{
LCD_Init();
DS1302_Init();
Timer0Init();
LCD_ShowString(1,1," - - ");//静态字符初始化显示
LCD_ShowString(2,1," : : ");
DS1302_SetTime();//设置时间
while(1)
{
KeyNum=Key();//读取键码
if(KeyNum==1)//按键1按下
{
if(MODE==0){MODE=1;TimeSetSelect=0;}//功能切换
else if(MODE==1){MODE=0;DS1302_SetTime();}
}
switch(MODE)//根据不同的功能执行不同的函数
{
case 0:TimeShow();break;
case 1:TimeSet();break;
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=500)//每500ms进入一次
{
T0Count=0;
TimeSetFlashFlag=!TimeSetFlashFlag;//闪烁标志位取反
}
}