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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于DS1302与AT89C51的实时日历时钟的LCD显示程序你还有么?还有图的相关的知识,希望对你有一定的参考价值。

2.3.6 显示模块的设计
本设计中由于要对时间、温度进行显示,所以选择液晶显示屏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端和P2.0,R/W端和P2.1, E 端和P2.2相连,当RS=0时,对LCD1602写入指令;当RS=1时,对LCD1602写入数据。当R/W端接高电平时芯片处于读数据状态,反之处于写数据状态,E端为使能信号端。当R/W为高电平,E端也为高电平,RS为低电平时,液晶显示屏显示需要显示的示数。图2.11为1602液晶显示屏与单片机的硬件连接图。
图2.11 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=tem*0.0625;
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); //设置液晶工作模式 意思:16*2行显示,5*7点阵,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=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//年月日显示将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)/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); //下面case3~case7基本相同,改变地址就行了
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;
write_sfm(0x08,miao);
temp=(miao)/10*16+(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);
来自:求助得到的回答
参考技术A http://user.qzone.qq.com/305526507/blog/1316076913?ptlang=2052&ADUIN=435117580&ADSESSION=1318752627&ADTAG=CLIENT.QQ.2839_FriendTip_QzoneFolder.0去看看吧有图有真相啊!还有视频哦!程序开源哦!追问

啊,那个太高级了,我指希望简单一点的,只要有DS1302,DS18B20,MAX232,AT89C51,LCD1602模块的就行了

追答

还高级吗!

参考技术B 可以到我博客去看看,有图有程序。http://blog.sina.com.cn/s/blog_534a5d500100bdqz.html

Arduino UNO + DS1302简单获取时间并串口打印

Arduino UNO + DS1302简单获取时间并串口打印


  • DS1302模块

DS1302简介

DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31 字节静态RAM ,通过简单的串行接口与单片机进行通信。实时时钟/日历电路提供秒、分、时、日、周、月、年的信息,每月的天数和闰年的天数可自动调整。时钟操作可通过AM/PM 指示决定采用24 或12 小时格式。DS1302 与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三个口线:(1)RST 复位(2)I/O 数据线(3)SCLK串行时钟。时钟/RAM 的读/写数据以一个字节或多达31 个字节的字符组方式通信。DS1302 工作时功耗很低保持数据和时钟信息时功率小于1mW

DS1302主要性能指标:

★ 实时时钟具有能计算2100 年之前的秒、分、时、日、星期、月、年的能力,还有闰年调整的能力
★ 31 8 位暂存数据存储RAM
★ 串行 I/O 口方式使得管脚数量最少
★ 宽范围工作电压2.0 5.5V
★ 工作电流 2.0V 时,小于300nA
★ 读/写时钟或RAM 数据时有两种传送方式单字节传送和多字节传送字符组方式
★ 8

以上是关于基于DS1302与AT89C51的实时日历时钟的LCD显示程序你还有么?还有图的的主要内容,如果未能解决你的问题,请参考以下文章

基于51单片机+DS1302时钟模块+LCD1602显示

基于51单片机+DS1302时钟模块+LCD1602显示

基于51单片机+DS1302时钟模块+LCD1602显示

51单片机 LCD1602+DS1302实时时钟+Proteus仿真

Arduino UNO + DS1302简单获取时间并串口打印

51单片机DS1302+ DS18b20+LCD1602时钟仿真