基于DS1302与AT89C51的实时日历时钟的LCD显示程序你还有么还有图的

基于DS1302与AT89C51的实时日历时钟的LCD显示程序你还有么还有图的,第1张

236 显示模块的设计

本设计中由于要对时间、温度进行显示,所以选择液晶显示屏1602模块作为输出。1602字符型LCD通常有14条引脚线或16条引脚线的LCD,多出来的2条线是背光电源线。它可以显示两行,每行16个字符,采用单+5V电源供电,外围电路配置简单,价格便宜,具有很高的性价比。1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。管脚功能如表2-1所示。

表2-1 LCD1602引脚功能

引脚 符号 功能说明

1 VSS 一般接地

2 VDD 接电源(+5V)

3 V0 液晶显示器对比度调整端。

4 RS RS为寄存器选择。

5 R/W R/W为读写信号线。

6 E E(或EN)端为使能(enable)端,下降沿使能。

7 DB0 低4位三态、 双向数据总线 0位(最低位)

8 DB1 低4位三态、 双向数据总线 1位

9 DB2 低4位三态、 双向数据总线 2位

10 DB3 低4位三态、 双向数据总线 3位

11 DB4 高4位三态、 双向数据总线 4位

12 DB5 高4位三态、 双向数据总线 5位

13 DB6 高4位三态、 双向数据总线 6位

14 DB7 高4位三态、 双向数据总线 7位(最高位)

LCD1602主要管脚介绍:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生鬼影使用时可以通过一个10K的电位器调整对比度。RS为寄存器选择端,高电平时选择数据寄存器,低电平时选择指令寄存器。R/W为读写信号线端,高电平时进行读 *** 作,低电平时进行写 *** 作。当RS和R/W共同为低电平时可以写入指令或者显示地址;当RS为高电平R/W 为低电平时可以写入数据。E为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。

将LCD1602的RS端和P20,R/W端和P21, E 端和P22相连,当RS=0时,对LCD1602写入指令;当RS=1时,对LCD1602写入数据。当R/W端接高电平时芯片处于读数据状态,反之处于写数据状态,E端为使能信号端。当R/W为高电平,E端也为高电平,RS为低电平时,液晶显示屏显示需要显示的示数。图211为1602液晶显示屏与单片机的硬件连接图。

图211 LCD液晶显示与单片机硬件连线图

附录二 部分程序说明

void delay(uint xms) //延时函数,有参函数//

{ uint x,y;

for(x=xms;x>0;x--)

for(y=110;y>0;y--);

}

//ds18b20芯片有关子程序/

void DS18B20_init() //初始化

{ uint i; tem_ds=0;

i=160; while(i>0) //给DS18B20单总线至少480uS的低电平信号

i--; tem_ds=1; //拉高15~60uS

i=8; while(i>0) i--;

}

void temwritebit(bit instruc_data) //写一位//

{ int time;

if(instruc_data)

{ tem_ds=0;

time=3; //延时14us

while(time>0)

time--;

tem_ds=1; //写"1"

time=8; //延时35us

while(time>0)

time--;

}

else

{

tem_ds=0; //写0

time=14; //延时62us

while(time>0)

time--;

}

tem_ds=1; //释放数据线

time++;time++;

}

bit temreadbit() //读一位//

{ uint i;

bit datbit;

tem_ds=0;

i++;

tem_ds=1;

i++;i++;

datbit=tem_ds; //读数据

i=10; //延时45 

while(i>0)

i--;

tem_ds=1;

return(datbit);

}

uchar temreadbyte() //读字节//

{ uchar i,j,dat;

dat=0;

for(i=0;i<8;i++)

{ j=temreadbit() ;

dat=(j<<7)|(dat>>1);

}

return(dat);

}

void temwritebyte(uchar instru) //写字节//

{ int i;

for(i=0;i<8;i++)

{temwritebit(instru&01);

instru>>=1;

}

}

uint get_tem() //获取温度//

{ uchar tem_L,tem_H;

DS18B20_init();

delay(1);

temwritebyte(0xcc); //写跳过ROM指令;

temwritebyte(0xbe); //读数据

tem_L=temreadbyte();

tem_H=temreadbyte();

tem=tem_H<<8|tem_L;

f_tem=tem00625;

tem=f_tem ;

return (tem);

}

//液晶相关程序/

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); //设置液晶工作模式 意思:162行显示,57点阵,8位数据

write_1602com(0x01); //清显示

write_1602com(0x06); //整屏不移动,光标自动右移

write_1602com(yh+1); //日历显示固定符号从第一行第1个位置之后开始显示

write_1602com(0x0c); //开显示不显示光标

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);

}

}

/DS1302有关子函数/

void write_byte(uchar dat) //写一个字节//

{ ACC=dat;

RST=1;

for(a=8;a>0;a--)

{ IO=ACC0;

SCLK=0; /在控制指令字输入后的下一个SCLK时钟的上升沿时/

SCLK=1; /数据被写入DS1302/

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码转十进制函数//

{ uchar Decimal;

Decimal=bcd>>4; //BCD高四位表示十位,低四位个位,8421码;

return(Decimal=Decimal10+(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//年月日显示将er改为yh即可,其他相同;

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; //下面六种选择形式相同将括号中的字符相应修改就行了

}

}

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; //关闭定时器

write_1602com(er+0x09); //设置按键按动一次,秒位置显示光标

write_1602com(0x0f); //设置光标为闪烁

temp=(miao)/1016+(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); //下面case3~case7基本相同,改变地址就行了

case 8: write_1602com(0x0c); //按动到第8次,设置光标不闪烁

TR0=1;//打开定时器

temp=(miao)/1016+(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;

write_sfm(0x08,miao);

temp=(miao)/1016+(miao)%10; //十进制转换成DS1302要求的BCD码

write_1302(0x8e,0x00); //允许写,禁止写保护

write_1302(0x80,temp); ;//向DS1302内写秒寄存器80H写入调整后的数据BCD码

write_1302(0x8e,0x80); //打开写保护

write_1602com(er+0x09); //因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位

break;

//下面case2~case7和case1相同将相应的地址改一下就行了。

}

}

}

下面的key3与加键key2形式基本相同;

}

}

void init() //定时器、计数器设置函数

{ TMOD=0x01; //指定定时/计数器的工作方式为1

TH0=0; //定时器T0的高四位=0

TL0=0; //定时器T0的低四位=0

EA=1; //系统允许有开放的中断

ET0=1; //允许T0中断

TR0=1; //开启中断,启动定时器

}

void main() //主函数

{ lcd_init(); //调用液晶屏初始化子函数

ds1302_init(); //调用DS1302时钟的初始化子函数

init(); //调用定时计数器的设置子函数

buzzer=0; //蜂鸣器长响一次

delay(80);

buzzer=1;

while(1) //无限循环下面的语句:

{keyscan();} //调用键盘扫描子函数

}

Void timer0() interrupt 1 //取得并显示日历和时间

{ TH0=0; //重复初始值

TL0=0;

DS18B20_init();

delay(1);

temwritebyte(0xcc); //写跳过ROM指令;

temwritebyte(0x44); //启动温度转换;

flag=get_tem(); //将18b20运行返回的函数结果送到变量flag中,用于显示

//读取秒时分周日月年七个数据(DS1302的读寄存器与写寄存器不一样):

miao = BCD_Decimal(read_1302(0x81));//下面分秒年月日形式相同,改变地址就可以了

//显示温度、秒、时、分数据:

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);

}

恩,你可以先参考别人的程序。

#include<reg52h>

#define uint unsigned int

#define uchar unsigned char

#define DS1302_SECOND 0x80

#define DS1302_MINUTE 0x82

#define DS1302_HOUR 0x84

sbit ACC0=ACC^0;

sbit ACC7=ACC^7;

sbit beep=P1^0;

sbit clk=P1^3;

sbit io=P1^2;

sbit rst=P1^1;

sbit k1=P1^4;

sbit k2=P1^5;

sbit k3=P1^6;

sbit k4=P1^7;

sbit w1=P2^7;

sbit w2=P2^6;

sbit w3=P2^5;

sbit w4=P2^4;

sbit w5=P2^3;

sbit w6=P2^2;

sbit w7=P2^1;

sbit w8=P2^0;

sbit ds=P3^7; //DS18B20的端口

char shi,fen,miao;

char month,week,date;

int year;

uchar k1num;

uchar fc,count,flag;

uchar fik,jt;

uint temp;

float tt;

uint p;

uchar code sec_7[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x46,0xbf,0xff};

void key();

//void Set_time(unsigned char k1num);

void delay(uint z)

{

uint x,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--);

}

/

DS1820相关

/

void dsinit()

{

uint i;

ds=0;

i=103;

while(i>0)i--;

ds=1;

i=4;

while(i>0)i--;

}

bit readbit()

{

uint i;

bit datas;

ds=0;i++;

ds=1;i++;i++;

datas=ds;

i=8;while(i>0)i--;

return(datas);

}

uchar read()

{

uchar i,j,datas;

datas=0;

for(i=1;i<=8;i++)

{

j=readbit();

datas=(j<<7)|(datas>>1);

}

return(datas);

}

void writbyte(uchar datas)

{

uint i;

uchar j;

bit testb;

for(j=1;j<=8;j++)

{

testb=datas&0x01;

datas=datas>>1;

if(testb)

{

ds=0;

i++;i++;

ds=1;

i=8;while(i>0)i--;

}

else

{

ds=0;

i=8;while(i>0)i--;

ds=1;

i++;i++;

}

}

}

void tempconvert()

{

dsinit();

delay(1);

writbyte(0xcc);

writbyte(0x44);

}

uint readtemp()

{

uchar a,b;

dsinit();

delay(1);

writbyte(0xcc);

writbyte(0xbe);

a=read();

b=read();

temp=b;

temp<<=8;

temp=temp|a;

tt=temp00625;

temp=tt10;

return temp;

}

/

函 数 名:WriteByte()

功 能:实时时钟写入一字节

说 明:往DS1302写入1Byte数据 (内部函数)

入口参数:d 写入的数据

返 回 值:无

/

void WriteByte(uchar d)

{

uchar h;

ACC = d;

for(h=8; h>0; h--)

{

io = ACC0; /相当于汇编中的 RRC /

clk = 1;

clk = 0;

ACC = ACC >> 1;

}

}

/

函 数 名:RTOutputByte()

功 能:实时时钟读取一字节

说 明:从DS1302读取1Byte数据 (内部函数)

入口参数:无

返 回 值:ACC

/

uchar RTOutputByte(void)

{

uchar h;

for(h=8; h>0; h--)

{

ACC = ACC >>1; /相当于汇编中的 RRC /

ACC7 =io;

clk = 1;

clk = 0;

}

return ACC;

}

/

函 数 名:W1302()

功 能:往DS1302写入数据

说 明:先写地址,后写命令/数据 (内部函数)

调 用:RTInputByte() , RTOutputByte()

入口参数:ucAddr: DS1302地址, ucData: 要写的数据

返 回 值:无

/

void W1302(uchar ucAddr, uchar ucDa)

{

rst = 0;

clk = 0;

rst = 1;

WriteByte(ucAddr); // 地址,命令

WriteByte(ucDa); //写1Byte数据

clk = 1;

rst = 0;

}

/

函 数 名:R1302()

功 能:读取DS1302某地址的数据

说 明:先写地址,后读命令/数据 (内部函数)

调 用:RTInputByte() , RTOutputByte()

入口参数:ucAddr: DS1302地址

返 回 值:ucData :读取的数据

/

uchar R1302(uchar ucAddr)

{

uchar ucData;

rst = 0;

clk = 0;

rst = 1;

WriteByte(ucAddr); / 地址,命令 /

ucData = RTOutputByte(); / 读1Byte数据 /

clk = 1;

rst = 0;

return ucData;

}

void Init_Time(void)

{//设置初始时间

// AMPM(0); //0 为24小时制,1为12小时制

W1302(DS1302_SECOND,0x08);

W1302(DS1302_MINUTE,0x08);

W1302(DS1302_HOUR,0x08);

}

/void Init_DS1302(void)

{//DS1302初始化

unsigned char Second=Read1302(DS1302_SECOND);

if(Second&0x80)

DS1302_SetTime(DS1302_SECOND,0);

}

/

/读取DS1302中的时间/

void du1302()

{

// uchar yy;

miao=R1302(0x81); //读取 秒 分 时 日 月 星期 年

fen=R1302(0x83);

shi=R1302(0x85);

/ shi=shi/1610+shi%16;

fen=fen/1610+fen%16;

miao=miao/1610+miao%16;/

date=R1302(0x87);

month=R1302(0x89);

week=R1302(0x8b);

year=R1302(0x8d);

}

void display()

{

uchar ms,mg ,fs,fg,ss,sg;

uchar mons,mong,dats,datg;

uchar wks,wkg,years,yearg;

static uchar hh=0, ff=0;

ms=miao/16;

mg=miao%16;

fs=fen/16;

fg=fen%16;

ss=shi/16;

sg=shi%16;

mons=month/16;

mong=month%16;

dats=date/16;

datg=date%16;

wks=week/16;

wkg=week%16;

years=year/16;

yearg=year%16;

if(k1num==1&&ff==0)

{

years=12;yearg=12;hh++;

}

if(hh>30||ff==1) //闪烁 ,hh值越大 闪烁越慢

{

years=year/16;

yearg=year%16;

hh--;

if(hh==0)

ff=0;

else

ff=1;

}

if(k1num==2&&ff==0)

{

mons=12;mong=12;hh++;

}

if(hh>30||ff==1) //闪烁 hh值越大 闪烁越慢

{

mons=month/16;

mong=month%16;

hh--;

if(hh==0)

ff=0;

else

ff=1;

}

if(k1num==3&&ff==0)

{

dats=12;datg=12;hh++;

}

if(hh>30||ff==1)

{

dats=date/16;

datg=date%16;

hh--;

if(hh==0)

ff=0;

else

ff=1;

}

if(k1num==4&&ff==0)

{

wks=12;wkg=12;hh++;

}

if(hh>30||ff==1) //闪烁 ,hh值越大 闪烁越慢

{

wks=week/16;

wkg=week%16;

hh--;

if(hh==0)

ff=0;

else

ff=1;

}

if(k1num==5&&ff==0)

{

ss=12;sg=12;hh++;

}

if(hh>30||ff==1) //闪烁 hh值越大 闪烁越慢

{

ss=shi/16;

sg=shi%16;

hh--;

if(hh==0)

ff=0;

else

ff=1;

}

if(k1num==6&&ff==0)

{

fs=12;fg=12;hh++;

}

if(hh>30||ff==1) //闪烁 hh值越大 闪烁越慢

{

fs=fen/16;

fg=fen%16;

hh--;

if(hh==0)

ff=0;

else

ff=1;

}

if(k1num==7&&ff==0)

{

ms=12;mg=12;hh++;

}

if(hh>30||ff==1) //闪烁 hh值越大 闪烁越慢

{

ms=miao/16;

mg=miao%16;

hh--;

if(hh==0)

ff=0;

else

ff=1;

}

/显示时分秒/

if((k1num==0||k1num==5||k1num==6||k1num==7)&&(fik==0)&&jt==0)

{

P0=sec_7[mg];

w8=0;

delay(2);

w8=1;

P0=sec_7[ms];

w7=0;

delay(2);

w7=1;

P0=sec_7[fg];

w5=0;

delay(2);

w5=1;

P0=sec_7[fs];

w4=0;

delay(2);

w4=1;

P0=sec_7[sg];

w2=0;

delay(2);

w2=1;

if(ss==0&&sg!=0)ss=12;//消除小时前端的0

P0=sec_7[ss];

w1=0;

delay(2);

w1=1;

P0=sec_7[11];

w6=0;

delay(2);

w6=1;

P0=sec_7[11];

w3=0;

delay(2);

w3=1;

}

/显示日期+星期///

if((fik==1||k1num==2||k1num==3||k1num==4)||jt==2)

{

P0=sec_7[mong];

w2=0;

delay(2);

w2=1;

if(mons==0)mons=12;

P0=sec_7[mons];

w1=0;

delay(2);

w1=1;

P0=sec_7[datg];

w5=0;

delay(2);

w5=1;

if(dats==0)dats=12;

P0=sec_7[dats];

w4=0;

delay(2);

w4=1;

P0=0xf7;

w3=0;

delay(2);

w3=1;

P0=0xf7;

w6=0;

delay(2);

w6=1;

P0=0xf7;

w7=0;

delay(2);

w7=1;

if(wkg==7)(wkg=8);

P0=sec_7[wkg];

w8=0;

delay(2);

w8=1;

P0=0x7f;

w8=0;

delay(2);

w8=1;

}

/显示年 /

if((fik==2||k1num==1)||(jt==1))

{

P0=sec_7[2];

w1=0;

delay(2);

w1=1;

P0=sec_7[0];

w2=0;

delay(2);

w2=1;

P0=sec_7[years];

w3=0;

delay(2);

w3=1;

P0=sec_7[yearg];

w4=0;

delay(2);

w4=1;

P0=sec_7[11];

w5=0;

delay(2);

w5=1;

P0=sec_7[11];

w6=0;

delay(2);

w6=1;

P0=sec_7[11];

w7=0;

delay(2);

w7=1;

P0=sec_7[11];

w8=0;

delay(2);

w8=1;

}

/显示温度/

if(fik==3||jt==3)

{

P0=sec_7[p%10];

w3=0;

delay(2);

w3=1;

P0=sec_7[p%100/10];

w2=0;

delay(2);

w2=1;

P0=0x7f; //显示小数点

w2=0;

delay(2);

w2=1;

P0=sec_7[p/100];

w1=0;

delay(2);

w1=1;

P0=0x46; //显示℃ 的符号

w4=0;

delay(2);

w4=1;

}

}

void key()

{

uchar xx;

if(k1==0) //k1是调整键,按下后调整的位会闪烁。

{

delay(15);

if(k1==0)

{

beep=0;

for(xx=4;xx>0;xx--)

{

display();

}

beep=1;

fik=0; jt=0;

count=0;fc=0;

k1num++;

if(k1num==8)k1num=0;

}

while(!k1)display(); //防止按下按键盘时数码管息灭(2010年元月10号修改)

}

if(k2==0) //按K2是加时间

{

delay(15);

if(k2==0)

{

beep=0;

for(xx=4;xx>0;xx--)

{

display();

}beep=1;

count=0; fc=0; jt=0;

switch(k1num)

{

case 7:

{

miao=0;

W1302(0x8e,0x00);

W1302(0x80,0);

W1302(0x8e,0x80);

}break;

case 6:

{

fen=fen/1610+fen%16;

fen++;

if(fen==60)fen=0;

fen=fen/1016+fen%10;

W1302(0x8e,0x00);

W1302(0x82,fen);

W1302(0x8e,0x80);

}break;

case 5 :

{

shi=shi/1610+shi%16;

shi++;

if(shi==24)shi=0;

shi=shi/1016+shi%10;

W1302(0x8e,0x00);

W1302(0x84,shi);

W1302(0x8e,0x80);

}break;

case 2:

{ month=month/1610+month%16;

month++;

if(month==13)month=1;

month=month/1016+month%10;

W1302(0x8e,0x00);

W1302(0x88,month);

W1302(0x8e,0x80); }

break;

case 3:

{ date=date/1610+date%16;

date++;if(date>31)date=1;

date=date/1016+date%10;

W1302(0x8e,0x00);

W1302(0x86,date);

W1302(0x8e,0x80); }

break;

case 4:

{ week=week/1610+week%16;

week++;if(week==8)week=1;

week=week/1016+week%10;

W1302(0x8e,0x00);

W1302(0x8a,week);

W1302(0x8e,0x80); }

break;

case 1:

{ year=year/1610+year%16;

year++;if(year>99)year=0;

year=year/1016+year%10;

W1302(0x8e,0x00);

W1302(0x8c,year);

W1302(0x8e,0x80); }

break;

/ case 8:

{

shi=shi/1610+shi%16;

if(shi>12)

shi=shi-12;

if(shi==0)shi=12; /12/24小时制转换

shi=shi/1016+shi%10;

} /

case 8:

k1num=0;

break;

default:

break;

}

while(!k2)display();

}

}

if(k3==0) //K3是减 时间

{

delay(15);

if(k3==0)

{

beep=0;

for(xx=4;xx>0;xx--)

{

display();

}beep=1;

count=0; fc=0; jt=0;

if(k1num==5)

{

shi=shi/1610+shi%16;

shi--;if(shi<0)shi=23;

shi=shi/1016+shi%10;

W1302(0x8e,0x00);

W1302(0x84,shi);

W1302(0x8e,0x80);

}

if(k1num==6)

{

fen=fen/1610+fen%16;

fen--;if(fen<0)fen=59;

fen=fen/1016+fen%10;

W1302(0x8e,0x00);

W1302(0x82,fen);

W1302(0x8e,0x80);

}

if(k1num==7)

{

miao=0;

W1302(0x8e,0x00);

W1302(0x80,miao);

W1302(0x8e,0x80);

}

if(k1num==2)

{

month=month/1610+month%16;

month--;if(month==0)month=12;

month=month/1016+month%10;

W1302(0x8e,0x00);

W1302(0x88,month);

W1302(0x8e,0x80);

}

if(k1num==3)

{

date=date/1610+date%16;

date--;if(date==0)date=31;

date=date/1016+date%10;

W1302(0x8e,0x00);

W1302(0x86,date);

W1302(0x8e,0x80);

}

if(k1num==4)

{

week=week/1610+week%16;

week--;if(week==0)week=7;

week=week/1016+week%10;

W1302(0x8e,0x00);

W1302(0x8a,week);

W1302(0x8e,0x80);

}

if(k1num==1)

{

year=year/1610+year%16;

year--;if(year<0)year=99;

year=year/1016+year%10;

W1302(0x8e,0x00);

W1302(0x8c,year);

W1302(0x8e,0x80);

}

}while(!k3)display();

}

}

void main()

{

Init_Time();//设置DS1302初始时间

TMOD=0x01; //16位定时

TH0=0xa6; //25ms晶振为110592M

TL0=0x00;

EA=1;

TR0=1;

ET0=1;

P2=0xff;

beep=0;

delay(300); //开机滴一声

beep=1;

W1302(0x90,0xaa); //打开涓流充电

while(1)

{

if(k4==0)

{ delay(15);

if(k4==0)

{

fik++; if(fik==4)fik=0;

count=0;k1num=0;

fc=0;

beep=0;

delay(100);

beep=1;

}while(!k4)display();

}

tempconvert();//温度转换

display();

key();

du1302(); //获取时间

display();

//Set_time(k1num);

p=readtemp(); //读取温度

miao=miao/1610+miao%16;

// if(miao==30&&k1num==0){jt=1;fik=0;} //交替显示年3S

if(miao==30&&k1num==0){jt=2;fik=0;} //交替显示月日星期5S

if(miao==33&&k1num==0){fik=0;jt=3;} //交替显示温度

if(miao<30||miao>35)jt=0; //正常显示时间 时分秒

miao=miao/1016+miao%10;

display();

}

}

void timer_1(void) interrupt 1 //中断入口,闪烁

{

TH0=0xa6; //25ms定时 晶振24M

TL0=0x00;

if(count++==40) //1000ms

{ count=0;

if(fc++==10) //12秒后进入正常走时。

{k1num=0;fc=0;fik=0;}// flag=0;

}

}

#define LCM_RW P2^4 //定义引脚

#define LCM_RS P2^3

#define LCM_E P2^5

#define LCM_Data P0

#define Busy 0x80 //用于检测LCM状态字中的Busy标识

#include <reg52h>

void WriteDataLCM (unsigned char WDLCM);

void WriteCommandLCM (unsigned char WCLCM,BuysC);

void DisplayOneChar (unsigned char X, unsigned char Y, unsigned char DData);

void DisplayListChar (unsigned char X, unsigned char Y, unsigned char code DData);

unsigned char ReadDataLCM(void);

unsigned char ReadStatusLCM(void);

void pro_timedate(void);

bit leap_year(); //判断是否为闰年

unsigned char data year=11,month=5,date=22;//年、月、日、星期

unsigned char disbuf[16];

unsigned char data hour=23,min=59,sec=55,sec20=0; //时、分、秒、百分之一秒

unsigned char code email[] = {"YEA:MON:DAT:TIME"};

void updatetime (void);

void LCMInit (void);

void pro_display(void);

void Delay400Ms (void);

void Delay5Ms (void);

void main(void)

{

Delay400Ms(); //启动等待,等LCM讲入工作状态

LCMInit(); //LCM初始化

DisplayListChar(0, 1, email);

TMOD=0X01;

TH0=0X4C;

TL0=0X00;

TR0=1;

ET0=1;

EA=1;

while(1);

}

void pro_timedate()

{

sec++;

if(sec > 59)

{sec = 0;

min++;

if(min>59)

{min=0;

hour++;

if(hour>23)

{hour=0;

date++;

if (month==1||month==3||month==5||month==7||month==8||month==10||month==12)

if (date>31)

{date=1;month++;} //大月31 天

if (month==4||month==6||month==9||month==11)

if (date>30)

{date=1;month++;} //小月30 天

if (month==2)

{if( leap_year()) //闰年的条件

{if (date>29) {date=1;month++;}} //闰年2 月为29 天

else

{if (date>28) {date=1;month++;}} //平年2 月为28 天

}

if (month>12) {month=1;year++;}

if (year>99) year=0;

}

}

}

}

bit leap_year()

{

bit leap;

if((year%4==0&&year%100!=0)||year%400==0)//闰年的条件

leap=1;

else

leap=0;

return leap;

}

//Timer0 中断处理程序,秒的产生

void timer0() interrupt 1

{

TH0=0x4C; //Timer0 置10ms 定时初值dc00H(2^16=65536D,dc00H=56320D)

TL0=0x00; //定时时间=(65536-56320)(1/110592)12=10ms (f0=110592Mhz)

sec20++;

if(sec20 >= 20) //1 秒时间 (10010ms=1000ms=1s)

{ sec20=0;

updatetime ();

pro_timedate();

pro_display ();

if(sec&0x01)

disbuf[13]=' ';

else disbuf[13]=':';

}

}

void updatetime(void)

{ disbuf[0] ='2';

disbuf[1] ='0';

disbuf[2] =year/10+48;

disbuf[3] =year%10+48;

disbuf[4] =' ';

disbuf[5] =month/10+48;

disbuf[6] =month%10+48;

disbuf[7] ='';

disbuf[8] =date/10+48;

disbuf[9] =date%10+48;

disbuf[10] =' ';

disbuf[11]=hour/10+48;

disbuf[12]=hour%10+48;

//disbuf[13]=' ';

disbuf[14]=min/10+48;

disbuf[15]=min%10+48;

}

//显示处理程序

void pro_display()

{ unsigned char f;

for (f=0;f<=15;f++)

{DisplayOneChar( f, 0, disbuf[f]);}

}

//写数据

void WriteDataLCM(unsigned char WDLCM)

{

ReadStatusLCM(); //检测忙

//WDLCM = ((WDLCM&0x01)<<7)|((WDLCM&0x02)<<5)|((WDLCM&0x04)<<3)|((WDLCM&0x08)<<1)|((WDLCM&0x10)>>1)|((WDLCM&0x20)>>3)|((WDLCM&0x40)>>5)|((WDLCM&0x80)>>7);

LCM_Data = WDLCM;

LCM_RS = 1;

LCM_RW = 0;

LCM_E = 0;

LCM_E = 0; //延时

LCM_E = 1;

}

//写指令

void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测

{

if (BuysC) ReadStatusLCM(); //根据需要检测忙

//WCLCM = ((WCLCM&0x01)<<7)|((WCLCM&0x02)<<5)|((WCLCM&0x04)<<3)|((WCLCM&0x08)<<1)|((WCLCM&0x10)>>1)|((WCLCM&0x20)>>3)|((WCLCM&0x40)>>5)|((WCLCM&0x80)>>7);

LCM_Data = WCLCM;

LCM_RS = 0;

LCM_RW = 0;

LCM_E = 0;

LCM_E = 0;

LCM_E = 1;

}

//读数据

unsigned char ReadDataLCM(void)

{

LCM_RS = 1;

LCM_RW = 1;

LCM_E = 0;

LCM_E = 0;

LCM_E = 1;

return(LCM_Data);

}

//读状态

unsigned char ReadStatusLCM(void)

{

LCM_Data = 0xFF;

LCM_RS = 0;

LCM_RW = 1;

LCM_E = 0;

LCM_E = 0;

LCM_E = 1;

while (LCM_Data & Busy); //检测忙信号

return(LCM_Data);

}

void LCMInit(void) //LCM初始化

{

LCM_Data = 0;

WriteCommandLCM(0x38,0);

1

//三次显示模式设置,不检测忙信号

Delay5Ms();

WriteCommandLCM(0x38,0);

Delay5Ms();

WriteCommandLCM(0x38,0);

Delay5Ms();

WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号

WriteCommandLCM(0x08,1); //关闭显示

WriteCommandLCM(0x01,1); //显示清屏

WriteCommandLCM(0x06,1); // 显示光标移动设置

WriteCommandLCM(0x0C,1); // 显示开及光标设置

}

//按指定位置显示一个字符

void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)

{

Y &= 0x1;

X &= 0xF; //限制X不能大于15,Y不能大于1

if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;

X |= 0x80; //算出指令码

WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码

WriteDataLCM(DData);

}

//按指定位置显示一串字符

void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code DData)

{

unsigned char ListLength;

ListLength = 0;

Y &= 0x1;

X &= 0xF; //限制X不能大于15,Y不能大于1

while (DData[ListLength]>0x20) //若到达字串尾则退出

{

if (X <= 0xF) //X坐标应小于0xF

{

DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符

ListLength++;

X++;

}

}

}

//50ms延时

void Delay5Ms(void)

{

unsigned int TempCyc = 5552;

while(TempCyc--);

}

//400ms延时

void Delay400Ms(void)

{

unsigned char TempCycA = 5;

unsigned int TempCycB;

while(TempCycA--)

{

TempCycB=7269;

while(TempCycB--);

};

}

AVR MEGE16 DS1302程序,分别保存为DS1302C DS1302H

后面是51 DS1302程序,分别保存为DS1302h mainc

用哪个下哪个吧。

#include "DS1302h"

#include "ym12864h"

#include "delayh"

/

函数名称: DS1302_init

功 能: 初始化DS1302的数据接口

参 数: 无

返回值 : 无

//

void DS1302_portinit(void)

{

DDRB|=BIT(RTC_CLK)|BIT(RTC_DATA)|BIT(RTC_CS);//将时钟端(RTC_CLK)数据端(RTC_DATA)片选端(RTC_CS)设置为输出

}

/

函数名称: DS1302_writeB

功 能: 向DS1302写入一个字节数据(没有RST *** 作)

参 数: byte--要写入的数据

返回值 : 无

//

void DS1302_writeB(uchar byte)

{

uchar i;

for(i=0;i<8;i++) //8位数据计数

{

CLR_CLK; //拉低时钟端

if(byte&0x01) //当前位是否是1

{

SET_DATA; //当前位是1,拉高数据端

}

else

{

CLR_DATA; //当前位是0,拉低数据端

}

delay_us(10); //调整时钟和脉冲宽度

SET_CLK; //时钟上升沿(DS1302采样数据)

byte>>=1; //数据右移1位,为送出新数据位做准备

}

}

/

函数名称: DS1302_readB

功 能: 从DS1302读出一个字节数据(没有RST *** 作)

参 数: 无

返回值 : byte--读出的数据

//

uchar DS1302_readB(void)

{

uchar i,byte=0;

DATA_IN; //将数据端口设置为输入

CLR_DATA; //无上拉电阻

for(i=0;i<8;i++) //8位数据计数

{

byte>>=1; //保存读入的数据位

SET_CLK; //时钟上升沿

delay_us(10); //延时,调整时钟脉冲宽度

CLR_CLK; //时钟下降沿,DS1302输出数据位

delay_us(10); //等待数据变化(MEGA16太快,必须等待DS1302的数据位输出,否则不能正确读出)

if(PINB&BIT(RTC_DATA)) //当前位是否是高电平

{

byte|=BIT(PB7); //是高电平就将返回数据的当前位置1

}

else

{

byte&=~BIT(PB7); //是低电平就将返回数据的当前位置0

}

}

DATA_OUT; //最后将数据端口设置为输出

return byte; //返回读出的数据

}

/

函数名称: DS1302_writeD

功 能: 向DS1302的某个地址写入一个字节数据

参 数: addr--地址值(寄存器或RAM)

data--要写入的地址

返回值 : 无

//

void DS1302_writeD(uchar addr,uchar data)

{

CLR_CS; //拉低片选端

CLR_CLK; //拉低时钟端

delay_us(10);

SET_CS //拉高片选端

delay_us(10); //调整片选脉冲

DS1302_writeB(addr); //写入 *** 作命令(地址)

delay_us(10);

CLR_CLK; //拉低时钟端

delay_us(10);

DS1302_writeB(data); //写入数据

CLR_CLK; //拉低时钟端

delay_us(10); //调整片选脉冲

CLR_CS; //拉低片选端

}

/

函数名称: DS1302_readD

功 能: 从DS1302的某个地址读出一个字节数据

参 数: addr--地址值(寄存器或RAM)

返回值 : data--读出的数据

//

uchar DS1302_readD(uchar addr)

{

uchar data;

CLR_CS; //拉低片选端

CLR_CLK; //拉低时钟端

delay_us(10);

SET_CS; //拉高片选端

delay_us(10); //调整片选脉冲

DS1302_writeB(addr); //写入 *** 作命令(地址)

delay_us(10);

data=DS1302_readB(); //读出数据

delay_us(10);

CLR_CLK; //拉低时钟端

CLR_CS; //拉低片选端

return data; //返回读出的数据

}

/

函数名称: DS1302_setT

功 能: 设置DS1302的时间

参 数: ptTimeD--设置时间数组指针

返回值 : 无

//

void DS1302_setT(uchar ptTimeD[])

{

uchar i;

uchar addr = 0x80; //写入地址从秒寄存器开始

DS1302_writeD(C_WP|WR,UPROTECT); //控制命令,WP位为0,允许写 *** 作

delay_ms(5);

for(i=0;i<7;i++)

{

DS1302_writeD(addr|WR,ptTimeD[i]); // 秒 分 时 日 月 星期 年

addr+=2;

delay_ms(1);

}

DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写 *** 作

}

/

函数名称: DS1302_getT

功 能: 读取DS1302的当前时间

参 数: time[]--读取的时间数组

返回值 : 无

//

void DS1302_getT(uchar time[])

{

uchar i;

////////下面的是单次读写//////////////////////////

/ uchar addr = 0x80; //读取地址从秒寄存器开始

for(i=0;i<7;i++)

{

time[i]=DS1302_readD(addr|RD); // 秒 分 时 日 月 星期 年

addr+=2;

}/

////////////////////////////////////////////////////

/////////下面是多字节读取///////////////

CLR_CS; //拉低片选端

delay_us(10);

SET_CS; //拉高片选端

delay_us(10); //调整片选脉冲

DS1302_writeB(0xbf); // 0xbf:时钟多字节读取命令

for (i=0;i<8;i++) //时间数据的存放格式是:

{ //秒,分,时,日,月,星期,年,控制

time[i]=DS1302_readB(); //7个数据(BCD格式)+1个控制

}

CLR_CS; //拉低片选端

///////////////////////////////////////////////

CLR_CLK; //拉低时钟端(时钟端在不 *** 作时为低)

}

/

函数名称: DS1302_check

功 能: 检测DS1302是否正常工作

参 数: 无

返回值 : exist--为TRUE为检测到DS1302,为FALSE为没检测到

//

/uchar DS1302_check(void)

{

uchar exist;

DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令

DS1302_writeD(C_RAMBASE|WR,0xA5); //RAM0写入0xA5

exist=DS1302_readD(C_RAMBASE|RD); //读取RAM0

if(exist==0xA5)

{

exist=TRUE; //如果读取值与写入值相等,返回TRUE

}

else

{

exist=FALSE; //如果读取值与写入值不相等,返回FALSE

}

return exist;

}/

/

函数名称: DS1302_init

功 能: 初始化DS1302

参 数: 无

返回值 : 无

//

void DS1302_init(void)

{

DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令

DS1302_writeD(C_SEC|WR,CLK_START); //启动振荡器,DS1302开始工作

DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写 *** 作

}

/

函数名称: BCD_ASCII

功 能: 将压缩BCD码转换成ascii码

参 数: BCD--将要转换的压缩BCD码

ptasc--转换后的ASCII码数组指针

返回值 : 无

//

void BCD_ASCII(uchar BCD,uchar ptasc[])

{

ptasc[0]=BCD/16|0x30; //0X58 35 38 //转换十位

ptasc[1]=BCD&0x0F|0x30; //转换个位

}

/

函数名称: Disp_time

功 能: 在1602液晶上显示当前时间(第1行格式:年-月-日 星期;第2行格式:时-分-秒)

参 数: time[]--时间数组

返回值 : 无

//

void Disp_time(uchar time[])

{

uchar i,asc[2];

uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'};//显示第1行的字符数组

uchar line2[9]={0,0,':',0,0,':',0,0,'\0'}; //显示第2行的字符数组

for(i=0;i<3;i++) //为第2行的字符数组赋值

{

BCD_ASCII(time[2-i],asc);

line2[i3]=asc[0];

line2[i3+1]=asc[1];

}

BCD_ASCII(time[6],asc); //为第1行的年赋值

line1[0]=asc[0];

line1[1]=asc[1];

BCD_ASCII(time[4],asc); //为第1行的月赋值

line1[3]=asc[0];

line1[4]=asc[1];

BCD_ASCII(time[3],asc); //为第1行的日赋值

line1[6]=asc[0];

line1[7]=asc[1];

BCD_ASCII(time[5],asc); //为第1行的星期赋值

line1[9]=asc[1];

Disp_String(0,16,"20"); //第1行从第3个位置开始显示,将07年显示为2007的形式

Disp_String(0,32,line1);

Disp_String(3,32,line2); //第2行从第5个位置开始显示,/第2行显示

}

#ifndef __DS1302_H

#define __DS1302_H

#include <iom16vh>

#include <macrosh>

typedef unsigned char uchar;

typedef unsigned int uint;

typedef unsigned long ulong;

/RTC常量/

#define RTC_CLK PB1

#define RTC_DATA PB0

#define RTC_CS PB4

#define SET_CLK PORTB|=BIT(RTC_CLK);

#define CLR_CLK PORTB&=~BIT(RTC_CLK);

#define SET_DATA PORTB|=BIT(RTC_DATA);

#define CLR_DATA PORTB&=~BIT(RTC_DATA);

#define SET_CS PORTB|=BIT(RTC_CS);

#define CLR_CS PORTB&=~BIT(RTC_CS);

#define DATA_OUT DDRB|=BIT(RTC_DATA);

#define DATA_IN DDRB&=~BIT(RTC_DATA);

//命令

#define RD 0x01

#define WR 0x00

#define C_SEC 0x80 //秒

#define C_MIN 0x82 //分

#define C_HR 0x84 //时

#define C_DAY 0x86 //日

#define C_MTH 0x88 //月

#define C_WK 0x8A //星期 DATE

#define C_YR 0x8C //年

#define C_WP 0x8E //控制(写保护)

#define C_CHARGE 0x90 //涓流充电

#define C_BURST 0xBE //时钟多字节

//配置

#define CLK_HALT 0x80 //停止时钟控制位 SECOND bit7

#define CLK_START 0x00 //启动时钟

#define M12_24 0x80 //12/24小时值选择位 HOUR bit7

#define PROTECT 0x80 //写保护控制位 CONTROL bit7

#define UPROTECT 0x00 //写保护控制位 CONTROL bit7

//涓流充电控制常量

#define TC_D1R2 0xA5 //high 1 Diode +2K Resistors

#define TC_D2R8 0xAB //low 2 Diodes+8K Resistors

#define TC_DISABLED 0x00 //Disabled(TCS<>1010 or DS=00 or RS=00)

//RAM 命令

#define C_RAMBASE 0xC0 //RAM0~RAM30<<1 地址需左移一位

void DS1302_portinit(void);

void DS1302_writeB(unsigned char byte);

unsigned char DS1302_readB(void);

void DS1302_writeD(unsigned char addr,unsigned char data);

unsigned char DS1302_readD(unsigned char addr);

void DS1302_setT(unsigned char ptTimeD[]);

void DS1302_getT(unsigned char time[]);

void DS1302_init(void);

void BCD_ASCII(unsigned char BCD,unsigned char ptasc[]);

void Disp_time(unsigned char time[]);

extern void DS1302_portinit(void);

extern void DS1302_setT(unsigned char ptTimeD[]);

extern void DS1302_getT(unsigned char time[]);

extern void DS1302_init(void);

extern void Disp_time(unsigned char time[]);

#endif

#include<reg52h>

#define uint unsigned int

#define uchar unsigned char

sbit dsrst=P1^4;

sbit dssclk=P1^1;

sbit dsio=P1^0;

uint a[24]={0,0,0,0,0,0,1,0,0,1,9,0,0,0,0,0,0,0,1,0,1,0,9,0};

//分别对应秒秒分分时时日日月月年年

//后12位为闹钟位,用于存储闹钟数据

//1302write DS1302写数据

void dswrite(uchar dswrite)

{

uchar i,temp;

delay(1);

temp=dswrite;

for(i=0;i<8;i++)

{

dsio=temp&0x01;

delay(1);

dssclk=1;

delay(1);

dssclk=0;

temp=temp>>1;

}

}

//1302read Ds1302读数据

uchar dsread()

{

uchar i,temp;

delay(1);

temp=0;

for(i=0;i<8;i++)

{

temp=temp>>1;

if(dsio==1)temp=temp+0x80;

delay(1);

dssclk=1;

delay(1);

dssclk=0;

}

return temp;

}

//1302addshuju DS1302向某地址写入某数据

void dsaddshuju(uchar add,uchar dsshuju)

{

dsrst=0;

dssclk=0;

dsrst=1;

dswrite(add);// 地址,命令

dswrite(dsshuju);// 写1Byte数据

dssclk=1;

dsrst=0;

dsio=0;

}

//1302on DS1302初始化

void dson()

{

uchar i;

dsaddshuju(0x8c,(a[11]<<4)+a[10]);

for(i=0;i<5;i++)

{

dsaddshuju(0x88-i2,(a[9-i2]<<4)+a[8-i2]);

}

}

//

//

/ /

//

/ /

/ /

//

//

/ /

/ 温度时钟显示 C语言程序 /

/ /

//

//

/

硬件连接: DS1302 io - P10 rst - P14 clk - P11

DS18B20 dq - P15

LCD1602 RS- P22 RW - P23 EN - P24 DATAPORT - P0

//

#include<reg52h>

#include"lcd1602h"

#include"ds1302h"

#include"ds18b20h"

#define uint unsigned int

#define uchar unsigned char

uint b[6];

//年月日时分秒

uchar code row1[]={"2009-10-01 "};

uchar code row2[]={"00:00:00"};

uchar year1[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年

uchar year2[12]={31,29,31,30,31,30,31,31,30,31,30,31};//润年

uchar j[6]={0x85,0x88,0x8b,0x84+0x40,0x87+0x40,0x8a+0x40};//LCD地址

uchar i,k,jj=0,w,clock=0,bigclock=0,c=0,num;

//i循环数 k温度缓存 jj地址位

uint temp;

sbit b1=P3^0;//设置

sbit b2=P3^1;//上调

sbit b3=P3^2;//下调

sbit b4=P3^3;//转换

sbit b5=P3^4;//闹钟

sbit speaker=P3^5;

lcdscan()

{

for(i=0;i<6;i++)

{

lcdwrite(j[i]);

lcdshuju(a[11-i2]+0x30);

lcdwrite(j[i]+0x01);

lcdshuju(a[10-i2]+0x30);

}

}

void key()

{

if(b1==0)

{

dsaddshuju(0x80,(a[1]<<4)+a[0]+0x80);

while(b1==0)

{

for(i=0;i<6;i++)

{

b[i]=a[11-i2+clock]10+a[10-i2+clock];

}

if(b4==0)

{

delay(3);

jj++;

if(jj==6)

{

jj=0;

}

}

if(b2==0)

{

delay(3);

b[jj]++;

if(b[5]==60)b[5]=0;

if(b[4]==60)b[4]=0;

if(b[3]==24)b[3]=0;

if((b[0]%4==0 && b[0]%100!=0) || b[0]%400==0){if(b[2]>year2[b[1]-1])b[2]=1;}

else {if(b[2]>year1[b[1]-1])b[2]=1;}

if(b[1]==13)b[1]=1;

if(b[0]==100)b[0]=0;

}

if(b3==0)

{

delay(3);

b[jj]--;

if(b[5]==-1)b[5]=59;

if(b[4]==-1)b[4]=59;

if(b[3]==-1)b[3]=23;

if((b[0]%4==0 && b[0]%100!=0) || b[0]%400==0){if(b[2]<=0)b[2]=year2[b[1]-1];}

else {if(b[2]<=0)b[2]=year1[b[1]-1];}

if(b[1]==0)b[1]=12;

if(b[0]==-1)b[0]=99;

}

for(i=0;i<6;i++)

{

a[11-i2+clock]=b[i]/10;

a[10-i2+clock]=b[i]%10;

}

lcdwrite(j[jj]);

lcdshuju(0);

lcdwrite(j[jj]+1);

lcdshuju(0);

delay(200);

lcdwrite(j[jj]);

lcdshuju(a[11-2jj+clock]+0x30);

lcdwrite(j[jj]+1);

lcdshuju(a[10-2jj+clock]+0x30);

delay(200);

if(b1==1)

{

dsaddshuju(0x80,(a[1]<<4)+a[0]);

dson();

}

if(b5==0)clock=12;

}

}

}

void main()

{

speaker=0;

lcdrw=0;

dson();

lcdon();

lcdwrite(0x83);

for(i=0;i<10;i++)

{

lcdshuju(row1[i]);

delay(1);

}

lcdwrite(0x84+0x40);

for(i=0;i<8;i++)

{

lcdshuju(row2[i]);

delay(1);

}

dsrst=0;

dssclk=0;

while(1)

{

for(i=0;i<5;i++)

{

dsrst=1;

dswrite(0x81+i2);

k=dsread();

dsrst=0;

a[i2]=k&0x0f;

a[i2+1]=(k>>4)&0x0f;

}

dsrst=1;

dswrite(0x8d);

k=dsread();

dsrst=0;

a[10]=k&0x0f;

a[11]=(k>>4)&0x0f;

delay(100);

lcdscan();

key();

if(b5==0)

{

for(i=0;i<12;i++)

{

if(a[i+12]==a[i])num++;

}

if(num==12)bigclock=1;

else num=0;

lcdwrite(0x8e);

lcdshuju('&');

}

else

{

lcdwrite(0x8e);

lcdshuju(0x00);

}

if(bigclock==1)

{

speaker=1;

c++;

if(c==100){bigclock=0;speaker=0;}

}

temp=readtemperature();//temp是uint型的。不然会出现温度到25后回00的现象。可能是由于十六进制与十进制的差异。

lcdwrite(0x8d+0x40);

lcdshuju(temp/100+0x30);

lcdwrite(0x8e+0x40);

lcdshuju(temp/10%10+0x30);

}

}

自己看看,看不明白HI我。

以上就是关于基于DS1302与AT89C51的实时日历时钟的LCD显示程序你还有么还有图的全部的内容,包括:基于DS1302与AT89C51的实时日历时钟的LCD显示程序你还有么还有图的、用80C51+DS1302做电子钟要加入DS1302的程序吗如何写入、求lm016l与ds1302 52 单片机实现时钟显示的程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zz/9518684.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-29
下一篇 2023-04-29

发表评论

登录后才能评论

评论列表(0条)

保存