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 单片机实现时钟显示的程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)