实验 串行口实时时钟实验.docx
- 文档编号:12007579
- 上传时间:2023-04-16
- 格式:DOCX
- 页数:25
- 大小:398.93KB
实验 串行口实时时钟实验.docx
《实验 串行口实时时钟实验.docx》由会员分享,可在线阅读,更多相关《实验 串行口实时时钟实验.docx(25页珍藏版)》请在冰豆网上搜索。
实验串行口实时时钟实验
实验三串行口实时时钟实验
实验目的
1、了解实时时钟电路工作原理
2、了解串行时钟芯片的控制方法
3、掌握DS1302串行时钟芯片的使用方法
实验仪器
单片机开发板、万利仿真机、稳压电源、计算机
实验原理
1、DS1302串行时钟芯片工作原理
DS1302是一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。
采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
芯片内部有一个31×8的用于临时性存放数据的RAM寄存器。
DS1302增加了主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。
引脚图如图4-77所示。
图4-77DS1302引脚图
DS1302的控制字如下所示。
DS1302的控制字最高位必须为1;D6位:
1:
读写内部通用存储器,0:
读写时钟存储器;随后是地址位。
最低位是读写控制:
1代表读,0:
代表写。
DS1302内部日历数据存储器位定义如图4-78所示。
图4-78DS1302内部日历数据存储器结构图
CH:
时钟停止位(CH=0振荡器工作允许,CH=1振荡器停止)
寄存器2的第7位:
12/24小时标志(bit7=1,12小时模式,bit7=0,24小时模式)
寄存器2的第5位:
AM/PM定义(AP=1下午模式,AP=0上午模式)
WP:
写保护位(WP=0寄存器数据能够写入,WP=1寄存器数据不能写入)
TCS:
涓流充电选择(TCS=1010使能涓流充电,TCS=其它禁止涓流充电)
DS:
二极管选择位(DS=01一个二极管,DS=10两个,DS=00或11,充电功能也被禁止)
从图中可以看出,第1脚电源经过开关、二极管、电阻对接在第8脚的备用电源进行充电。
调整涓流充电控制寄存器的值可以控制涓流充电方式。
2、DS1302芯片读写时序
DS1302采用三线串行口通迅,占用IO口少。
数据在SCLK的上升沿有效。
每个SCLK正脉冲锁存一位数据。
如图4-80所示。
图4-80DS芯片读写时序图
DS1302支持单字节读写和多字节读写方式。
单字节读写时,单片机先发出读写的地址,然后再读写一字节数据;多字节读写时,单片机先发出读写的地址,然后再连续读写多个字节。
如图4-81所示。
图4-82DS1302读数据帧结构
3、DS1302应用电路
51单片机没有SPI接口,只能用普通IO口来模拟读写时序。
将芯片IO口与单片机连接,电容C1用于备份电源,电源断电时为DS1302提供电能。
DS1302的复位端与74LS138的Y6连接,当P2=0CH时,复位端有效。
电路如图4-83所示。
图4-83DS1302应用电路
4、DS1302应用程序设计
DS1302应用程序设计包含:
DS1302串口驱动程序、DS1302接口程序等。
DS1302串口驱动程序就是串口发送、接收一个字节数据程序。
DS1302接口程序包含:
时钟启动/停止、时间日期设置、读时间日期、充电方式设计等。
根据原理说明,我们可以设计出一部分程序。
流程序图如图4-84所示。
图4-84DS1302应用程序流程图
实验内容
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
#definedata1000
sbitLEDCLK=P3^4;
sbitLEDDIN=P2^3;
ucharcodeledtable[]={0x03,0x9F,0x25,0x0D,0x99,0x49,0x41,0x1F,
0x01,0x09,0x11,0xC1,0x63,0x85,0x61,0x71,0xFD};
uchardispbuf[8];
uintmsecond=0;
ucharwei=0;
uchartimebuf[3]={0x12,0x34,0x56};
#definesecondtimebuf[0]
#defineminutetimebuf[1]
#definehourtimebuf[2]
#defineNOP3()_nop_();_nop_();_nop_()
/**DS1302与MCU连接的各端口定义*****************/
sbitDS_IO=P3^5;//DS1302数据口
sbitDS_SCLK=P1^7;//DS1302串行时钟
#defineDSRST_1P2=0XFF;//
#defineDSRST_0P2=0X03;//
/**DS1302内部各个寄存器地址定义***********/
#defineDS1302_SECOND0X80//秒
#defineDS1302_MINUTE0X82//分
#defineDS1302_HOUR0X84//时
#defineDS1302_DAY0X86//日
#defineDS1302_MONTH0X88//月
#defineDS1302_WEEK0X8A//星期
#defineDS1302_YEAR0X8C//年
#defineDS1302_CONTROL0X8E//写保护控制位
#defineDS1302_RAM(X)(0XC0+(X)*2)//用于计算DS1302静态RAM地址
/************************************************
延时函数
*功能:
可随意设置延时时间,延时时间为ttms.晶振为12MHz
*************************************************/
voiddelay1ms(unsignedinttms)
{
unsignedchari;
while(tms--)
for(i=123;i>0;i--)
;
}
/**********************************************
写入单个字节
**********************************************/
voidDS1302WriteByte(ucharWdate)
{
uchari;
EA=0;
DS_SCLK=1;
for(i=0;i<8;i++)
{
DS_IO=(bit)(Wdate&0x01);
DS_SCLK=1;
DS_SCLK=0;
NOP3();
Wdate>>=1;
}
EA=1;
}
/***********************************************
读取一个字节
*************************************************/
ucharDS1302ReadByte(void)
{
uchari,temp;
EA=0;
for(i=0;i<8;i++)
{
temp>>=1;
if(DS_IO==1)
{
temp=temp|0x80;
}
DS_SCLK=1;
NOP3();
DS_SCLK=0;
}
EA=1;
return(temp);
}
/**********************************************
对单个地址写相应的数据
***********************************************/
voidWrite1302(ucharaddr,ucharDSdate)
{
DSRST_0;
DS_SCLK=0;
DSRST_1;
DS1302WriteByte(addr);//地址
DS1302WriteByte(DSdate);//数据
DS_SCLK=1;
DSRST_0;
}
/**********************************************
读相应地址的数据
***********************************************/
ucharRead1302(ucharaddr)
{
ucharRdate;
DSRST_0;
DS_SCLK=0;
DSRST_1;
DS1302WriteByte(addr|0x01);
Rdate=DS1302ReadByte();
DS_SCLK=1;
DSRST_0;
return(Rdate);
}
/**********************************************
对多个地址写相应的数据
***********************************************/
voidWrite1302_All(ucharaddr,uchar*p)
{
DSRST_0;
DS_SCLK=0;
DSRST_1;
DS1302WriteByte(addr);//地址
while(*p!
='\0')
{
DS1302WriteByte(*p++);//数据
}
DS_SCLK=1;
DSRST_0;
}
/******************************************
更新数据
******************************************/
update()
{
dispbuf[0]=second%16;
dispbuf[1]=second/16;
dispbuf[2]=16;
dispbuf[3]=minute%16;
dispbuf[4]=minute/16;
dispbuf[5]=16;
dispbuf[6]=hour%16;
dispbuf[7]=hour/16;
}
/******************************************
动态扫描
******************************************/
display()
{
LEDCLK=0;
if(wei==0)
{
LEDDIN=0;
}
else
{
LEDDIN=1;
}
LEDCLK=1;
P0=ledtable[dispbuf[wei]];
LEDCLK=0;
wei++;
if(wei>8)
{
wei=0;
}
}
/******************************************
定时器1中断
******************************************/
voidtime1_int()interrupt3
{
msecond++;
update();
display();
TH1=(65536-data)>>8;
TL1=(65536-data)%256;
}
/******************************************
MCU初始化
******************************************/
init_mcu()
{
TMOD=0x01;
TH1=(65536-data)>>8;
TL1=(65536-data)%256;
ET1=1;TR1=1;
EA=1;
}
/********************************************
DS1302初始化
********************************************/
voidInit_DS1302()
{
Write1302(DS1302_CONTROL,0X00);
}
/******************************************
主函数
******************************************/
main()
{
init_mcu();
Init_DS1302();
while
(1)
{
second=Read1302(DS1302_SECOND);
minute=Read1302(DS1302_MINUTE);
hour=Read1302(DS1302_HOUR);
delay1ms(100);
}
}
实验现象
数码管上显示我们给定的时间,显现如下图
思考题
1、编写程序,设置电源对备用电池充电。
答:
#defineDS1302_DIAODIAN0X90//
。
。
。
。
。
。
Write1302(DS1302_DIAODIAN,0XA5);
。
。
。
。
。
。
2、编写程序,把读到的时间和日期每隔2秒交替显示到数码管上。
答:
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
#definedata1000
sbitLEDCLK=P3^4;
sbitLEDDIN=P2^3;
ucharcodeledtable[]={0x03,0x9F,0x25,0x0D,0x99,0x49,0x41,0x1F,
0x01,0x09,0x11,0xC1,0x63,0x85,0x61,0x71,0xFD};
uchardispbuf[8];
uintmsecond=0;
ucharwei=0;
uchartimebuf[8]={0x00,0x00,0x00};
#definesecondtimebuf[2]
#defineminutetimebuf[1]
#definehourtimebuf[0]
#defineNOP3()_nop_();_nop_();_nop_()
/**DS1302与MCU连接的各端口定义*****************/
sbitDS_IO=P2^0;//DS1302数据口
sbitDS_SCLK=P2^7;//DS1302串行时钟
sbitDS_RST=P2^3;
/**DS1302内部各个寄存器地址定义***********/
#defineDS1302_SECOND0X80//秒
#defineDS1302_MINUTE0X82//分
#defineDS1302_HOUR0X84//时
#defineDS1302_DAY0X86//日
#defineDS1302_MONTH0X88//月
#defineDS1302_WEEK0X8A//星期
#defineDS1302_YEAR0X8C//年
#defineDS1302_CONTROL0X8E//写保护控制位
#defineDS1302_RAM(X)(0XC0+(X)*2)//用于计算DS1302静态RAM地址
#defineDS1302_WRITEALL0XBE
#defineDS1302_READALL0XBF
/************************************************
延时函数
*功能:
可随意设置延时时间,延时时间为ttms.晶振为12MHz
*************************************************/
voiddelay1ms(unsignedinttms)
{
unsignedchari;
while(tms--)
for(i=123;i>0;i--)
;
}
/**********************************************
写入单个字节
**********************************************/
voidDS1302WriteByte(ucharWdate)
{
uchari;
for(i=0;i<8;i++)
{
DS_IO=(bit)(Wdate&0x01);
DS_SCLK=1;
DS_SCLK=0;
NOP3();
Wdate>>=1;
}
}
/***********************************************
读取一个字节
*************************************************/
ucharDS1302ReadByte(void)
{
uchari,temp;
for(i=0;i<8;i++)
{
temp>>=1;
if(DS_IO==1)
{
temp=temp|0x80;
}
DS_SCLK=1;
NOP3();
DS_SCLK=0;
}
return(temp);
}
/**********************************************
对单个地址写相应的数据
***********************************************/
voidWrite1302(ucharaddr,ucharDSdate)
{
DS_RST=0;
DS_SCLK=0;
DS_RST=1;
EA=0;
DS1302WriteByte(addr);//地址
DS1302WriteByte(DSdate);//数据
DS_SCLK=1;
DS_RST=0;
EA=1;
}
/**********************************************
读相应地址的数据
***********************************************/
ucharRead1302(ucharaddr)
{
ucharRdate;
DS_RST=0;
DS_SCLK=0;
DS_RST=1;
EA=0;
DS1302WriteByte(addr|0x01);
Rdate=DS1302ReadByte();
DS_SCLK=1;
DS_RST=0;
EA=1;
return(Rdate);
}
/**********************************************
对多个地址写相应的数据
***********************************************/
voidWrite1302_All(uchar*p)
{
uchari;
DS_RST=0;
DS_SCLK=0;
DS_RST=1;
DS1302WriteByte(DS1302_WRITEALL);//地址
for(i=0;i<8;i++)
{
DS1302WriteByte(*p);
p++;
}
DS_SCLK=1;
DS_RST=0;
}
/******************************************
更新数据
******************************************/
update()
{
dispbuf[0]=second%16;
dispbuf[1]=second/16;
dispbuf[2]=16;
dispbuf[3]=minute%16;
dispbuf[4]=minute/16;
dispbuf[5]=16;
dispbuf[6]=hour%16;
dispbuf[7]=hour/16;
}
/******************************************
动态扫描
******************************************/
display()
{
P0=0XFF;
LEDCLK=0;
if(wei==0)
{
LEDDIN=0;
}
else
{
LEDDIN=1;
}
LEDCLK=1;
P0=ledtable[dispbuf[wei]];
wei++;
if(wei==8)
{
wei=0;
}
}
/******************************************
定时器1中断
******************************************/
voidtime1_int()interrupt3
{
msecond++;
update();
display();
TH1=(65536-data)>>8;
TL1=(65536-data)%256;
}
/******************************************
MCU初始化
******************************************/
init_mcu()
{
TMOD=0x01;
TH1=(65536-data)>>8;
TL1=(65536-data)%256;
ET1=1;TR1=1;
EA=1;
}
/********************************************
DS1302初始化
********************************************/
voidInit_DS1302()
{
DS_RST=0;
DS_SCLK=1;
DS_IO=1;
}
/******************************************
设置时钟芯片时间
*******************************************/
voidSET_DS1302()
{
Write1302(DS1302_CONTROL,0X00);//
//Write1302_All(timebuf);
Write1302(DS1302_SECOND,0X00);//
Write1302(DS1302_MINUTE,0X00);//
Write1302(DS1302_HOUR,0X00);//
W
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 串行口实时时钟实验 串行口 实时 时钟