13 实时时钟.docx
《13 实时时钟.docx》由会员分享,可在线阅读,更多相关《13 实时时钟.docx(17页珍藏版)》请在冰豆网上搜索。
![13 实时时钟.docx](https://file1.bdocx.com/fileroot1/2023-7/27/abd6473a-bc93-4dd8-bde7-d82cdba717e9/abd6473a-bc93-4dd8-bde7-d82cdba717e91.gif)
13实时时钟
重庆理工大学
实验报告
题目:
DS1302实时时钟
二级学院计算机科学与工程
专业计算机科学与技术
班级113030701
学生姓名刘勇学号11303070134
教师刘小洋
时间2014-3-25
目录
一实验名称
二实验目的
三实验设备与环境
四实验基本原理
五实验内容(包括主要算法分析与流程图)
六实验运行结果及分析
七实验心得体会
一实验名称
DS1302实时时钟
二实4验目的
DS时钟芯片包括实时时钟/日历,提供秒、分、时、日、周、月和年等信息
用LCD1602显示从DS1302读出的年、月、日、星期、时、分、秒的实时值
同时按下K1和K4键将由程序预设的日期和时间数据写入DS1302芯片内
三实验设备与环境
实验芯片(AT89S52)
ME850单片机开发实验仪
USB通讯线
串口通讯线
四实验基本原理
将JP24的ON端短接,使LCD1602使能
将JP25背光短接子短接,使LCD1602的背光灯点亮
将JP18短接子短接,使芯片管脚与P1.0~P1.2端口接通
五实验内容(包括主要算法分析与流程图)
#include
#include
//#defineucharunsignedchar
//#defineuintunsignedint
sbitLCD_RS=P2^0;
sbitLCD_RW=P2^1;
sbitLCD_EN=P2^2;
sbitK1=P1^4;
sbitK2=P1^5;
sbitK3=P1^6;
sbitK4=P1^7;
sbitreset=P1^2;//DS1302
sbitsclk=P1^0;
sbitio=P1^1;
sbitBEEP=P3^7;
unsignedcharstr1[]="--Week:
";
unsignedcharstr2[]="Time:
:
:
";
unsignedcharinit[]=
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
unsignedcharinit1[]=
{
0x00,0x00,0x20,0x08,0x08,0x05,0x08
};
//秒,分,时,日,月,星期,年
charcodereserve[3]_at_0x3b;//保留0x3b开始的3个字节
/*********************************************************
us延时子函数(4.34us)
*********************************************************/
voiddelayNOP()
{
_nop_();
_nop_();
_nop_();
_nop_();
}
/*********************************************************
ms延时子函数
*********************************************************/
voiddelayms(unsignedintms)
{
unsignedchary;
while(ms--)
{
for(y=0;y<114;y++)
;
}
}
/**********************************************************
x*0.14MS延时子函数
**********************************************************/
voiddelayus(unsignedcharx)
{
unsignedchari;
while(x--)
{
for(i=0;i<14;i++)
{
;
}
}
}
/**********************************************************
蜂鸣器驱动子函数
**********************************************************/
voidbeep()
{
unsignedchary;
for(y=0;y<180;y++)
{
delayus(6);
BEEP=!
BEEP;//BEEP取反
}
BEEP=1;//关闭蜂鸣器
delayms(150);
}
/**********************************************************
检查LCD忙状态
lcd_busy为1时,忙,等待。
lcd-busy为0时,闲,可写指令与数据。
***********************************************************/
unsignedcharlcd_busy()
{
bitresult;
LCD_RS=0;
LCD_RW=1;
LCD_EN=1;
delayNOP();
result=(bit)(P0&0x80);
LCD_EN=0;
return(result);
}
/**********************************************************
写指令数据到LCD
RS=L,RW=L,E=高脉冲,D0-D7=指令码。
**********************************************************/
voidlcd_wcmd(unsignedcharcmd)
{
while(lcd_busy())
;
LCD_RS=0;
LCD_RW=0;
LCD_EN=0;
_nop_();
_nop_();
P0=cmd;
delayNOP();
LCD_EN=1;
delayNOP();
LCD_EN=0;
}
/**********************************************************
写显示数据到LCD
RS=H,RW=L,E=高脉冲,D0-D7=数据。
**********************************************************/
voidlcd_wdat(unsignedchardat)
{
while(lcd_busy())
;
LCD_RS=1;
LCD_RW=0;
LCD_EN=0;
P0=dat;
delayNOP();
LCD_EN=1;
delayNOP();
LCD_EN=0;
}
/**********************************************************
LCD初始化设定
**********************************************************/
voidlcd_init()
{
delayms(50);//延时等待上电稳定
lcd_wcmd(0x38);//16*2显示,5*7点阵,8位数据
delayms(5);
lcd_wcmd(0x38);
delayms(5);
lcd_wcmd(0x38);
delayms(5);
lcd_wcmd(0x0c);//显示开,关光标
delayms(5);
lcd_wcmd(0x06);//移动光标
delayms(5);
lcd_wcmd(0x01);//清除LCD的显示内容
delayms(5);
}
/**********************************************************
写字符串函数
**********************************************************/
voidwrite_str(unsignedcharaddr,unsignedchar*p)
{
unsignedchari=0;
lcd_wcmd(addr);
while(p[i]!
='\0')
{
lcd_wdat(p[i]);
i++;
}
}
/**********************************************************
设定显示位置
row取值为1-2col取值为1-16
**********************************************************/
voidwrite_position(unsignedcharrow,unsignedcharcol)
{
unsignedcharplace;
if(row==1)
{
place=0x80+col-1;
lcd_wcmd(place);
}
if(row==2)
{
place=0xc0+col-1;
lcd_wcmd(place);
}
}
/**********************************************************
DS1302写字节子函数
**********************************************************/
voidwrite_byte(unsignedcharinbyte)
{
unsignedchari;
for(i=0;i<8;i++)
{
sclk=0;
delayNOP();
inbyte=inbyte>>1;//右移一位,最低位移入CY
io=CY;//写入CY
sclk=1;
delayNOP();
}
}
/**********************************************************
DS1302读字节子函数
**********************************************************/
unsignedcharread_byte()
{
unsignedchari,temp=0;
io=1;//设置为输入口
for(i=0;i<8;i++)
{
sclk=0;
delayNOP();
temp=temp>>1;//右移一位,最高位补"0"
if(io==1)
//读
temp=temp|0x80;
//最高位补"1"
sclk=1;
delayNOP();
}
return(temp);
}
/**********************************************************
往ds1302的某个地址写入数据
**********************************************************/
voidwrite_ds1302(unsignedcharcmd,unsignedcharindata)
{
reset=0;
delayNOP();
sclk=0;//为低电平时
delayNOP();
reset=1;//才能置为高电平
delayNOP();
write_byte(cmd);//先写地址
write_byte(indata);//然后再写数据
sclk=1;
reset=0;
}
/**********************************************************
读ds1302某地址的的数据
**********************************************************/
unsignedcharread_ds1302(unsignedcharaddr)
{
unsignedcharbackdata;
reset=0;
delayNOP();
sclk=0;//为低电平时
delayNOP();
reset=1;//才能置为高电平
delayNOP();
write_byte(addr);//先写地址
backdata=read_byte();//然后再读数据
sclk=1;
reset=0;
return(backdata);
}
/**********************************************************
写入初始时间子函数
**********************************************************/
voidset_ds1302(unsignedcharaddr,unsignedchar*p,unsignedcharn)
//写入n个数据
{
write_ds1302(0x8e,0x00);//写控制字,允许写操作
for(;n>0;n--)
{
write_ds1302(addr,*p);
p++;
addr=addr+2;
}
write_ds1302(0x8e,0x80);//写保护,不允许写
}
/**********************************************************
读取当前时间子函数
**********************************************************/
voidread_nowtime(unsignedcharaddr,unsignedchar*p,unsignedcharn)
{
for(;n>0;n--)
{
*p=read_ds1302(addr);
p++;
addr=addr+2;
}
}
/**********************************************************
DS1302初始化
**********************************************************/
voidinit_ds1302()
{
reset=0;
sclk=0;
write_ds1302(0x8e,0x00);//写控制字,允许写操作
write_ds1302(0x80,0x00);//时钟启动
write_ds1302(0x90,0xa6);//一个二极管+4K电阻充电
write_ds1302(0x8e,0x80);//写控制字,禁止写操作
}
/**********************************************************
显示当前时间
**********************************************************/
voidPlay_nowtime()
{
read_nowtime(0x81,init,7);//读出当前时间,读出7个字节
write_position(2,7);
lcd_wdat(((init[2]&0xf0)>>4)+0x30);//时
lcd_wdat((init[2]&0x0f)+0x30);
write_position(2,10);
lcd_wdat(((init[1]&0xf0)>>4)+0x30);//分
lcd_wdat((init[1]&0x0f)+0x30);
write_position(2,13);
lcd_wdat(((init[0]&0x70)>>4)+0x30);//秒
lcd_wdat((init[0]&0x0f)+0x30);
write_position(1,1);//年
lcd_wdat(((init[6]&0xf0)>>4)+0x30);
lcd_wdat((init[6]&0x0f)+0x30);
write_position(1,4);
lcd_wdat(((init[4]&0xf0)>>4)+0x30);//月
lcd_wdat((init[4]&0x0f)+0x30);
write_position(1,7);
lcd_wdat(((init[3]&0xf0)>>4)+0x30);//日
lcd_wdat((init[3]&0x0f)+0x30);
write_position(1,15);
lcd_wdat((init[5]&0x0f)+0x30);//周
}
/**********************************************************
主函数
**********************************************************/
voidmain(void)
{
P0=0xff;//端口初始化
P1=0xff;
P2=0xff;
lcd_init();//初始化LCD
write_str(0x80,str1);//液晶显示字符串
write_str(0xc0,str2);//液晶显示字符串
init_ds1302();//初始化ds1302
while
(1)
{
if((K1|K4)==0)
//K1和K4键同时按下?
{
delayms(20);//延时20ms
if((K1|K4)==0)
//K1和K4键同时按下?
{
set_ds1302(0x80,init1,7);//写入初始值
beep();
}
}
delayms(100);//100ms更新一次数据
Play_nowtime();
}
}
/*********************************************************/
2、流程图
六实验运行结果及分析
与预期的结果相符。
七实验心得体会
同过这次试验,对于单片机的实验原理有了更加深的理解。
虽然途中遇到一些不懂的知识点以及程序错误,只要我们认真观察,不断努力,相信我们的能力必定得到提升。