1. 单片机日历时钟系统
//给你一个DS1302的库函数
//液晶那个库要的话也能给你哈
//#include "intrins.h"
sbit DS1302_clk=0xa0;
sbit DS1302_data=0xa1;
sbit DS1302_cs=0xa2;
unsigned char year,month,date,hour,minute,second,week;
//unsigned char display_buffer[6];
void short_ds1302_delay();//短延时
void long_ds1302_delay();//长延时
void DS1302_write(unsigned char DS1302_temp); //写入一个字节
unsigned char DS1302_read(void); //读一字节
void DS1302_init();//ds1302初始化
void DS1302_write_time(int command,int dat);//写入second or minute or hour...... or 写入一个命令
unsigned char DS1302_read_time(int command);//读取second or minute or hour......
void short_ds1302_delay()
{
unsigned char i;
for(i=0;i<5;i++);
}
void long_ds1302_delay()
{
unsigned char i;
for(i=0;i<25;i++);
}
void DS1302_write(unsigned char DS1302_temp) //写入一个字节
{
unsigned char i,temp;
long_ds1302_delay();
temp=DS1302_temp;
for(i=0;i<8;i++)
{
DS1302_data=temp&0x01;
short_ds1302_delay();
DS1302_clk=1;
short_ds1302_delay();
DS1302_clk=0;
temp=temp>>1;
}
}
unsigned char DS1302_read(void) //读一字节
{
unsigned char i,temp;
long_ds1302_delay();
temp=0;
for(i=0;i<8;i++)
{
temp=temp>>1;
if(DS1302_data==1)
temp=temp+0x80;
DS1302_clk=1;
short_ds1302_delay();
DS1302_clk=0;
short_ds1302_delay();
}
return temp;
}
/*
/////////写操作设置,当a=0x80时禁止写操作,a=0x00时允许////////////////
void DS1302_write_able(unsigned char a)
{
DS1302_cs=0;
DS1302_clk=0;
short_ds1302_delay();
DS1302_cs=1;
DS1302_write(0x8e);
DS1302_data=1;
DS1302_write(a);
DS1302_cs=0;
short_ds1302_delay();
DS1302_clk=1;
}
/////////读操作设置,当a=0x80时禁止读操作,a=0x00时允许////////////////
void DS1302_read_able(unsigned char a)
{
DS1302_cs=0;
DS1302_clk=0;
short_ds1302_delay();
DS1302_cs=1;
DS1302_write(0x8f);
DS1302_data=1;
DS1302_write(a);
DS1302_cs=0;
short_ds1302_delay();
DS1302_clk=1;
}
*/
////////////////////ds1302初始化////////////////////////
void DS1302_init()
{
unsigned char i;
DS1302_write_time(0x8e,0x00); //允许写操作
DS1302_cs=0;
DS1302_clk=0;
short_ds1302_delay();
DS1302_cs=1;
DS1302_write(0x81);
DS1302_data=1;
i=DS1302_read();
DS1302_cs=0;
short_ds1302_delay();
DS1302_clk=1;
second=((i>>4)&0x07)*10+(i&0x0f);
DS1302_clk=0;
short_ds1302_delay();
DS1302_cs=1;
DS1302_write(0x80);
DS1302_data=1;
DS1302_write(0x7f&i);
DS1302_cs=0;
short_ds1302_delay();
DS1302_clk=1;
DS1302_clk=0; //充电设置
short_ds1302_delay();
DS1302_cs=1;
DS1302_write(0x90);
DS1302_data=1;
// DS1302_write(0xa6); //允许充电,一个二极管 4k电阻
DS1302_write(0x00); //禁止充电
DS1302_cs=0;
short_ds1302_delay();
DS1302_clk=1;
DS1302_write_time(0x8e,0x80); //禁止写操作
}
unsigned char DS1302_read_time(int command)//读取second or minute or hour......
{
unsigned char i;
DS1302_clk=0;
short_ds1302_delay();
DS1302_cs=1;
DS1302_write(command);
DS1302_data=1;
i=DS1302_read();
DS1302_cs=0;
short_ds1302_delay();
DS1302_clk=1;
return i;
}
void DS1302_readdate()
{
unsigned char i;
DS1302_cs=0;
//读取second
i=DS1302_read_time(0x81);
second=((i>>4)&0x07)*10+(i&0x0f);
//读取分minute
i=DS1302_read_time(0x83);
minute=((i>>4)&0x07)*10+(i&0x0f);
//读取时hour
i=DS1302_read_time(0x85);
hour=((i>>4)&0x03)*10+(i&0x0f);
//读取日date
i=DS1302_read_time(0x87);
date=((i>>4)&0x03)*10+(i&0x0f);
//读取月份month
i=DS1302_read_time(0x89);
month=((i>>4)&0x01)*10+(i&0x0f);
//读取周week
i=DS1302_read_time(0x8b);
week=i&0x07;
//读取年份year
i=DS1302_read_time(0x8d);
year=((i>>4)&0x0f)*10+(i&0x0f);
}
void DS1302_write_time(int command,int dat)//写入second or minute or hour...... or 写入一个命令
{
DS1302_clk=0;
short_ds1302_delay();
DS1302_cs=1;
DS1302_write(command);
DS1302_data=1;
DS1302_write(dat);
DS1302_cs=0;
short_ds1302_delay();
DS1302_clk=1;
}
void DS1302_writedate()
{
DS1302_write_time(0x8e,0x00); //允许写操作
DS1302_cs=0;
//写second
DS1302_write_time(0x80,0x7f&(((second/10)<<4)+(second%10)));
//minute
DS1302_write_time(0x82,0x7f&(((minute/10)<<4)+(minute%10)));
//hour
DS1302_write_time(0x84,0x3f&(((hour/10)<<4)+(hour%10)));
//date
DS1302_write_time(0x86,0x3f&(((date/10)<<4)+(date%10)));
//month
DS1302_write_time(0x88,0x1f&(((month/10)<<4)+(month%10)));
//week
DS1302_write_time(0x8a,0x07&week);
//year
DS1302_write_time(0x8c,((year/10)<<4)+(year%10));
DS1302_write_time(0x8e,0x80); //禁止写操作
}
2. 跪求 51单片机+12864液晶+1302时钟制成的万年历c程序
顶层文件 万年历.C
#include<reg51.h>
#include "LCD1602.h"
#include "DS1302.h"
#define uchar unsigned char
#define uint unsigned int
sbit speaker=P2^4;
bit key_flag1=0,key_flag2=0;
SYSTEMTIME adjusted;
uchar sec_add=0,min_add=0,hou_add=0,day_add=0,mon_add=0,yea_add=0;
uchar data_alarm[7]={0};
/************键盘控制******************************/
int key_scan() //扫描是否有键按下
{ int i=0;
uint temp;
P1=0xf0;
temp=P1;
if(temp!=0xf0)
i=1;
else
i=0;
return i;
}
uchar key_value() //确定按键的值
{
uint m=0,n=0,temp;
uchar value;
uchar v[4][3]={'2','1','0','5','4','3','8','7','6','b','a','9'} ;
P1=0xfe; temp=P1; if(temp!=0xfe)m=0;
P1=0xfd;temp=P1 ;if(temp!=0xfd)m=1;
P1=0xfb;temp=P1 ;if(temp!=0xfb)m=2;
P1=0xf7;temp=P1 ;if(temp!=0xf7)m=3;
P1=0xef;temp=P1 ;if(temp!=0xef)n=0;
P1=0xdf;temp=P1 ;if(temp!=0xdf)n=1;
P1=0xbf;temp=P1 ;if(temp!=0xbf)n=2;
value=v[m][n];
return value;
}
/***************************设置闹铃函数*******************************/
void naoling(void)
{
uchar i=0,l=0,j;
init1602();
while(key_flag2&&i<12)
if(key_scan()){j=key_value();write_data(j);if(i%2==0)data_alarm[l]=(j-'0')*10;else {data_alarm[l]+=(j-'0');l++;}i++;delay(600);}
write_com(0x01);
}
uchar according(void)
{ uchar k;
if(data_alarm[0]==adjusted.Year&&data_alarm[1]==adjusted.Month&&data_alarm[2]==adjusted.Day&&data_alarm[3]==adjusted.Hour&&data_alarm[4]==adjusted.Minute&&data_alarm[5]==adjusted.Second)
k=1;
else k=0;
return k;
}
void speak(void)
{uint i=50;
while(i)
{speaker=0;
delay(1);
speaker=1;
delay(1);
i--;
}
}
void alarm(void)
{uint i=10;
while(i)
{
speak();
delay(10);
i--;
}
}
/**************************修改时间操作********************************/
void reset(void)
{
sec_add=0;
min_add=0;
hou_add=0;
day_add=0;
mon_add=0;
yea_add=0 ;
}
void adjust(void)
{
if(key_scan()&&key_flag1)
switch(key_value())
{case '0':sec_add++;break;
case '1':min_add++;break;
case '2':hou_add++;break;
case '3':day_add++;break;
case '4':mon_add++;break;
case '5':yea_add++;break;
case 'b':reset();break;
default: break;
}
adjusted.Second+=sec_add;
adjusted.Minute+=min_add;
adjusted.Hour+=hou_add;
adjusted.Day+=day_add;
adjusted.Month+=mon_add;
adjusted.Year+=yea_add;
if(adjusted.Second>59) adjusted.Second=adjusted.Second%60;
if(adjusted.Minute>59) adjusted.Minute=adjusted.Minute%60;
if(adjusted.Hour>23) adjusted.Hour=adjusted.Hour%24;
if(adjusted.Day>31) adjusted.Day=adjusted.Day%31;
if(adjusted.Month>12) adjusted.Month=adjusted.Month%12;
if(adjusted.Year>100) adjusted.Year=adjusted.Year%100;
}
/**************************中断处理函数*********************************/
void changing(void) interrupt 0 using 0 //需要修改时间和日期,或者停止修改
{
if(key_flag1)key_flag1=0;
else key_flag1=1;
}
void alarming(void) interrupt 3 using 0 //需要设置闹铃或者停止设置
{
if(key_flag2)key_flag2=0;
else key_flag2=1;
}
/********************************主函数***********************************/
main()
{uint i;
uchar *l;
uchar p1[]="D:",p2[]="T:";
SYSTEMTIME T;
EA=1;
EX0=1;
IT0=1;
EA=1;
EX1=1;
IT1=1;
init1602();
Initial_DS1302() ;
while(1)
{ write_com(0x80);
write_string(p1,2);
write_com(0xc0);
write_string(p2,2);
DS1302_GetTime(&T) ;
adjusted.Second=T.Second;
adjusted.Minute=T.Minute;
adjusted.Hour=T.Hour;
adjusted.Week=T.Week;
adjusted.Day=T.Day;
adjusted.Month=T.Month;
adjusted.Year=T.Year;
for(i=0;i<9;i++)
{
adjusted.DateString[i]=T.DateString[i];
adjusted.TimeString[i]=T.TimeString[i];
}
adjust();
if(key_flag2)naoling();
if(according())alarm();
DateToStr(&adjusted);
TimeToStr(&adjusted);
write_com(0x82);
write_string(adjusted.DateString,8);
write_com(0xc2);
write_string(adjusted.TimeString,8);
delay(10);
}
(二)头文件1 显示模块 LCD1602.H
#ifndef LCD_CHAR_1602_2009_5_9
#define LCD_CHAR_1602_2009_5_9
#define uchar unsigned char
#define uint unsigned int
sbit lcdrs = P2^0;
sbit lcdrw = P2^1;
sbit lcden = P2^2;
void delay(uint z) // 延时
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com) // 写入指令数据到 lcd
{
lcdrw=0;
lcdrs=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date) // 写入字符显示数据到 lcd
{
lcdrw=0;
lcdrs=1;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init1602() // 初始化设定
{
lcdrw=0;
lcden=0;
write_com(0x3C);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
}
void write_string(uchar *pp,uint n)
{
int i;
for(i=0;i<n;i++)
write_data(pp[i]);
}
#endif
(三)头文件2 时钟模块 DS1302.H
#ifndef _REAL_TIMER_DS1302_2009_5_20_
#define _REAL_TIMER_DS1302_2003_5_20_
sbit DS1302_CLK = P2^6; //实时时钟时钟线引脚
sbit DS1302_IO = P2^7; //实时时钟数据线引脚
sbit DS1302_RST = P2^5; //实时时钟复位线引脚
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
typedef struct SYSTEM_TIME
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char DateString[9]; //用这两个字符串来放置读取的时间
unsigned char TimeString[9];
}SYSTEMTIME; //定义的时间类型
#define AM(X) X
#define PM(X) (X+12) // 转成24小时制
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8C
#define DS1302_RAM(X) (0xC0+(X)*2) //用于计算 DS1302_RAM 地址的宏
/******内部指令**********/
void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数)
{
unsigned char i;
ACC = d;
for(i=8; i>0; i--)
{
DS1302_IO = ACC0;
DS1302_CLK = 1;
DS1302_CLK = 0;
ACC = ACC >> 1; //因为在前面已经定义了ACC0 = ACC^0;以便再次利用DS1302_IO = ACC0;
}
}
unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数)
{
unsigned char i;
for(i=8; i>0; i--)
{
ACC = ACC >>1;
ACC7 = DS1302_IO;
DS1302_CLK = 1;
DS1302_CLK = 0;
}
return(ACC);
}
/********************************/
void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据
{
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr); // 地址,命令
DS1302InputByte(ucDa); // 写1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
}
unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据
{
unsigned char ucData;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr|0x01); // 地址,命令
ucData = DS1302OutputByte(); // 读1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
return(ucData);
}
void DS1302_SetProtect(bit flag) //是否写保护
{
if(flag)
Write1302(0x8E,0x10);
else
Write1302(0x8E,0x00);
}
void DS1302_SetTime(unsigned char Address, unsigned char Value) // 设置时间函数
{
DS1302_SetProtect(0);
Write1302(Address, ((Value/10)<<4 | (Value%10))); //将十进制数转换为BCD码
} //在DS1302中的与日历、时钟相关的寄存器存放的数据必须为BCD码形式
void DS1302_GetTime(SYSTEMTIME *Time)
{
unsigned char ReadValue;
ReadValue = Read1302(DS1302_SECOND);
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将BCD码转换为十进制数
ReadValue = Read1302(DS1302_MINUTE);
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_HOUR);
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_DAY);
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_WEEK);
Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MONTH);
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_YEAR);
Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
}
unsigned char *DataToBCD(SYSTEMTIME *Time)
{
unsigned char D[8];
D[0]=Time->Second/10<<4+Time->Second%10;
D[1]=Time->Minute/10<<4+Time->Minute%10;
D[2]=Time->Hour/10<<4+Time->Hour%10;
D[3]=Time->Day/10<<4+Time->Day%10;
D[4]=Time->Month/10<<4+Time->Month%10;
D[5]=Time->Week/10<<4+Time->Week%10;
D[6]=Time->Year/10<<4+Time->Year%10;
return D;
}
void DateToStr(SYSTEMTIME *Time)
{
//将十进制数转换为液晶显示的ASCII值
Time->DateString[0] = Time->Year/10 + '0';
Time->DateString[1] = Time->Year%10 + '0';
Time->DateString[2] = '-';
Time->DateString[3] = Time->Month/10 + '0';
Time->DateString[4] = Time->Month%10 + '0';
Time->DateString[5] = '-';
Time->DateString[6] = Time->Day/10 + '0';
Time->DateString[7] = Time->Day%10 + '0';
Time->DateString[8] = '\0';
}
void TimeToStr(SYSTEMTIME *Time)
{
//将十进制数转换为液晶显示的ASCII值
Time->TimeString[0] = Time->Hour/10 + '0';
Time->TimeString[1] = Time->Hour%10 + '0';
Time->TimeString[2] = ':';
Time->TimeString[3] = Time->Minute/10 + '0';
Time->TimeString[4] = Time->Minute%10 + '0';
Time->TimeString[5] = ':';
Time->TimeString[6] = Time->Second/10 + '0';
Time->TimeString[7] = Time->Second%10 + '0';
Time->DateString[8] = '\0';
}
void Initial_DS1302(void)
{
unsigned char Second;
Second=Read1302(DS1302_SECOND);
if(Second&0x80) //初始化时间
DS1302_SetTime(DS1302_SECOND,0);
}
void DS1302_TimeStop(bit flag) // 是否将时钟停止
{
unsigned char Data;
Data=Read1302(DS1302_SECOND);
DS1302_SetProtect(0);
if(flag)
Write1302(DS1302_SECOND, Data|0x80);
else
Write1302(DS1302_SECOND, Data&0x7F);
}
#endif
3. c璇瑷51鍗旷墖链烘棩铡嗘樉绀猴纸鎴愬姛阃100鍒嗭级
浣犲厛锅氢竴涓鏁村舰鏁扮粍瀛樻斁杩欎簺杩愮畻缁撴灉锛岀劧钖庡啀鍐欎竴涓瀛楃︿覆鍜屾暣褰㈣浆鎹㈢殑绋嫔簭锛屾妸杩欎釜鏁扮粍杞鎹㈡垚涓涓瀛楃︿覆灏卞ソ浜嗐傝繖镙蜂綘灏卞彲浠ユ椂闂存疮鏀瑰彉涓娆′慨鏀逛竴涓鏁村舰鏁扮粍锛岀劧钖庤皟鐢ㄤ竴娆¤浆鎹銆 浣犲簲璇ユ槸璁╂樉绀哄湪LCD涓婇溃钖э纴濡傛灉缂栫▼链夐梾棰樼殑璇濓纴鏅氢笂锲炲幓鎴戝彲浠ュ府浣犲啓涓镣广
4. 我用单片机c程序写的一个日历,求高手帮我补充下主函数部分的年月日闰年平年的判断条件
year++;
if(((year%100)==0)&&((year%400)==0))||(((year%100)!=0)&&((year%4)==0))
{
February=29;//2月有29天
}
else
{
February=28;//2月有28天
}
注:符合磨做氏下面两种情况中的一种就是润年:1.能被100整除而且能被400整除瞎散胡灶
2.不能被100整除但是能被4整除
5. 电子日历单片机制作
实现日历的显示、闹钟设置、日期和时间的设置功能
6. 51单片机 制作 日历时钟 用汇编语言 要详细的代码和硬件图示
你好这是基于DS1302日历时钟的单片机汇编程序 51单片机
ORG 0000H
MOV SP,#30H
LOAD EQU P2.0
CLR LOAD
MOV R0,#0FH
MOV R1,#0AH ;亮度
ACALL TRT
MOV R0,#02H
MOV R1,#0BH ;扫描位数
ACALL TRT
MOV R0,#0FFH
MOV R1,#09H ;译码
ACALL TRT
MOV R0,#01H
MOV R1,#0CH
CALL TRT
SETB P1.0
MOV 22H,#00H
;以下为按键扫描输入初值子程序
KEYSET: MOV 73H,#01H ;设温度初值为10度
MOV 74H,#00H
MOV 75H,#00H
CALL DISPLAY
KEY1: CALL KS1 ;调判断有无键按下子程序
JNZ LK1 ;有键按下(A)<>0转消抖延时
AJMP KEY1 ;无键按下返回,等键按下
LK1: CALL DEL10MS ;延时
CALL KS1 ;若有键按下则为真实按下
JNZ KEYI ;键按下(A)<>0转键扫描
AJMP KEY1 ;不是键按下返回
KEYI: JNB ACC.0,KEYR ;加1键未按下,转查减1键
LK2: CALL KS1 ;等待键释放
CALL DEL10MS
JNZ LK2 ;未释放,等待
INC 75H ;末位加1
MOV A,75H
CJNE A,#0AH,PPA
MOV 75H,#00H
INC 74H
MOV A,74H
CJNE A,#0AH,PPA
MOV 74H,#00H
INC 73H
PPA: CALL DISPLAY
AJMP KEY1 ;转再次扫描
KEYR: JNB ACC.1,KEYH ;减1键未按下,转查上限确认键
LK3: CALL KS1
CALL DEL10MS
JNZ LK3
MOV A,75H
CJNE A,#00H,PPC
MOV 75H,#09H
MOV A,74H
CJNE A,#00H,PPD
MOV 74H,#09H
DEC 73H
AJMP PPB
PPD: DEC 74H
AJMP PPB
PPC: DEC 75H
PPB: CALL DISPLAY
AJMP KEY1 ;再次扫描
KEYH: JNB ACC.2,KEYL ;上限键未按下,转查下限确认键
LK4: CALL KS1
CALL DEL10MS
JNZ LK4
MOV A,73H
MOV 70H,A ;保存上限
MOV A,74H
MOV 71H,A
MOV A,75H
MOV 72H,A
AJMP KEY1
;KEYL: JNB ACC.3,KEY1
LK5: CALL KS1
CALL DEL10MS
JNZ LK5
MOV A,73H
MOV 6DH,A ;保存下限
MOV A,74H
MOV 6EH,A
MOV A,75H
MOV 6FH,A
EX_CON: ;CPL P1.3 ;使用仪器测试时用
CALL DS18B20 ;转DS18B20采样子程序
CALL DISPLAY
;以下为后向通道控制部分
CONTROL:MOV A,73H
CJNE A,6DH,NEQA
MOV A,74H
CJNE A,6EH,NEQB
CLR P1.5
CLR P1.6
JMP EX_CON ;样温=下限,返回采样
NEQA: JNC NEQD ;CY=0,即(73H)>(6DH)时转比上限
SETB P1.5
CLR P1.6
JMP EX_CON
NEQB: JNC NEQD
SETB P1.5
CLR P1.6
JMP EX_CON
NEQD: MOV A,73H
CJNE A,70H,NEQE
MOV A,74H
CJNE A,71H,NEQF
CLR P1.5
CLR P1.6
JMP EX_CON ;样温=上限,返回采样
NEQE: JNC NEQH ;CY=0,即(73H)>(70H)时转打开降温开关
CLR P1.5
CLR P1.6
JMP EX_CON
NEQF: JNC NEQH
CLR P1.5
CLR P1.6
JMP EX_CON
NEQH: CLR P1.5
SETB P1.6
JMP EX_CON
KS1: MOV P0,#0FFH
MOV A,P0
CPL A
ANL A,#0FH
RET
DEL10MS:MOV R7,#20
S2: MOV R6,#250
S1: DJNZ R6,S1
DJNZ R7,S2
RET
;以下为显示
DISPLAY:MOV A,73H ;字码
MOV R0,A
MOV R1,#01H ;位置
ACALL TRT
MOV A,74H
MOV R0, A
MOV R1,#02H
ACALL TRT
MOV A,75H
MOV R0,A
MOV R1,#03H
ACALL TRT
RET
;JMP DIS
DS18B20:LCALL RESET ;测试温度探头存在否?
MOV A,#0CCH
LCALL WRITE
MOV A,#44H
LCALL WRITE ;命令字写入探头内
MOV R7,#70D ;延时
CALL DE11
LCALL RESET
MOV A,#0CCH
LCALL WRITE
MOV A,#0BEH
LCALL WRITE
LCALL READ ;读取探头内的温度值
MOV B,A
MOV 21H,A ;保存温度值低位
LCALL READ
MOV 20H,A ;保存温度值高位
LCALL EXCHANG ;温度值B转D并送入显示缓存
RET
RESET:
LA: SETB P1.0 ;复位
NOP
LB: CLR P1.0 ;480US < TS < 960US
MOV R7,#36D
CALL DE11
SETB P1.0 ;60US < T <90US
LC: MOV R7,#6D
CALL DE11
CLR C
ORL C,P1.0
JC LB
LF: MOV R7,#18D ;T > 270
CALL DE11
SETB P1.0
RET
WRITE:
MOV R3,#8
WR1: SETB P1.0
CLR P1.0 ;延时
MOV R4,#2
WR2: DJNZ R4,WR2
RRC A
MOV P1.0,C ;写的数据在线上需延时
MOV R4,#18
WR3: DJNZ R4,WR3
NOP
SETB P1.0
DJNZ R3,WR1
SETB P1.0
RET
READ:
MOV R3,#8
RD1: CLR C
SETB P1.0 ;适当延时
NOP
NOP
CLR P1.0 ;适当延时
NOP
NOP
SETB P1.0 ;延时
MOV R4,#9
RD2: DJNZ R4,RD2
MOV C,P1.0
RRC A
MOV R5,#23
RD3: DJNZ R5,RD3
DJNZ R3,RD1
RET
DELAY: MOV R7,#10
DL2: MOV R6,#200
DL1: MOV R5,#250
DL0: DJNZ R5,DL0
DJNZ R6,DL1
DJNZ R7,DL2
RET
EXCHANG: MOV A,21H
SWAP A
ANL A,#0FH
MOV 24H,A
MOV A,20H
ANL A,#07H
SWAP A
ADD A,24H
MOV B,#10D
DIV AB
MOV 73H,A
MOV 74H,B
MOV A,21H
ANL A,#0FH
mov dptr,#SADDR ;小数部分的转换查表
movc a,@a+dptr
MOV 75H,A
ret
SADDR: DB 00H,1H,02h ; bo_ying address in eeprom 0800h-0A08H
DB 03H,3H,04h ; da_ling address in eeprom 0A10H-0AD3H
DB 04H,05H,06h ;shou_ying address in eeprom 0AE0H-0C25H
DB 06H,7H,08h ; lu_ying address in eeprom 0C30H-0D75H
DB 08H,9H,9h,9H
DELAY15US: ;12MHZ ,15US
DE11: NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ R7,DE11
RET
TRT: CLR P2.0 ;LOAD
MOV R2,#08H
MOV A,R1
T_1: CLR P2.2 ;SETB P2.2 ;CLK
RLC A
MOV P2.1,C ;DATA
CALL TDELAY
SETB P2.2 ;CLR P2.2
DJNZ R2,T_1
CALL TDELAY
MOV R2, #08H
MOV A,R0
TT2: CLR P2.2 ;SETB P2.2
RLC A
MOV P2.1,C
CALL TDELAY
SETB P2.2 ;CLR P2.2
DJNZ R2,TT2
SETB P2.0 ;CLR P2.0
RET
TDELAY: MOV R6,#01H
TMS0: MOV R7,#03H
TMS1: DJNZ R7,TMS1
DJNZ R6,TMS0
RET
7. 基于51系列的单片机和DS1302时钟芯片以及液晶显示的lcd1602电子万年历毕业设计,万分感谢。
#include<reg51.h>
#include"DS18B20_3.H"
#define uint unsigned int
#define uchar unsigned char
uchar a,miao,shi,fen,ri,yue,nian,week,flag,key1n,temp;
//flag用于读取头文件中的温度值,和显示温度值
#define yh 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)
#define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)
//液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口)
sbit rs=P1^0;
sbit en=P1^2;
sbit rw=P1^1; //如果硬件上rw接地,就不用写这句和后面的rw=0了
sbit led=P3^7; //LCD背光开关
//DS1302时钟芯片与C51之间的引脚连接定义
sbit IO=P2^2;
sbit SCLK=P2^1;
sbit RST=P2^2;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
/************************************************************
ACC累加器=A
ACC.0=E0H
ACC.0就是ACC的第0位。Acc可以位寻址。
累加器ACC是一个8位的存储单元,是用来放数据的。但是,这个存储单元有其特殊的地位,
是单片机中一个非常关键的单元,很多运算都要通过ACC来进行。以后在学习指令时,
常用A来表示累加器。但有一些地方例外,比如在PUSH指令中,就必须用ACC这样的名字。
一般的说法,A代表了累加器中的内容、而ACC代表的是累加器的地址。
***************************************************************/
//校时按键与C51的引脚连接定义
sbit key1=P2^4; //设置键
sbit key2=P2^5; //加键
sbit key3=P2^6; //减键
sbit buzzer=P2^0;//蜂鸣器,通过三极管9012驱动,端口低电平响
/**************************************************************/
uchar code tab1[]={"20 - - "}; //年显示的固定字符
uchar code tab2[]={" : : "};//时间显示的固定字符
//延时函数,后面经常调用
void delay(uint xms)//延时函数,有参函数
{
uint x,y;
for(x=xms;x>0;x--)
for(y=120;y>0;y--);
}
/********液晶写入指令函数与写入数据函数,以后可调用**************/
/*在这个程序中,液晶写入有关函数会在DS1302的函数中调用,所以液晶程序要放在前面*/
write_1602com(uchar com)//****液晶写入指令函数****
{
rs=0;//数据/指令选择置为指令
rw=0; //读写选择置为写
P0=com;//送入数据
delay(1);
en=1;//拉高使能端,为制造有效的下降沿做准备
delay(1);
en=0;//en由高变低,产生下降沿,液晶执行命令
}
write_1602dat(uchar dat)//***液晶写入数据函数****
{
rs=1;//数据/指令选择置为数据
rw=0; //读写选择置为写
P0=dat;//送入数据
delay(1);
en=1; //en置高电平,为制造下降沿做准备
delay(1);
en=0; //en由高变低,产生下降沿,液晶执行命令
}
lcd_init()//***液晶初始化函数****
{
write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据
write_1602com(0x0c);//开显示不显示光标
write_1602com(0x06);//整屏不移动,光标自动右移
write_1602com(0x01);//清显示
write_1602com(yh+1);//日历显示固定符号从第一行第1个位置之后开始显示
for(a=0;a<14;a++)
{
write_1602dat(tab1[a]);//向液晶屏写日历显示的固定符号部分
//delay(3);
}
write_1602com(er+2);//时间显示固定符号写入位置,从第2个位置后开始显示
for(a=0;a<8;a++)
{
write_1602dat(tab2[a]);//写显示时间固定符号,两个冒号
//delay(3);
}
}
/*********************over***********************/
/***************DS1302有关子函数********************/
void write_byte(uchar dat)//写一个字节
{
ACC=dat;
RST=1;
for(a=8;a>0;a--)
{
IO=ACC0;
SCLK=0;
SCLK=1;
ACC=ACC>>1;
}
}
uchar read_byte()//读一个字节
{
RST=1;
for(a=8;a>0;a--)
{
ACC7=IO;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
return (ACC);
}
//----------------------------------------
void write_1302(uchar add,uchar dat)//向1302芯片写函数,指定写入地址,数据
{
RST=0;
SCLK=0;
RST=1;
write_byte(add);
write_byte(dat);
SCLK=1;
RST=0;
}
uchar read_1302(uchar add)//从1302读数据函数,指定读取数据来源地址
{
uchar temp;
RST=0;
SCLK=0;
RST=1;
write_byte(add);
temp=read_byte();
SCLK=1;
RST=0;
return(temp);
}
uchar BCD_Decimal(uchar bcd)//BCD码转十进制函数,输入BCD,返回十进制
{
uchar Decimal;
Decimal=bcd>>4;
return(Decimal=Decimal*10+(bcd&=0x0F));
}
//--------------------------------------
void ds1302_init() //1302芯片初始化子函数(2010-01-07,12:00:00,week4)
{
RST=0;
SCLK=0;
write_1302(0x8e,0x00); //允许写,禁止写保护
write_1302(0x80,0x00); //向DS1302内写秒寄存器80H写入初始秒数据00
write_1302(0x82,0x00);//向DS1302内写分寄存器82H写入初始分数据00
write_1302(0x84,0x12);//向DS1302内写小时寄存器84H写入初始小时数据12
write_1302(0x8a,0x04);//向DS1302内写周寄存器8aH写入初始周数据4
write_1302(0x86,0x07);//向DS1302内写日期寄存器86H写入初始日期数据07
write_1302(0x88,0x01);//向DS1302内写月份寄存器88H写入初始月份数据01
write_1302(0x8c,0x10);//向DS1302内写年份寄存器8cH写入初始年份数据10
write_1302(0x8e,0x80); //打开写保护
}
//------------------------------------
//温度显示子函数
void write_temp(uchar add,uchar dat)//向LCD写温度数据,并指定显示位置
{
uchar gw,sw;
gw=dat%10;//取得个位数字
sw=dat/10;//取得十位数字
write_1602com(er+add);//er是头文件规定的值0x80+0x40
write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码
write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码
write_1602dat(0xdf);//显示温度的小圆圈符号,0xdf是液晶屏字符库的该符号地址码
write_1602dat(0x43); //显示"C"符号,0x43是液晶屏字符库里大写C的地址码
}
//------------------------------------
//时分秒显示子函数
void write_sfm(uchar add,uchar dat)//向LCD写时分秒,有显示位置加、现示数据,两个参数
{
uchar gw,sw;
gw=dat%10;//取得个位数字
sw=dat/10;//取得十位数字
write_1602com(er+add);//er是头文件规定的值0x80+0x40
write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码
write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码
}
//-------------------------------------
//年月日显示子函数
void write_nyr(uchar add,uchar dat)//向LCD写年月日,有显示位置加数、显示数据,两个参数
{
uchar gw,sw;
gw=dat%10;//取得个位数字
sw=dat/10;//取得十位数字
write_1602com(yh+add);//设定显示位置为第一个位置+add
write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码
write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码
}
//-------------------------------------------
void write_week(uchar week)//写星期函数
{
write_1602com(yh+0x0c);//星期字符的显示位置
switch(week)
{
case 1:write_1602dat('M');//星期数为1时,显示
write_1602dat('O');
write_1602dat('N');
break;
case 2:write_1602dat('T');//星期数据为2时显示
write_1602dat('U');
write_1602dat('E');
break;
case 3:write_1602dat('W');//星期数据为3时显示
write_1602dat('E');
write_1602dat('D');
break;
case 4:write_1602dat('T');//星期数据为4是显示
write_1602dat('H');
write_1602dat('U');
break;
case 5:write_1602dat('F');//星期数据为5时显示
write_1602dat('R');
write_1602dat('I');
break;
case 6:write_1602dat('S');//星期数据为6时显示
write_1602dat('T');
write_1602dat('A');
break;
case 7:write_1602dat('S');//星期数据为7时显示
write_1602dat('U');
write_1602dat('N');
break;
}
}
//****************键盘扫描有关函数**********************
void keyscan()
{
if(key1==0)//---------------key1为功能键(设置键)--------------------
{
delay(9);//延时,用于消抖动
if(key1==0)//延时后再次确认按键按下
{
buzzer=0;//蜂鸣器短响一次
delay(20);
buzzer=1;
while(!key1);
key1n++;
if(key1n==9)
key1n=1;//设置按键共有秒、分、时、星期、日、月、年、返回,8个功能循环
switch(key1n)
{
case 1: TR0=0;//关闭定时器
//TR1=0;
write_1602com(er+0x09);//设置按键按动一次,秒位置显示光标
write_1602com(0x0f);//设置光标为闪烁
temp=(miao)/10*16+(miao)%10;//秒数据写入DS1302
write_1302(0x8e,0x00);
write_1302(0x80,0x80|temp);//miao
write_1302(0x8e,0x80);
break;
case 2: write_1602com(er+6);//按2次fen位置显示光标
//write_1602com(0x0f);
break;
case 3: write_1602com(er+3);//按动3次,shi
//write_1602com(0x0f);
break;
case 4: write_1602com(yh+0x0e);//按动4次,week
//write_1602com(0x0f);
break;
case 5: write_1602com(yh+0x0a);//按动5次,ri
//write_1602com(0x0f);
break;
case 6: write_1602com(yh+0x07);//按动6次,yue
//write_1602com(0x0f);
break;
case 7: write_1602com(yh+0x04);//按动7次,nian
//write_1602com(0x0f);
break;
case 8:
write_1602com(0x0c);//按动到第8次,设置光标不闪烁
TR0=1;//打开定时器
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,0x00|temp);//miao数据写入DS1302
write_1302(0x8e,0x80);
break;
}
}
}
//------------------------------加键key2----------------------------
if(key1n!=0)//当key1按下以下。再按以下键才有效(按键次数不等于零)
{
if(key2==0) //上调键
{
delay(10);
if(key2==0)
{
buzzer=0;//蜂鸣器短响一次
delay(20);
buzzer=1;
while(!key2);
switch(key1n)
{
case 1:miao++;//设置键按动1次,调秒
if(miao==60)
miao=0;//秒超过59,再加1,就归零
write_sfm(0x08,miao);//令LCD在正确位置显示"加"设定好的秒数
temp=(miao)/10*16+(miao)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00); //允许写,禁止写保护
write_1302(0x80,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码
write_1302(0x8e,0x80); //打开写保护
write_1602com(er+0x09);//因为设置液晶的模式是写入数据后,光标自动右移,所以要指定返回
//write_1602com(0x0b);
break;
case 2:fen++;
if(fen==60)
fen=0;
write_sfm(0x05,fen);//令LCD在正确位置显示"加"设定好的分数据
temp=(fen)/10*16+(fen)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x82,temp);//向DS1302内写分寄存器82H写入调整后的分数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(er+6);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
break;
case 3:shi++;
if(shi==24)
shi=0;
write_sfm(2,shi);//令LCD在正确的位置显示"加"设定好的小时数据
temp=(shi)/10*16+(shi)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x84,temp);//向DS1302内写小时寄存器84H写入调整后的小时数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(er+3);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
case 4:week++;
if(week==8)
week=1;
write_1602com(yh+0x0C);//指定'加'后的周数据显示位置
write_week(week);//指定周数据显示内容
temp=(week)/10*16+(week)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x8a,temp);//向DS1302内写周寄存器8aH写入调整后的周数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(yh+0x0e);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
case 5:ri++;
if(ri==32)
ri=1;
write_nyr(9,ri);//令LCD在正确的位置显示"加"设定好的日期数据
temp=(ri)/10*16+(ri)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x86,temp);//向DS1302内写日期寄存器86H写入调整后的日期数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(yh+10);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
case 6:yue++;
if(yue==13)
yue=1;
write_nyr(6,yue);//令LCD在正确的位置显示"加"设定好的月份数据
temp=(yue)/10*16+(yue)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x88,temp);//向DS1302内写月份寄存器88H写入调整后的月份数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(yh+7);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
case 7:nian++;
if(nian==100)
nian=0;
write_nyr(3,nian);//令LCD在正确的位置显示"加"设定好的年份数据
temp=(nian)/10*16+(nian)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x8c,temp);//向DS1302内写年份寄存器8cH写入调整后的年份数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(yh+4);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
}
}
}
//------------------减键key3,各句功能参照'加键'注释---------------
if(key3==0)
{
delay(10);//调延时,消抖动
if(key3==0)
{
buzzer=0;//蜂鸣器短响一次
delay(20);
buzzer=1;
while(!key3);
switch(key1n)
{
case 1:miao--;
if(miao==-1)
miao=59;//秒数据减到-1时自动变成59
write_sfm(0x08,miao);//在LCD的正确位置显示改变后新的秒数
temp=(miao)/10*16+(miao)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00); //允许写,禁止写保护
write_1302(0x80,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码
write_1302(0x8e,0x80); //打开写保护
write_1602com(er+0x09);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
//write_1602com(0x0b);
break;
case 2:fen--;
if(fen==-1)
fen=59;
write_sfm(5,fen);
temp=(fen)/10*16+(fen)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x82,temp);//向DS1302内写分寄存器82H写入调整后的分数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(er+6);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
break;
case 3:shi--;
if(shi==-1)
shi=23;
write_sfm(2,shi);
temp=(shi)/10*16+(shi)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x84,temp);//向DS1302内写小时寄存器84H写入调整后的小时数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(er+3);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
case 4:week--;
if(week==0)
week=7;
write_1602com(yh+0x0C);//指定'加'后的周数据显示位置
write_week(week);//指定周数据显示内容
temp=(week)/10*16+(week)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x8a,temp);//向DS1302内写周寄存器8aH写入调整后的周数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(yh+0x0e);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
case 5:ri--;
if(ri==0)
ri=31;
write_nyr(9,ri);
temp=(ri)/10*16+(ri)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x86,temp);//向DS1302内写日期寄存器86H写入调整后的日期数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(yh+10);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
case 6:yue--;
if(yue==0)
yue=12;
write_nyr(6,yue);
temp=(yue)/10*16+(yue)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x88,temp);//向DS1302内写月份寄存器88H写入调整后的月份数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(yh+7);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
case 7:nian--;
if(nian==-1)
nian=99;
write_nyr(3,nian);
temp=(nian)/10*16+(nian)%10;//十进制转换成DS1302要求的DCB码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x8c,temp);//向DS1302内写年份寄存器8cH写入调整后的年份数据BCD码
write_1302(0x8e,0x80);//打开写保护
write_1602com(yh+4);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
}
}
}
}
}
//-------------------------------
void init() //定时器、计数器设置函数
{
TMOD=0x11; //指定定时/计数器的工作方式为3
TH0=0; //定时器T0的高四位=0
TL0=0; //定时器T0的低四位=0
EA=1; //系统允许有开放的中断
ET0=1; //允许T0中断
TR0=1; //开启中断,启动定时器
}
//*******************主函数**************************
//***************************************************
void main()
{
lcd_init(); //调用液晶屏初始化子函数
ds1302_init(); //调用DS1302时钟的初始化子函数
init(); //调用定时计数器的设置子函数
led=0; //打开LCD的背光电源
buzzer=0;//蜂鸣器长响一次
delay(80);
buzzer=1;
while(1) //无限循环下面的语句:
{
keyscan(); //调用键盘扫描子函数
}
}
void timer0() interrupt 1 //取得并显示日历和时间
{
//Init_DS18B20();//温度传感器DS18b2初始化子函数,在头文件中
flag=ReadTemperature();//将18b2头文件运行返回的函数结果送到变量FLAG中,用于显示
//读取秒时分周日月年七个数据(DS1302的读寄存器与写寄存器不一样):
miao = BCD_Decimal(read_1302(0x81));
fen = BCD_Decimal(read_1302(0x83));
shi = BCD_Decimal(read_1302(0x85));
ri = BCD_Decimal(read_1302(0x87));
yue = BCD_Decimal(read_1302(0x89));
nian=BCD_Decimal(read_1302(0x8d));
week=BCD_Decimal(read_1302(0x8b));
//显示温度、秒、时、分数据:
write_temp(12,flag);//显示温度,从第二行第12个字符后开始显示
write_sfm(8,miao);//秒,从第二行第8个字后开始显示(调用时分秒显示子函数)
write_sfm(5,fen);//分,从第二行第5个字符后开始显示
write_sfm(2,shi);//小时,从第二行第2个字符后开始显示
//显示日、月、年数据:
write_nyr(9,ri);//日期,从第二行第9个字符后开始显示
write_nyr(6,yue);//月份,从第二行第6个字符后开始显示
write_nyr(3,nian);//年,从第二行第3个字符后开始显示
write_week(week);
}