51单片机+ds1302+lcd1602简易电子时钟(带闹钟功能)
Posted perseverance52
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51单片机+ds1302+lcd1602简易电子时钟(带闹钟功能)相关的知识,希望对你有一定的参考价值。
51单片机+ds1302+lcd1602简易电子时钟(带闹钟功能)
AT89C52
、LCD1602
、DS1302
、speaker
、Proteus
仿真
实例代码
#include<reg52.H>
#include<INTRINS.H>
#define TIME (0X10000-50000)
#define FLAG 0XEF //闹钟标志
//引脚连接图
sbit rst=P3^5;
sbit clk=P3^4;
sbit dat=P3^3;
sbit rs=P1^5;
sbit rw=P1^6;
sbit e=P1^7;
sbit DQ=P1^4;
sbit P3_2=P3^2;
sbit ACC_7=ACC^7;
//全局变量及常量定义
unsigned char i=20,j,time1[16];
unsigned char alarm[2],time2[15],time[3];
unsigned char code Day[]={31,28,31,30,31,30,31,31,30,31,30,31};//12个月的最大日期(非闰年)
//音律表
unsigned int code table1[]={64260,64400,64524,64580,64684,64777,
64820,64898,64968,65030,65058,65110,65157,65178,65217};
//发声部分的延时时间
unsigned char code table2[]={0x82,1,0x81,0xf4,0xd4,0xb4,0xa4,
0x94,0xe2,1,0xe1,0xd4,0xb4,0xc4,0xb4,4,0};
//LCD自建字
unsigned char code tab[]={0x10,0x11,0x12,0x1c,0x1c,0x12,0x11,0x11,
0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,//年
0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00,//月
0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00};//日
unsigned char code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
//闹钟中用的全局变量
unsigned char th1,tl1;
unsigned char temp_data[2]={0x00,0x00}; // 读出温度暂放
bit flag; //18b20存在标志位
/***********11微秒延时函数**********/
void delay(unsigned int t)
{
for(;t>0;t--);
}
/***********18B20复位函数**********/
void RST18B20(void)
{
unsigned char i;
DQ=1;_nop_();_nop_();
DQ=0; //
delay(50); // 550us
DQ=1; //
delay(6); // 66us
for(i=0;i<0x30;i++)
{
if(!DQ)
goto d1;
}
flag=0; //清标志位,表示ds1820不存在
DQ=1;
return;
d1: delay(45); //延时500us
flag=1;
DQ=1; //置标志位,表示ds1820存在
}
/**********18B20写命令函数*********/
//向 1-WIRE 总线上写一个字节
void Write1Byte18B20(unsigned char val)
{
unsigned char i;
for (i=8; i>0; i--) //
{
DQ=1;_nop_();_nop_();
DQ=0;_nop_();_nop_();_nop_();_nop_();_nop_();//5us
DQ=val&0x01; //最低位移出
delay(6); //66us
val=val/2; //右移一位
}
DQ=1;
delay(1);
}
/*********18B20读1个字节函数********/
//从总线上读取一个字节
unsigned char Read1Byte18B20(void)
{
unsigned char i;
unsigned char value=0;
for (i=8;i>0;i--)
{
DQ=1;_nop_();_nop_();
value>>=1;
DQ=0; //
_nop_();_nop_();_nop_();_nop_(); //4us
DQ=1;_nop_();_nop_();_nop_();_nop_(); //4us
if(DQ)
value|=0x80;
delay(6); //66us
}
DQ=1;
return(value);
}
/***********读出温度函数**********/
void Read18B20()
{
RST18B20(); //总线复位
if(!flag) //判断ds1820是否存在?若ds18b20不存在则返回
return;
//Write1Byte18B20(0xCC); // Skip ROM
//Write1Byte18B20(0x44); // 发转换命令
//delay(70);
Write1Byte18B20(0xCC); //发Skip ROM命令
Write1Byte18B20(0xBE); //发读命令
temp_data[0]=Read1Byte18B20(); //温度低8位
temp_data[1]=Read1Byte18B20(); //温度高8位
RST18B20();
Write1Byte18B20(0xCC); // Skip ROM
Write1Byte18B20(0x44); // 发转换命令
}
/***********温度数据处理函数**********/
void DealTempData()
{
unsigned char n=0,m;
if(temp_data[1]>127)//负温度求补码
{
temp_data[1]=(256-temp_data[1]);
temp_data[0]=(256-temp_data[0]);
n=1;
}
time2[13]=ditab[temp_data[0]&0x0f]+'0';
time2[12]='.';
m=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);//
if(n)
{
m-=16;
}
time2[9]=m/100+'0';
time2[11]=m%100;
time2[10]=time2[11]/10+'0';
time2[11]=time2[11]%10+'0';
if(time2[9]=='0')//最高位为0时都不显示
{
time2[9]=0x20;
if(n)//负温度时最高位显示"-"
{
time2[9]='-';
}
if(time2[10]=='0')
{
if(n)
{
time2[10]='-';
time2[9]=0x20;
}
else
time2[10]=0x20;
if(time2[11]=='0'&&time2[13]=='0')
time2[11]=time2[12]=0x20;
}
}
}
void delay1ms(unsigned char time) //延时1ms
{
unsigned char i,j;
for(i=0;i<time;i++)
{
for(j=0;j<110;j++);
}
}
//使能1602
void EnableLCD()
{
rs=0;
rw=0;
e=0;
delay1ms(3);
e=1;
}
//写LCD函数
void WriteLCD(unsigned char i)
{
P0=i;
rs=1;
rw=0;
e=0;
delay1ms(2);
e=1;
}
//写LCD内部地址函数
void WriteLCDRAM(unsigned char data *address,m)
{
unsigned char i,j;
for(i=0;i<m;i++,address++)
{
j=*address;
WriteLCD(j);
}
}
//LCD显示
void LCDSHOW()
{
P0=0XC; //显示器开、光标关
EnableLCD();
P0=0x80; //写入显示起始地址
EnableLCD();
WriteLCDRAM(time1,16);
P0=0xc1; //写入显示起始地址
EnableLCD();
WriteLCDRAM(time2,15);
}
//自建字函数库
void DesignHZ()
{
unsigned char i;
P0=0x40;
EnableLCD();
for(i=0;i<32;i++)
{
WriteLCD(tab[i]);
delay1ms(2);
}
}
//写DS1302子程序
void WriteDS1302(unsigned char address)
{
unsigned char i;
clk=0;
_nop_();
rst=1;
_nop_();
for(i=0;i<8;i++)
{
dat=address&1;
_nop_();
clk=1;
address>>=1;
clk=0;
}
}
//读DS1302子程序
unsigned char ReadDS1302()
{
unsigned char i,j=0;
for(i=0;i<8;i++)
{
j>>=1;
_nop_();
clk=0;
_nop_();
if(dat)
j|=0x80;
_nop_();
clk=1;
}
return(j);
}
//部分显示数据初始化
void TimeInit()
{
time1[1]=time1[13]=time2[8]=time2[9]=time2[10]=0x20,time2[14]=0;
time1[6]=1,time1[9]=2,time1[12]=3,time1[2]='2',time1[3]='0';
time1[14]='W',time2[2]=time2[5]=':';
WriteDS1302(0xc1);
alarm[0]=ReadDS1302();
rst=0;
WriteDS1302(0xc3);
alarm[1]=ReadDS1302();
rst=0;
WriteDS1302(0xc5);
time1[0]=ReadDS1302();
rst=0;
}
//读取时间
void ReadTime()
{
unsigned char i,m,n;
WriteDS1302(0x8d); //读取年份
m=ReadDS1302();
rst=0;
time1[4]=m/16+0x30;
time1[5]=m%16+0x30;
WriteDS1302(0x8b); //读取星期
m=ReadDS1302();
rst=0;
time1[15]=m+0x30;
for(i=7,n=0x89;i<11;i+=3,n-=2) //读取月份和日期
{
WriteDS1302(n);
m=ReadDS1302();
rst=0;
time1[i]=m/16+0x30;
time1[i+1]=m%16+0x30;
}
for(m=0,i=0,n=0x85;i<7;i+=3,n-=2,m++) //读取时,分,秒
{
WriteDS1302(n);
time[m]=ReadDS1302();
rst=0;
time2[i]=time[m]/16+0x30;
time2[i+1]=time[m]%16+0x30;
}
}
void time0() interrupt 1 using 1
{
i以上是关于51单片机+ds1302+lcd1602简易电子时钟(带闹钟功能)的主要内容,如果未能解决你的问题,请参考以下文章
51单片机+DS1302+lcd1602+按键时间调整+Proteus仿真
51单片机 DHT11+ DS1302+LCD1602温湿度监测系统
基于51单片机+DS1302+ LCD1602显示时间Proteus仿真