标题:
51单片机DS1302简要记录
[打印本页]
作者:
NIMITIZ
时间:
2021-5-16 20:40
标题:
51单片机DS1302简要记录
写了一个DS1302的程序,在开发板上成功运行,通过LCD1602显示时间,现在分享出来,给像我这样的单片机萌新一个参考吧。
从2021年5月11日0时0分0秒开始计时并在LCD1602上显示,源码如下:
#include<reg52.h>
#include<intrins.h>
sbit RST=P2^4;
sbit CLK=P2^1;
sbit IO=P2^0;
sbit RS=P1^0;
sbit RW=P1^1;
sbit E=P2^5;
sbit DU=P2^6;
unsigned char num[]={"0123456789"}; //LCD1602显示的数字字符
void X() //关闭数码管
{
DU=1;
P0=0x00;
DU=0;
}
void Delay()
{
_nop_();
}
void Write_Bit_DS1302(unsigned char DAT) //向DS1302写入一字节的数据
{
unsigned char i;
CLK=0;
Delay();
for(i=0;i<8;i++)
{
IO=DAT&0x01; //低位在前,高位在后
Delay();
CLK=1; //时钟信号上升沿,写入数据
Delay();
CLK=0; //重新拉低CLK,形成脉冲
DAT>>=1; //将DAT的各数据位右移1位,准备写入下一数据位
}
}
void Write_DS1302(unsigned char CMD,unsigned char DAT) //向DS1302写入命令和数据
{
RST=0; //禁止数据传输
CLK=0; //在写入数据前确保CLK置低电平
RST=1; //开始数据传输
Delay();
Write_Bit_DS1302(CMD); //写入命令
Write_Bit_DS1302(DAT); //写入数据
CLK=1;
RST=0;
}
unsigned char Read_Bit_DS1302() //从DS1302读出一字节的数据
{
unsigned char i,DAT;
Delay();
for(i=0;i<8;i++)
{
DAT>>=1;
if(IO==1)
{
DAT|=0x80;
}
CLK=1;
Delay();
CLK=0; //时钟信号下降沿,读出数据
Delay();
}
return DAT;
}
unsigned char Read_DS1302(unsigned char CMD) //向DS1302写入命令后再从DS1302读出数据
{
unsigned char DAT;
RST=0;
CLK=0;
RST=1;
Write_Bit_DS1302(CMD); //写入命令
DAT=Read_Bit_DS1302(); //读出数据
CLK=1;
RST=0;
return DAT;
}
void Init_DS1302() //DS1302初始化
{
unsigned char X;
X=Read_DS1302(0x81);
if(X&0x80) //判断DS1302是否处于运行状态
{
Write_DS1302(0x8e,0x00); //允许将数据写入DS1302的寄存器
Write_DS1302(0x80,((00/10)<<4|(00%10))); //写入“秒”的初始值,需要将LCD1602显示的数字的ASCII值转换成BCD码
Write_DS1302(0x82,((00/10)<<4|(00%10))); //写入“分”的初始值
Write_DS1302(0x84,((00/10)<<4|(00%10))); //写入“时”的初始值
Write_DS1302(0x86,((11/10)<<4|(11%10))); //写入“日”的初始值
Write_DS1302(0x88,((5/10)<<4|(5%10))); //写入“月”的初始值
Write_DS1302(0x8c,((21/10)<<4|(21%10))); //写入“年”的初始值
Write_DS1302(0x8e,0x80); //禁止将数据写入DS1302的寄存器
}
}
void Delay5ms()
{
unsigned char i,j;
_nop_();
i=9;
j=244;
do
{
while(--j);
}
while(--i);
}
int ReadBusy() //LCD1602“读忙”操作
{
int temp;
RS=0;
RW=1;
_nop_();
P0=0xff;
_nop_();
E=1;
_nop_();
temp=P0;
_nop_();
E=0;
return(temp&0x80);
}
void Write_Com(char com) //LCD1602“写命令”操作
{
while(ReadBusy());
RS=0;
RW=0;
E=0;
_nop_();
P0=com;
_nop_();
E=1;
Delay5ms();
E=0;
Delay5ms();
}
void Write_Dat(char dat) //LCD1602“写数据”操作
{
while(ReadBusy());
RS=1;
RW=0;
E=0;
_nop_();
P0=dat;
_nop_();
E=1;
Delay5ms();
E=0;
Delay5ms();
}
void LCD1602_Init() //LCD1602初始化
{
Delay5ms(); //延时15ms,首次写入LCD1602时应给LCD1602一段较长的响应时间
Delay5ms();
Delay5ms();
Write_Com(0x38); //显示模式设置:16*2显示、5*7点阵,连续写入3次,确保LCD1602初始化成功
Delay5ms();
Write_Com(0x38);
Delay5ms();
Write_Com(0x38);
Delay5ms();
Write_Com(0x0c); //显示模式设置:开显示、光标不显示、光标不闪烁
Delay5ms();
Write_Com(0x06); //显示模式设置:光标右移,字符不右移
Delay5ms();
Write_Com(0x01); //清除屏幕
Delay5ms();
}
void Display_Second(unsigned char x) //LCD1602显示“秒”的数值
{
unsigned char i,j;
i=x/10; //取数值的十位
j=x%10; //取数值的个位
Write_Com(0x80+0x49); //写入在LCD1602上显示的位置
Write_Dat(num[i]);
Write_Dat(num[j]);
Delay5ms();
}
void Display_Minute(unsigned char x) //LCD1602显示“分”的数值
{
unsigned char i,j;
i=x/10;
j=x%10;
Write_Com(0x80+0x46);
Write_Dat(num[i]);
Write_Dat(num[j]);
Delay5ms();
}
void Display_Hour(unsigned char x) //LCD1602显示“时”的数值
{
unsigned char i,j;
i=x/10;
j=x%10;
Write_Com(0x80+0x43);
Write_Dat(num[i]);
Write_Dat(num[j]);
Delay5ms();
}
void Display_Day(unsigned char x) //LCD1602显示“日”的数值
{
unsigned char i,j;
i=x/10;
j=x%10;
Write_Com(0x80+0x0c);
Write_Dat(num[i]);
Write_Dat(num[j]);
Delay5ms();
}
void Display_Month(unsigned char x) //LCD1602显示“月”的数值
{
unsigned char i,j;
i=x/10;
j=x%10;
Write_Com(0x80+0x09);
Write_Dat(num[i]);
Write_Dat(num[j]);
Delay5ms();
}
void Display_Year(unsigned char x) //LCD1602显示“年”的数值
{
unsigned char i,j;
i=x/10;
j=x%10;
Write_Com(0x80+0x06);
Write_Dat(num[i]);
Write_Dat(num[j]);
Delay5ms();
}
void main()
{
unsigned char second,minute,hour,day,month,year;
unsigned char temp; //暂存从DS1302读出的数据
X();
LCD1602_Init();
Write_Com(0x80+0x01);
Write_Dat('D');
Write_Dat('A');
Write_Dat('T');
Write_Dat('E');
Write_Dat(':');
Delay5ms();
Write_Com(0x80+0x08);
Write_Dat('-');
Delay5ms();
Write_Com(0x80+0x0b);
Write_Dat('-');
Delay5ms();
Write_Com(0x80+0x45);
Write_Dat(':');
Delay5ms();
Write_Com(0x80+0x48);
Write_Dat(':');
Delay5ms();
Init_DS1302();
while(1)
{
temp=Read_DS1302(0x81);
second=((temp&0x70)>>4)*10+(temp&0x0f); //将“秒”的BCD码转换成对应的ASCII值
Display_Second(second);
temp=Read_DS1302(0x83);
minute=((temp&0x70)>>4)*10+(temp&0x0f); //将“分”的BCD码转换成对应的ASCII值
Display_Minute(minute);
temp=Read_DS1302(0x85);
hour=((temp&0x70)>>4)*10+(temp&0x0f); //将“时”的BCD码转换成对应的ASCII值
Display_Hour(hour);
temp=Read_DS1302(0x87);
day=((temp&0x70)>>4)*10+(temp&0x0f); //将“日”的BCD码转换成对应的ASCII值
Display_Day(day);
temp=Read_DS1302(0x89);
month=((temp&0x70)>>4)*10+(temp&0x0f); //将“月”的BCD码转换成对应的ASCII值
Display_Month(month);
temp=Read_DS1302(0x8d);
year=((temp&0x70)>>4)*10+(temp&0x0f); //将“年”的BCD码转换成对应的ASCII值
Display_Year(year);
}
}
复制代码
以下为原理图
LCD1602模块.png
(30.13 KB, 下载次数: 150)
下载附件
2021-5-16 20:39 上传
DS1302时钟模块.png
(19.63 KB, 下载次数: 161)
下载附件
2021-5-16 20:39 上传
作者:
sharehope
时间:
2021-5-20 22:05
感谢分享,有个疑问,I/O接口的输出方式是什么?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1