“可与PC通信的实时时钟”程序设计说明
1 工程文件下载:
2 程序设计框架及关键实现说明
2.1 程序步骤
l voidmain()
调用Init()函数进行初始化,while(1)循环中,首先判断上位机是否连续发送0xf0、寄存器地址、校准值3个字节给下位机。然后通过按键Key1切换显示的数据。
l voidInit()
对函数进行初始化,设置P0,P2为推挽模式,同时设置定时器:
TMOD=0x01;//定时器0,方式1
ET0=1;//开启定时器中断
TH0=(65535-1000)/256;TL0=(65535-1000)%256;
TR0=1;//启动定时器
l voidtimer0() interrupt 1
定时器中断,用于产生延时在数码管上显示数据,并每1ms中向上位机发送数据。在定时器0中断中,调用voidConversion(bit c,unsigned char year,unsigned char month,unsigned char day)函数和Conver_week(0,t.Year,t.Month,t.Day)函数;分别用于将公历转农历和获取具体星期几。
l voidUart1_Init(void)
设置有关串口的参数:
SCON|=0X50; //允许接收
TL1=(65536-(Machine_Focs/4/BAUD1));//定时器1 初始值
TH1=(65536-(Machine_Focs/4/BAUD1))>>8;
l voidUart1_fun() interrupt 4 using 1
串口中断,用于保存上位机发送来的数据,以及判断下位机是否把数据发送到上位机已经完成。
2.2 程序总框架流程图

3 定义及函数说明
3.1 定义说明
#define Machine_Focs11059200L //晶振频率
#define BAUD1 9600 //波特率
#define NMAX_KEY 100 //100次读取按键值
/***********时分秒写寄存器**************/
#define DS1302_SECOND_WRITE0x80
#define DS1302_MINUTE_WRITE0x82
#defineDS1302_HOUR_WRITE 0x84
#defineDS1302_WEEK_WRITE 0x8A
#defineDS1302_DAY_WRITE 0x86
#define DS1302_MONTH_WRITE0x88
#defineDS1302_YEAR_WRITE 0x8C
/***********时分秒读寄存器**************/
#define DS1302_SECOND_READ0x81
#define DS1302_MINUTE_READ0x83
#defineDS1302_HOUR_READ 0x85
#defineDS1302_WEEK_READ 0x8B
#defineDS1302_DAY_READ 0x87
#define DS1302_MONTH_READ0x89
#defineDS1302_YEAR_READ 0x8D
/**********************
引脚别名定义
***********************/
/********DS1302*******/
sbit Rtc_sclk=P1^5;
sbit Rtc_rst=P1^6;
sbit Rtc_io=P5^4;
/********按键******/
sbit Key1=P3^2; //
sbit Key2=P3^3; //
sbit Key3=P1^7; //Key3
/**********************
变量定义
***********************/
ucharduanxuan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //显示0-f 上午A、下午P---0x73
ucharweixuan[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
uchartable_D_BCD[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
ucharflag,temp,second,minute,hour,day,month,week,year,dtime;
bit Uart1_Sendbusy = 0 ;
unsigned char display ;
uchar data_recieve[10]; /*保存接收的字节*/
uchar rec_num;/*接收的字节数*/
//定义时间
typedef struct__SYSTEMTIME__
{
uchar Second;
uchar Minute;
uchar Hour;
uchar Week;
uchar Day;
uchar Month;
uchar Year;
}SYSTEMTIME; //定义的时间类型
SYSTEMTIME t;
uint count_send; // 中断次数
uchar G_count; //记录中断次数
uint Key1_count; //按键1计数
uint Key_count; //总按键次数
bit flg_1ms; //1ms标志位
bit Key1_C;/*key1当前的状态*/
bit Key1_P;/*key1前一个状态*/
bit show_set_flag;
3.2 函数说明
voidDs1302_write(uchar temp) //Ds1302写入一字节
ucharDs1302_read() //Ds1302读取一字节
voidWriteDS1302(uchar Addr, uchar Data) //Addr: DS1302地址,Data: 要写的数据
ucharReadDS1302(uchar cmd) //读出Addr对应的寄存器中的数据
SYSTEMTIMEDS1302_GetTime() //读出DS1302中时、分、秒、年、月、日寄存器中对应的数据
void Uart1_Init(void) //初始化串口1的相关设置,设定串口的波特率等
void SendData(unsigned char dat) //发送单个字符给UART1以发送到PC机
void timer0() interrupt 1 //把数码管的显示提到中断里面来了
void Uart1_fun() interrupt 4 using1 //串口1中断服务程序
/*万年历功能实现相关函数*/
void Conversion(bit c,unsigned char year,unsigned char month,unsignedchar day); //转化成阴历
void Conver_week(bit c,unsigned char year,unsigned char month,unsignedchar day) ; //获取星期
4 相关寄存器配置
Ø 串口相关寄存器:

SCON|=0X50;//对于接收板设置为8位波特率可变允许接收无奇偶校验
Ø DS1302相关寄存器:

其中:
控制字寄存器:写地址0x8E,读地址0x8F
位7:必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。
位6:如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;此程序中没有涉及RAM存取数据,所以位6置为0.
位5~位1(A4~A0):指示操作单元的地址;
位0 :为0写操作,为1读操作。

秒寄存器:
位7:时间暂停位,为1 时钟振荡器停止工作,为 0 时,时钟振荡器启动;
初始化时,要启动时钟振荡器,在禁止写保护的情况下通过如下语句实现:
temp=ReadDS1302(DS1302_SECOND_READ)&0x7f;
WriteDS1302(0x80,temp);//晶振开始工作
小时寄存器:
位7:12 或 24 小时工作模式选择位,为1时12 小时工作模式,此时位5 为 AM/PM 位,低电平对应AM,高电平对应PM;在24 小时模式下,位5 为第二个10 小 时位表示(20~23 时);
写保护寄存器:
位7: WP 是写保护位,工作时除WP 外的其他位都置为0,写操作之前WP 必须 为 0,当 WP 为1时不能进行写操作。
WriteDS1302(0x8E,0x00); //禁止写保护位
WriteDS1302(0x8E,0x80); //写保护位置1
Ø 定时器相关寄存器:
TMOD寄存器:

初始化时,设置定时器0,工作模式1即16位不可重装载模式,TMOD= 0x01 ;
IE寄存器:

初始化时,设置EA=1,打开总的中断,设置ET0=1开启定时器0的中断;
TH0、TL0寄存器:
同时还要设置TH0、TL0的初始值;
TCON寄存器:

初始化时,设置TR0=1启动定时器0
特别补充一下ADC中断号的定义依据如表3所示。
表3 MCS51 C语言中断号定义依据表


