**
51单片机DS1302实时时钟Proteus仿真显示
学习用51单片机显示实时时间。
用DS1302实时时钟芯片,用来练习很不错,我所编写的程序时间误差较大。刚开始和网络是时间存在微小差距,显示的时间越长,误差越来越大。
这里用LCD1602显示(显示样式参照了网上的历程)。下面有仿真图
如有大神路过,欢迎指导,指出不足。
DS1302.c
#include <reg52.h>
#include "DS1302.h"
#include <intrins.h>
sbit RST = P2^5;
sbit SCLK = P2^6;
sbit IO = P2^7;
void RTC_Initial()
{
RST = 0;
SCLK = 0;
}
/*
写数据
*/
void RTC_Write_Data(uchar Addr,uchar dat)
{
uchar i;
RTC_Initial();
RST = 1;
for(i=0;i<8;i++)
{
SCLK = 0;
if(Addr&0x01) IO = 1;
else IO = 0;
SCLK = 1;
Addr>>=1;
}
for(i=0;i<8;i++)
{
SCLK = 0;
if(dat&0x01) IO = 1;
else IO = 0;
SCLK = 1;
dat>>=1;
}
}
/*
读数据
*/
uchar RTC_Read_Data(uchar Addr)
{
uchar i;
uchar dat;
RTC_Initial();
RST = 1;
for(i=0;i<8;i++)
{
SCLK = 0;
if(Addr&0x01) IO = 1;
else IO = 0;
SCLK = 1;
Addr>>=1;
}
//SCLK = 1;
IO = 1;
/*
上面读取了地址的有效信息
经DS1302 IO发送数据,低-高
*/
for(i=0;i<8;i++)
{
dat >>= 1; //清0
SCLK = 1;
_nop_();
SCLK = 0;
if(IO) dat |= 0x80;//DS1302向C51发送数据
}
return dat;
}
LCD1602.c
#include <reg52.h>
#include <intrins.h>
#include "LCD1602.h"
#define uint unsigned int
#define uchar unsigned char
sbit RS = P2^0;
sbit RW = P2^1;
sbit EN = P2^2;
void LCD_delayMs(uchar ms)
{
int i=0;
while(ms--)
for(i=0;i<160;i++);
}
void LCD1602_Initial()
{
LCD_delayMs(80);
LCD1602_WriteCMD(0x38); //开显示
LCD_delayMs(20);
LCD1602_WriteCMD(0x38);
LCD_delayMs(2);
LCD1602_WriteCMD(0x01); //清屏
LCD_delayMs(10);
LCD1602_WriteCMD(0x0c); //开显示,不显示光标
LCD1602_WriteCMD(0x06); //写一个指针+1
}
void check_busy() //忙检测
{
uchar dt;
do
{
dt=0xff;
EN=0;
RS=0;
RW=1;
EN=1;
dt=P0;
}while(dt&0x80);
EN=0;
}
void LCD1602_WriteCMD(uchar Addr)
{
check_busy();
//LCD_delayMs(10);
RS = 0;
RW = 0;
EN = 0;
P0 = Addr;
EN = 1;
_nop_();
EN = 0;
//RS = 1;
}
void LCD1602_WriteDATA(uchar Data)
{
LCD_delayMs(1);
RS = 1;
RW = 0;
EN = 0;
P0 = Data;
EN = 1;
_nop_();
EN = 0;
//RS = 0;
}
/********************************************
0 1 2 3 4 ... 15
----------------------------->x
0 |
1 |
y V
********************************************/
void LCD1602_Display(uchar x,uchar y,uchar dat)
{
uchar addr;
addr = y?(0xC0+x):(0x80+x);
LCD1602_WriteCMD(addr);
LCD1602_WriteDATA(dat);
}
/*---------------显示字符串----------*/
void Show_String(char *temp)
{
while((*temp)!='\0')
{
LCD1602_WriteDATA(*temp);
temp++;
}
}
Main文件
#include <reg52.h>
#include "LCD1602.h"
#include "DS1302.h"
#define uint unsigned int
#define uchar unsigned char
#define u8 unsigned char
void RTC_setTime(u8 sec,u8 min,u8 hrs,u8 date,u8 month,u8 year);
void RTC_readTime();
void Save_read_Time();
void Display_Date();
char code line1[16]={"Date:20__-__-__"};
char code line2[16]={"Time: __:__:__"};
uchar Div[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0};
struct Time {
uchar secData;
uchar minData;
uchar hrsData;
uchar dateData;
uchar monthData;
uchar yearData;
//uchar dayData;
}Clock;
void main()
{
LCD1602_Initial();
RTC_Initial();
RTC_setTime(0x55,0x59,0x23,0x30,0x06,0x18);
LCD1602_WriteCMD(0x80);
Show_String(line1);
LCD1602_WriteCMD(0xc0);
Show_String(line2);
while(1)
{
RTC_readTime();
Save_read_Time();
Display_Date();
}
}
/*向RTC寄存器写入数据
设置时间如:RTC_setTime(0x55,0x59,0x23,0x30,0x06,0x18,0x07)*/
void RTC_setTime(u8 sec,u8 min,u8 hrs,u8 date,u8 month,u8 year)//,u8 day)
{
RTC_Write_Data(0x8e,0x00);
RTC_Write_Data(RTC_Write_secAddr, sec);
RTC_Write_Data(RTC_Write_minAddr, min);
RTC_Write_Data(RTC_Write_hrsAddr, hrs);
RTC_Write_Data(RTC_Write_dateAddr, date);
RTC_Write_Data(RTC_Write_monthAddr, month);
RTC_Write_Data(RTC_Write_yearAddr, year);
//RTC_Write_Data(RTC_Write_dayAddr, day);
RTC_Write_Data(0x8e,0x80);
}
/*读取RTC内部寄存器数据*/
void RTC_readTime()
{
Clock.secData = RTC_Read_Data(RTC_Read_secAddr);
Clock.minData = RTC_Read_Data(RTC_Read_minAddr);
Clock.hrsData = RTC_Read_Data(RTC_Read_hrsAddr);
Clock.dateData = RTC_Read_Data(RTC_Read_dateAddr);
Clock.monthData = RTC_Read_Data(RTC_Read_monthAddr);
Clock.yearData = RTC_Read_Data(RTC_Read_yearAddr);
//Clock.dayData = RTC_Read_Data(RTC_Read_dayAddr);
}
void Save_read_Time()
{
Div[1] = (Clock.secData&0x70)>>4;
Div[0] = Clock.secData&0x0f;
Div[3] = (Clock.minData&0x70)>>4;
Div[2] = Clock.minData&0x0f;
Div[5] = (Clock.hrsData&0x30)>>4;
Div[4] = Clock.hrsData&0x0f;
/*-----------------------------*/
Div[7] = (Clock.dateData&0x30)>>4;
Div[6] = Clock.dateData&0x0f;
Div[9] = (Clock.monthData&0x10)>>4;
Div[8] = Clock.monthData&0x0f;
Div[11] = (Clock.yearData&0xf0)>>4;
Div[10] = Clock.yearData&0x0f;
// Div[13] = (Clock.dayData&0x00)>>4;
// Div[12] = Clock.dayData&0x07;
}
void Display_Date()
{
LCD1602_Display(7,0,Div[11]+'0'); //year
LCD1602_Display(8,0,Div[10]+'0');
LCD1602_Display(10,0,Div[9]+'0'); //month
LCD1602_Display(11,0,Div[8]+'0');
LCD1602_Display(13,0,Div[7]+'0'); //date
LCD1602_Display(14,0,Div[6]+'0');
/*----------------------------*/
LCD1602_Display(6,1,Div[5]+'0'); //hrs
LCD1602_Display(7,1,Div[4]+'0');
LCD1602_Display(9,1,Div[3]+'0'); //minute
LCD1602_Display(10,1,Div[2]+'0');
LCD1602_Display(12,1,Div[1]+'0'); //second
LCD1602_Display(13,1,Div[0]+'0');
}