导航:首页 > 数据处理 > ds1307时钟读出来的数据怎么处理

ds1307时钟读出来的数据怎么处理

发布时间:2022-09-11 23:41:58

㈠ DS1307时钟变慢要怎么解决

更换精度更高的晶体,DS1307走时快慢只和晶体的频率有关系

㈡ 如何读出DS1302里面的时钟数据

#include <REG51.H>
#include <intrins.h>
//#include "LCD1602.h"
//#include "DS1302.h"
#define uint unsigned int
#define uchar unsigned char
sbit DS1302_CLK = P1^7; //实时时钟时钟线引脚
sbit DS1302_IO = P1^6; //实时时钟数据线引脚
sbit DS1302_RST = P1^5; //实时时钟复位线引脚
sbit wireless_1 = P3^0;
sbit wireless_2 = P3^1;
sbit wireless_3 = P3^2;
sbit wireless_4 = P3^3;
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数
sbit Set = P2^0; //模式切换键
sbit Up = P2^1; //加法按钮
sbit Down = P2^2; //减法按钮
sbit out = P2^3; //立刻跳出调整模式按钮
char done,count,temp,flag,up_flag,down_flag;
uchar TempBuffer[5],week_value[2];

/***********DS1302时钟部分子程序******************/
typedef struct __SYSTEMTIME__
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char DateString[11];
unsigned char TimeString[9];
}SYSTEMTIME; //定义的时间类型
SYSTEMTIME CurrentTime;

#define AM(X) X
#define PM(X) (X+12) // 转成24小时制
#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8C

void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数)
{
unsigned char i;
ACC = d;
for(i=8; i>0; i--)
{
DS1302_IO = ACC0; //相当于汇编中的 RRC
DS1302_CLK = 1;
DS1302_CLK = 0;
ACC = ACC >> 1;
}
}

unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数)
{
unsigned char i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; //相当于汇编中的 RRC
ACC7 = DS1302_IO;
DS1302_CLK = 1;
DS1302_CLK = 0;
}
return(ACC);
}

void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据
{
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr); // 地址,命令
DS1302InputByte(ucDa); // 写1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
}

unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据
{
unsigned char ucData;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr|0x01); // 地址,命令
ucData = DS1302OutputByte(); // 读1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
return(ucData);
}

void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组
{
unsigned char ReadValue;
ReadValue = Read1302(DS1302_SECOND);
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MINUTE);
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_HOUR);
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_DAY);
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_WEEK);
Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MONTH);
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_YEAR);
Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
}

void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]
{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22
{
Time->DateString[0] = '2';
Time->DateString[1] = '0';
Time->DateString[2] = Time->Year/10 + '0';
Time->DateString[3] = Time->Year%10 + '0';
}
else
{
Time->DateString[0] = ' ';
Time->DateString[1] = ' ';
Time->DateString[2] = ' ';
Time->DateString[3] = ' ';
}
Time->DateString[4] = '/';
if(hide_month<2)
{
Time->DateString[5] = Time->Month/10 + '0';
Time->DateString[6] = Time->Month%10 + '0';
}
else
{
Time->DateString[5] = ' ';
Time->DateString[6] = ' ';
}
Time->DateString[7] = '/';
if(hide_day<2)
{
Time->DateString[8] = Time->Day/10 + '0';
Time->DateString[9] = Time->Day%10 + '0';
}
else
{
Time->DateString[8] = ' ';
Time->DateString[9] = ' ';
}
if(hide_week<2)
{
week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示
}
else
{
week_value[0] = ' ';
}
week_value[1] = '\0';

Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判断结束字符
}

void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];
{ if(hide_hour<2)
{
Time->TimeString[0] = Time->Hour/10 + '0';
Time->TimeString[1] = Time->Hour%10 + '0';
}
else
{
Time->TimeString[0] = ' ';
Time->TimeString[1] = ' ';
}
Time->TimeString[2] = ':';
if(hide_min<2)
{
Time->TimeString[3] = Time->Minute/10 + '0';
Time->TimeString[4] = Time->Minute%10 + '0';
}
else
{
Time->TimeString[3] = ' ';
Time->TimeString[4] = ' ';
}
Time->TimeString[5] = ':';
if(hide_sec<2)
{
Time->TimeString[6] = Time->Second/10 + '0';
Time->TimeString[7] = Time->Second%10 + '0';
}
else
{
Time->TimeString[6] = ' ';
Time->TimeString[7] = ' ';
}
Time->DateString[8] = '\0';
}

void Initial_DS1302(void) //时钟芯片初始化
{
unsigned char Second="Read1302"(DS1302_SECOND);
if(Second&0x80) //判断时钟芯片是否关闭
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x8c,0x07); //以下写入初始化时间 日期:07/07/25.星期: 3. 时间: 23:59:55
Write1302(0x88,0x07);
Write1302(0x86,0x25);
Write1302(0x8a,0x07);
Write1302(0x84,0x23);
Write1302(0x82,0x59);
Write1302(0x80,0x55);
Write1302(0x8e,0x80); //禁止写入
}

}

void Upkey()//升序按键
{
Up=1;
if(Up==0||wireless_2==1)
{
mdelay(8);
switch(count)
{case 1:
temp="Read1302"(DS1302_SECOND); //读取秒数
temp="temp"+1; //秒数加1
up_flag=1; //数据调整后更新标志
if((temp&0x7f)>0x59) //超过59秒,清零
temp="0";
break;
case 2:
temp="Read1302"(DS1302_MINUTE); //读取分数
temp="temp"+1; //分数加1
up_flag=1;
if(temp>0x59) //超过59分,清零
temp="0";
break;
case 3:
temp="Read1302"(DS1302_HOUR); //读取小时数
temp="temp"+1; //小时数加1
up_flag=1;
if(temp>0x23) //超过23小时,清零
temp="0";
break;
case 4:
temp="Read1302"(DS1302_WEEK); //读取星期数
temp="temp"+1; //星期数加1
up_flag=1;
if(temp>0x7)
temp="1";
break;
case 5:
temp="Read1302"(DS1302_DAY); //读取日数
temp="temp"+1; //日数加1
up_flag=1;
if(temp>0x31)
temp="1";
break;
case 6:
temp="Read1302"(DS1302_MONTH); //读取月数
temp="temp"+1; //月数加1
up_flag=1;
if(temp>0x12)
temp="1";
break;
case 7:
temp="Read1302"(DS1302_YEAR); //读取年数
temp="temp"+1; //年数加1
up_flag=1;
if(temp>0x85)
temp="0";
break;
default:break;
}

while(Up==0);
while(wireless_2==1);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Downkey()//降序按键
{
Down=1;
if(Down==0||wireless_3==1)
{
mdelay(8);
switch(count)
{case 1:
temp="Read1302"(DS1302_SECOND); //读取秒数
temp="temp-1"; //秒数减1
down_flag=1; //数据调整后更新标志
if(temp==0x7f) //小于0秒,返回59秒
temp="0x59";
break;
case 2:
temp="Read1302"(DS1302_MINUTE); //读取分数
temp="temp-1"; //分数减1
down_flag=1;
if(temp==-1)
temp="0x59"; //小于0秒,返回59秒
break;
case 3:
temp="Read1302"(DS1302_HOUR); //读取小时数
temp="temp-1"; //小时数减1
down_flag=1;
if(temp==-1)
temp="0x23";
break;
case 4:
temp="Read1302"(DS1302_WEEK); //读取星期数
temp="temp-1"; //星期数减1
down_flag=1;
if(temp==0)
temp="0x7";;
break;
case 5:
temp="Read1302"(DS1302_DAY); //读取日数
temp="temp-1"; //日数减1
down_flag=1;
if(temp==0)
temp="31";
break;
case 6:
temp="Read1302"(DS1302_MONTH); //读取月数
temp="temp-1"; //月数减1
down_flag=1;
if(temp==0)
temp="12";
break;
case 7:
temp="Read1302"(DS1302_YEAR); //读取年数
temp="temp-1"; //年数减1
down_flag=1;
if(temp==-1)
temp="0x85";
break;
default:break;
}

while(Down==0);
while(wireless_3==1);
}
}

void Setkey()//模式选择按键
{
Set=1;
if(Set==0||wireless_4==1)
{
mdelay(8);
count="count"+1; //Setkey按一次,count就加1
done="1"; //进入调整模式
while(Set==0);
while(wireless_4==1);
}

}

void keydone()//按键功能执行
{ uchar Second;
if(flag==0) //关闭时钟,停止计时
{ Write1302(0x8e,0x00); //写入允许
temp="Read1302"(0x80);
Write1302(0x80,temp|0x80);
Write1302(0x8e,0x80); //禁止写入
flag="1";
}
Setkey(); //扫描模式切换按键
switch(count)
{case 1:do //count=1,调整秒
{
outkey(); //扫描跳出按钮
Upkey(); //扫描加按钮
Downkey(); //扫描减按钮
if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x80,temp|0x80); //写入新的秒数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}

hide_sec++; //位闪计数
if(hide_sec>3)
hide_sec=0;
show_time(); //液晶显示数据
}while(count==2);break;
case 2:do //count=2,调整分
{
hide_sec=0;
outkey();
Upkey();
Downkey();
if(temp>0x60)
temp="0";
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x82,temp); //写入新的分数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_min++;
if(hide_min>3)
hide_min=0;
show_time();
}while(count==3);break;
case 3:do //count=3,调整小时
{
hide_min=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x84,temp); //写入新的小时数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_hour++;
if(hide_hour>3)
hide_hour=0;
show_time();
}while(count==4);break;
case 4:do //count=4,调整星期
{
hide_hour=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x8a,temp); //写入新的星期数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_week++;
if(hide_week>3)
hide_week=0;
show_time();
}while(count==5);break;
case 5:do //count=5,调整日
{
hide_week=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x86,temp); //写入新的日数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_day++;
if(hide_day>3)
hide_day=0;
show_time();
}while(count==6);break;
case 6:do //count=6,调整月
{
hide_day=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x88,temp); //写入新的月数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_month++;
if(hide_month>3)
hide_month=0;
show_time();
}while(count==7);break;
case 7:do //count=7,调整年
{
hide_month=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x8c,temp); //写入新的年数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_year++;
if(hide_year>3)
hide_year=0;
show_time();
}while(count==8);break;
case 8: count="0";hide_year=0; //count8, 跳出调整模式,返回默认显示状态
Second="Read1302"(DS1302_SECOND);
Write1302(0x8e,0x00); //写入允许
Write1302(0x80,Second&0x7f);
Write1302(0x8E,0x80); //禁止写入
done="0";
break; //count=7,开启中断,标志位置0并退出
default:break;

}

}

㈢ 谁会读写DS1307,并显示到1602上

/******************************************************************************************************************************/
/* smally 2008.5.20 南阳师范学院*/

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcdrs=P2^7;
sbit lcden=P2^6;
sbit rtscl=P2^1;
sbit rtsda=P2^2;
sbit da_18b20=P2^0;
uchar code table[]="0123456789";
uchar table1[8];
uchar convert_begin;
uint t_click,tp;
//*****************************************/
//1602操作相关函数
//*****************************************/
void wait() //上电后延时操作,等待各芯片准备好 //avoid error
{
uint i=60000;
while(i>0)i--;
}
void delay() // 操作之间的时间间隔
{
uchar i=200;
while(i>0)i--;
}
void write_com(uchar com) //写命令到1602
{
lcdrs=0;
P0=com;
lcden=1;
delay();
lcden=0;
}
void write_dat(uchar dat) //写数据到1602
{
lcdrs=1;
P0=dat;
lcden=1;
delay();
lcden=0;
}

void init_1602() //初始化1602
{
lcden=0;
write_com(0x01);delay();
write_com(0x80);delay();
write_com(0x38);delay();
write_com(0x0c);delay();
write_com(0x06);delay();
}
//**********************************************
//over
//**********************************************

//********************************************/
//ds1307相关操作函数//传送与接收数据都是先高位
//********************************************/
void rt_delay() //操作延时,等待信号稳定
{
uchar i=10;
while(i>0)i--;
}
void init_1307() //初始化1307
{
rtscl = 1; rt_delay(); rtsda = 1; rt_delay();
}
void start_1307() // 开始信号
{
rtsda = 1; rtscl = 1; rt_delay(); rtsda = 0; rt_delay();
}
void stop_1307() // 结束信号
{
rtsda = 0; rtscl = 1; rt_delay(); rtsda = 1; rt_delay();
}
void write_1307(uchar d ) //写1307
{
uchar i,j; rtscl = 0;
for(i = 0;i < 8; i++)
{
rtsda = (d >> 7);
rtscl = 1;
rt_delay();
d = d << 1;
rtscl = 0;
}
rtsda = 1;
rtscl = 1;
while((rtsda == 1) && (j < 255))j++;
rtscl=0;
}
uchar read_1307(uchar b) //读1307
{
uchar d ,i;
rtsda = 1; rtscl = 0;
for(i = 0; i < 8; i++)
{
rtscl = 1;
rt_delay();
d = d << 1;
d = d | rtsda;
rtscl=0;
}
rtsda = b;
rt_delay();
rtscl = 0;
rtscl = 1;
return d;
}
read_8byte_1307()
{
uchar i;
start_1307( );
write_1307( 0xd0 );
write_1307( 0x00 );
stop_1307( );
for(i = 0;i < 8; i++)
{
start_1307();
write_1307(0xd1);
table1[i]=read_1307(1);
stop_1307();
}
}
//**********************************************
//over
//**********************************************

//**********************************************
//18b20操作相关函数
//**********************************************
void reset_time_18b20() //延时640us
{
uint i;
i=80;
while(i>0)i--;
}

void wrbyte(uchar b) //写一个字节
{
uchar i,j;
bit btmp;
for(j=1;j<=8;j++)
{
btmp=b&0x01;
b=b>>1;
if(btmp)
{
da_18b20=0;
i++;i++;
da_18b20=1;
i=40; //写1时,15us内拉高数据线,总时间时隙不低于60us
while(i>0)i--;
}
else
{
da_18b20=0;
i=40; //写0时,拉低至少60us
while(i>0)i--;
da_18b20=1;
}
}
}

bit rdbit() //读取18b20的一位
{
uchar i;
uchar b;
da_18b20=0;
i++;i++;i++;i++;i++;
da_18b20=1;
i=10; //上升沿15us后读有效
while(i>0)i--;
b=da_18b20;
i=30;
while(i>0)i--; ///总时间不低于60us
return(b);
}

uchar rdbyte() //读取18b20的一字节
{
uchar i,j,byte;

for(i=1;i<=8;i++)
{
j=rdbit();
byte=(j<<7)|(byte>>1);
}

return(byte);
}

uchar init_18b20() //初始化18b20
{
uint j=0;
da_18b20=0;
reset_time_18b20();
da_18b20=1;
while((da_18b20==1)&&(j<250))j++;
if(da_18b20) return 0;
else
{
while(!da_18b20);
return 1;
}
}

void restore()
{
if(t_click==0)
{
if(init_18b20())
{
ET0=0;
while(ET0); //////////操作命令时关闭中断,以免影响时序
wrbyte(0xcc);//////////skip rom命令
wrbyte(0x44);//////////convert 命令
ET0=1; //////////操作命令后再打开中断
convert_begin=1;
}
}
}

void read_18b20()
{
uchar tplsb,tpmsb;
if(t_click>100)
{
convert_begin=0;t_click=0;
if(init_18b20())
{
ET0=0;
while(ET0); //////////操作命令时关闭中断,以免影响时序
wrbyte(0xcc);//////////skip rom命令
wrbyte(0xbe);//////////读暂存器
tplsb=rdbyte();
tpmsb=rdbyte();
ET0=1; //////////操作命令后再打开中断
tp=tpmsb*256+tplsb;
}
}
}
//**********************************************
//over
//**********************************************

//**********************************************
//1602显示函数
//**********************************************

void display()
{
uint nian;
write_com(0x80);delay();
write_dat('D');delay();write_dat('a');delay();
write_dat('t');delay();write_dat(':');delay();
//显示日期信息
nian=table1[7]/16*10+table1[7]%16;
write_dat('2');delay();
write_dat(table[(table1[6]/100)]);delay();
write_dat(table[(table1[6]%100/10)]);delay();
write_dat(table[(table1[6]%10)]);delay();
//间隔符号'-'
write_dat('-');delay();
//显示月份
write_dat(table[table1[5]/16%2]);delay();
write_dat(table[table1[5]%16]);delay();
//间隔符号'-'
write_dat('-');delay();
//显示日期
write_dat(table[table1[4]/16%4]);delay();
write_dat(table[table1[4]%16]);delay();
//星期
write_dat(' ');delay();
write_dat(table[table1[3]%16]);delay();
//LCD第二行
write_com(0x80+0x40);delay();
write_dat('T');delay();write_dat('i');delay();
write_dat('m');delay();write_dat(':');delay();
//显示小时
write_dat(table[table1[2]/16%4]);delay();
write_dat(table[table1[2]%16]);delay();
//间隔符号'-'
write_dat('-');delay();
//显示分钟
write_dat(table[table1[1]/16%8]);delay();
write_dat(table[table1[1]%16]);delay();
//间隔符号'-'
write_dat('-');delay();
//显示秒
write_dat(table[table1[0]/16%8]);delay();
write_dat(table[table1[0]%16]);delay();
//显示温度
write_dat(' ');delay();
if((tp>>11)==0)
{write_dat('+');delay();
write_dat(table[(tp>>4)/10]);delay();
write_dat(table[(tp>>4)%10]);delay();
}
else
{write_dat('-');delay();
write_dat(table[((~(tp-1))>>4)/10]);delay();
write_dat(table[((~(tp-1))>>4)%10]);delay();
}

}

//**********************************************
//over
//**********************************************

//**********************************************

//main主函数

//**********************************************
void main()
{
TMOD=0x01;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256; //定时器初始化
EA=1;
ET0=1;
TR0=1;

wait(); //上电前预热
init_1602();
init_1307();
if(init_18b20())
{
ET0=0;
while(ET0); //////////操作命令时关闭中断,以免影响时序
wrbyte(0xcc);//////////skip rom命令
wrbyte(0x4E);//////////写暂存器命令
wrbyte(0x01);//////////设置上限温度
wrbyte(0x00);//////////设置下限温度
wrbyte(0x1f);//////////设置分辨率TM/R1/R0/1/1/1/1/1
wrbyte(0x43);//////////复制暂存器
ET0=1; //////////操作命令后再打开中断

}
start_1307();
write_1307(0xd0);
write_1307(0x00);
write_1307(0x00);
write_1307(0x59);
write_1307(0x12);
write_1307(0x05);
write_1307(0x03);
write_1307(0x07);
write_1307(0x09);
stop_1307();
while(1)
{
restore();
read_18b20();
read_8byte_1307();
display();
}
}

//****************************************************************

//over

//***************************************************************

//***************************************************************

//中断服务子程序

//***************************************************************

void time0() interrupt 1 using 1
{
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
if(convert_begin)t_click++;
}
//****************************************************************

//over

//****************************************************************

//**********************************************that's alll*******************************************************************//

㈣ 单片机 DS1302时钟读写问题

uchar read_Byte()
{
uchar i;
for(i = 8;i > 0;i--)
{
ACC = ACC >> 1;
ACC7 = ds1302_IO;
ds1302_SCLK = 1;
ds1302_SCLK = 0;
}
return(ACC);
}

是的,你要相信自己,然后多实践,网上的东西只做一个参考,对不对还要由你自己来验证。

㈤ 树莓派基础实验32:DS1302实时时钟模块实验

  现在有很多流行的串行时钟芯片,如DS1302,DS1307,PCF8485等,由于简单的接口,低成本和易用性,他们被广泛应用于电话、传真、便携式仪器等产品领域。在本实验中,我们将使用DS1302实时时钟(RTC)模块获取当前日期和时间。

  DS1302可以用于数据记录,特别是对某些具有特殊意义的数据点的记录,能实现数据与出现该数据的时间同时记录。这种记录对长时间的连续测控系统结果的分析,及对异常数据出现的原因的查找具有重要意义。

  传统的数据记录方式是隔时采样或定时采样,没有具体的时间记录,因此,只能记录数据而无法准确记录其出现的时间;若采用单片机计时,一方面需要采用计数器,占用硬件资源,另一方面需要设置中断、查询等,同样耗费单片机的资源,而且,某些测控系统可能不允许。但是,如果在系统中采用时钟芯片DS1302,则能很好地解决这个问题。

★Raspberry Pi 3主板*1

★树莓派电源*1

★40P软排线*1

★DS1302实时时钟模块*1

★面包板*1

★跳线若干

  DS1302是DALLAS(达拉斯)公司出的一款涓流充电时钟芯片,2001年DALLAS被MAXIM(美信)收购。
  DS1302实时时钟芯片广泛应用于电话、传真、便携式仪器等产品领域,他的主要性能指标如下:
  1、DS1302是一个实时时钟芯片,可以提供秒、分、小时、日期、月、年等信息,并且还有软年自动调整的能力,可以通过配置AM/PM来决定采用24小时格式还是12小时格式。
  2、拥有31字节数据存储RAM。
  3、串行I/O通信方式,相对并行来说比较节省IO口的使用。
  4、DS1302的工作电压比较宽,大概是2.0V~5.5V都可以正常工作。
  5、DS1302这种时钟芯片功耗一般都很低,它在工作电压2.0V的时候,工作电流小于300nA。
  6、DS1302共有8个引脚,有两种封装形式,一种是DIP-8封装,芯片宽度(不含引脚)是300mil,一种是SOP-8封装,有两 种宽度,一种是150mil,一种是208mil。我们看一下DS1302的引脚封装图:

  7、当供电电压是5V的时候,兼容标准的TTL电平标准,这里的意思是,可以完美的和单片机进行通信。
   8、由于DS1302是DS1202的升级版本,所以所有的功能都兼容DS1202。此外DS1302有两个电源输入,一个是主电源, 另外一个是备用电源,比如可以用电池或者大电容,这样是为了保证系统掉电的情况下,我们的时钟还会继续走。如果使用的是充电电池,还可以在正常工作时,设置充电功能,给我们的备用电池进行充电。

  DS1302的特点第二条“拥有31字节数据存储RAM”,这是DS1302额外存在的资源。这31字节的RAM相当于一个存储器一样,我们编写单片机程序的时候,可以把我们想存储的数据存储在DS1302里边,需要的时候读出来,这块功能和EEPROM有点类似,相当于一个掉电丢失数据的“EEPROM”,如果我们的时钟电路加上备用电池,那么这31个字节的RAM就可以替代EEPROM的功能了。

  DS1302一共有8个引脚,下边要根据引脚分布图和典型电路图来介绍一下每个引脚的功能:

  DS1302的电路一个重点就是时钟电路,它所使用的晶振是一个32.768k的晶振,晶振外部也不需要额外添加其他的电容或者电阻电路了。时钟的精度,首先取决于晶振的精度以及晶振的引脚负载电容。如果晶振不准或者负载电容过大过小,都会导致时钟误差过大。在这一切都搞定后,最终一个考虑因素是晶振的温漂。随着温度的变化,晶振往往精度会发生变化,因此,在实际的系统中,其中一种方法就是经常校对。比如我们所用的电脑的时钟,通常我们会设置一个选项“将计算机设置于internet时间同步”。选中这个选项后,一般可以过一段时间,我们的计算机就会和internet时间校准同步一次。

  对DS1302的操作就是对其内部寄存器的操作,DS1302内部共有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式。此外,DS1302还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。时钟突发寄存器可一次性顺序读/写除充电寄存器以外的寄存器。

  DS1302的一条指令一个字节8位,其中第7位(即最高位)是固定1,这一位如果是0的话,那写进去是无效的。第6位是选择RAM还是CLOCK的,这里主要讲CLOCK时钟的使用,它的RAM功能我们不用,所以如果选择CLOCK功能,第6位是0,如果要用RAM,那第6位就是1。从第5到第1位,决定了寄存器的5位地址,而第0位是读写位,如果要写,这一位就是0,如果要读,这一位就是1。

  DS1302时钟的寄存器,其中8个和时钟有关的,5位地址分别是00000一直到00111这8个地址,还有一个寄存器的地址是01000,这是涓流充电所用的寄存器,我们这里不讲。在DS1302的数据手册里的地址,直接把第7位、第6位和第0位值给出来了,所以指令就成了80H、81H那些了,最低位是1,那么表示读,最低位是0表示写。

  寄存器一:最高位CH是一个时钟停止标志位。如果我们的时钟电路有备用电源部分,上电后,我们要先检测一下这一位,如果这一位是0,那说明我们的时钟在系统掉电后,由于备用电源的供给,时钟是持续正常运行的;如果这一位是1,那么说明我们的时钟在系统掉电后,时钟部分不工作了。若我们的Vcc1悬空或者是电池没电了,当我们下次重新上电时,读取这一位,那这一位就是1,我们可以通过这一位判断时钟在单片机系统掉电后是否持续运行。剩下的7位高3位是秒的十位,低4位是秒的个位,这里注意再提一次,DS1302内部是BCD码,而秒的十位最大是5,所以3个二进制位就够了。
  寄存器二:bit7没意义,剩下的7位高3位是分钟的十位,低4位是分钟的个位。
  寄存器三:bit7是1的话代表是12小时制,是0的话代表是24小时制,bit6固定是0,bit5在12小时制下0代表的是上午,1代表的是下午,在24小时制下和bit4一起代表了小时的十位,低4位代表的是小时的个位。
  寄存器四:高2位固定是0,bit5和bit4是日期的十位,低4位是日期的个位。
  寄存器五:高3位固定是0,bit4是月的十位,低4位是月的个位。
  寄存器六:高5位固定是0,低3位代表了星期。
  寄存器七:高4位代表了年的十位,低4位代表了年的个位。这里特别注意,这里的00到99年指的是2000年到2099年。
  寄存器八:bit7是一个保护位,如果这一位是1,那么是禁止给任何其他的寄存器或者那31个字节的RAM写数据的。因此在写数据之前,这一位必须先写成0。

   物理上,DS1302的通信接口由3个口线组成,即RST,SCLK,I/O。其中RST从低电平变成高电平启动一次数据传输过程,SCLK是时钟线,I/O是数据线。这个DS1302的通信线定义和SPI很像,事实上,DS1302的通信是SPI的变异种类,它用了SPI的通信时序,但是通信的时候没有完全按照SPI的规则来,下面我们介绍DS1302的变异SPI通信方式。

  请注意数据是对时钟信号敏感的,而且一般数据是在下降沿写入,上升沿读出。平时SCLK保持低电平,当需要写命令或者写数据时,在时钟输出变为高电平之前先输出数据;当需要读数据时,在时钟输出变为高电平之前采样读取数据。

   第1步: 连接电路。

   第2步: DS1302的Python程序比较复杂,我们先编写一个模块ds1302.py,在里面创建一个类DS1302(),在里面编写读取时钟信息等方法。

   第3步: 编写实际控制程序,导入上面的模块ds1302。运行本文件,不断循环读取并打印时钟信息。

  实验结果示例:

㈥ DS1307读取时间出问题了,帮忙看看错哪了

gfu

㈦ c语言编的DS1302怎么读出和写入数据

这是汇编版的dS1302驱动程序,你可以参考一下。
PUBLIC D1302_INIT,SET1302,GET1302,WRITE,READ
CODE_DS1302 SEGMENT CODE
T_CLK BIT P1.0
T_IO BIT P1.1
T_RST BIT P1.2
SECOND EQU 30H
MINUTE EQU 31H
HOUR EQU 32H
DAY EQU 33H
MONTH EQU 34H
WEEK EQU 35H
YEAR EQU 36H

RSEG CODE_DS1302 ;使用当前段
;以下是DS1302初始化子程序
D1302_INIT: CLR T_RST ;DS1302复位
CLR T_CLK
NOP
NOP
SETB T_RST
MOV R1,#80H
MOV R0,#00H
LCALL WRITE
MOV R1,#90H
MOV R0,#0ABH
LCALL WRITE
RET
;以下是 读 日期时间数据子程序
GET1302: MOV R1,#81H
LCALL READ
MOV SECOND,R0
MOV R1,#83H
LCALL READ
MOV MINUTE,R0
MOV R1,#85H
LCALL READ
MOV HOUR,R0
MOV R1,#87H
LCALL READ
MOV DAY,R0
MOV R1,#89H
LCALL READ
MOV MONTH,R0
MOV R1,#8BH
LCALL READ
MOV WEEK,R0
MOV R1,#8DH
LCALL READ
MOV YEAR,R0
RET
;以下是时钟日历写操作子程序(单片机向DS1302写入初始时间)
SET1302: MOV R1,#80H ;写 秒
LCALL WRITE
MOV SECOND,R0
MOV R1,#82H ;写 分
LCALL WRITE
MOV MINUTE,R0
MOV R1,#84H ;写 时
LCALL WRITE
MOV HOUR,R0
MOV R1,#86H ;写 天
LCALL WRITE
MOV DAY,R0
MOV R1,#88H ;写 月
LCALL WRITE
MOV MONTH,R0
MOV R1,#8AH ;写 周
LCALL WRITE
MOV WEEK,R0
MOV R1,#8CH ;写 年
LCALL WRITE
MOV YEAR,R0
RET
;以下是 写 一个字节地址和数据的子程序
WRITE: CLR T_CLK
NOP
NOP
SETB T_RST
NOP
MOV A,R1
MOV R2,#08H
WRI_01: RRC A
NOP
NOP
CLR T_CLK
NOP
NOP
MOV T_IO,C
NOP
NOP
SETB T_CLK
NOP
NOP
DJNZ R2,WRI_01
CLR T_CLK
NOP
NOP
MOV A,R0
MOV R2,#08H
WRI_02: RRC A
NOP
CLR T_CLK
NOP
NOP
MOV T_IO,C
NOP
NOP
SETB T_CLK
NOP
NOP
DJNZ R2,WRI_02
CLR T_CLK
NOP
NOP
CLR T_RST
NOP
NOP
RET

;以下是从DS1302读取一字节地址中数据子程序
READ: CLR T_CLK
NOP
NOP
SETB T_RST
NOP
NOP
MOV A,R1
MOV R2,#08H
READ_01: RRC A
NOP
MOV T_IO,C
NOP
NOP
SETB T_CLK
NOP
NOP
CLR T_CLK
NOP
NOP
DJNZ R2,READ_01
NOP
NOP
SETB T_IO
CLR A
CLR C
MOV R2,#08H
READ_02: CLR T_CLK
NOP
NOP
MOV C,T_IO
NOP
NOP
RRC A
NOP
NOP
SETB T_CLK
NOP
NOP
DJNZ R2,READ_02
MOV R0,A
CLR T_RST
RET
END

㈧ ds1302是怎么个工作过程,怎么把当前时间赋给它,又是怎样通过控制段选、位选来显示ds1302写入的时间

首先、你要写一个读字节函数(根据1302的读写时序);其次、你要知道时、分、秒等寄存器的地址,给它们宏定义了;然后、你就可以根据原先定义好的读函数来读取当前时间寄存器中的数据了(也就是把时、分、秒等读取出来);最后、做数据处理就可以拿来显示了。不知楼主是否可以给分了……

㈨ Tiny RTC I2C模块的DS1307连续读取时间时,有时会死掉,这是什么问题

IIC总线的时序有问题,看看总线的时钟频率和应答位那里处理的不合适

㈩ 单片机问题:单片机从ds1302时钟芯片io口读出来的数据是什么进制的,那怎么送到1602液晶显示呢

BCD码(16进制数)。参考下面的程序(取数后送1602显示)
//向LCM中填写 年 数据
void lcm_w_yy(void){
//if(read_clock(0x8d) != yy){
yy = read_clock(0x8d);
lcm_w_test(0,0x83);
lcm_w_word("20");
lcm_w_test(0,0x84);
lcm_w_test(1,(yy/16)+0x30);
lcm_w_test(1,yy%16+0x30);
} //}
/*****************************************************************************/
//向LCM中填写 月 数据
void lcm_w_mo(void){
//if(read_clock(0x89) != mo){
mo = read_clock(0x89);
lcm_w_test(0,0x90);
if(mo/16 != 0){lcm_w_test(1,(mo/16)+0x30);} //十位消隐
else{lcm_w_test(1,0x20);}//同上
lcm_w_test(1,mo%16+0x30);
lcm_w_test(0,0x91);
lcm_w_word("月");
} //}
/*****************************************************************************/
//星期处理并送入LCM的指定区域
void lcm_w_xq(void){
unsigned char sel;
//if(read_clock(0x8b) != xq){
xq = read_clock(0x8b);
sel = (read_clock(0x8b))%16; //字节低4位的BCD码放入sel
lcm_w_test(0,0x97);//写入指定区域(97H 第二行第8个字)
if(sel==7) {lcm_w_word("日");} //
if(sel==6) {lcm_w_word("六");} //
if(sel==5) {lcm_w_word("五");} //
if(sel==4) {lcm_w_word("四");} //
if(sel==3) {lcm_w_test(1,0xc8);lcm_w_test(1,0xfd);} //此指令等于lcm_w_word("三"); 因为“三”的内码失效。
if(sel==2) {lcm_w_word("二");} //
if(sel==1) {lcm_w_word("一");} //星期一
lcm_w_test(0,0x95);
lcm_w_word("星期");
} //}
/*****************************************************************************/
//向LCM中填写 日 数据
void lcm_w_dd(void){
// if(read_clock(0x87) != dd){
dd = read_clock(0x87);
lcm_w_test(0,0x92);
if(dd/16 != 0){lcm_w_test(1,(dd/16)+0x30);} //十位消隐
else{lcm_w_test(1,0x20);}//同上
lcm_w_test(1,dd%16+0x30);
lcm_w_test(0,0x93);
lcm_w_word("日 ");

} //}
/*****************************************************************************/
//向LCM中填写 小时 数据
void lcm_w_hh(void){
if(read_clock(0x85) != hh){
hh = read_clock(0x85);
if (hh > 0x07 && hh < 0x22 && w == 0){
Beep();//整点报时音
}
}
lcm_w_test(0,0x88);
lcm_w_test(1,(hh/16)+0x30);
lcm_w_test(1,hh%16+0x30);

}
/*****************************************************************************/
//向LCM中填写 分钟 数据
void lcm_w_mm(void){
if(read_clock(0x83) != mm){
mm = read_clock(0x83);
}
if(w == 0){
days();//节日显示
}
lcm_w_test(0,0x89);
lcm_w_test(1,0x3a); //":"
lcm_w_test(1,(mm/16)+0x30);
lcm_w_test(1,mm%16+0x30);
lcm_w_test(1,0x2e); //"."
}
/*****************************************************************************/
//刷新数据
void updata (void){
lcm_w_mm();//刷新 分
lcm_w_hh();//刷新 小时
lcm_w_dd();//刷新 日
lcm_w_xq();//更新星期值
lcm_w_mo();//刷新 月
lcm_w_yy();//刷新 年
}
/*****************************************************************************/
//向LCM中填写 秒 数据
void lcm_w_ss(void){
unsigned int i=0;
unsigned char a=0,b=0,c=0;
if(read_clock(0x81) != ss){ //判断是否需要更新
ss = read_clock(0x81); //更新数据
lcm_w_test(0,0x8b); //秒值在LCM上的写入位置
lcm_w_test(1,(ss/16)+0x30); //写十位
lcm_w_test(1,ss%16+0x30); //写个位
lcm_w_word(" ");
led_b = ~led_b; //LED闪烁
updata (); //刷新数据
lcm_w_test(0,0x8d); //温度在LCM上的写入位置
i=ReadTemperature();//读温度并送显
a=i/100;
lcm_w_test(1,a+0x30); //显示温度十位
b=i/10-a*10;
lcm_w_test(1,b+0x30); //个位
lcm_w_test(1,0x2e); //"."
c=i-a*100-b*10;
lcm_w_test(1,c+0x30); //小位1位
lcm_w_word("℃"); //度C
} }

阅读全文

与ds1307时钟读出来的数据怎么处理相关的资料

热点内容
期货交易里一手是多少 浏览:825
网站信息怎么删除 浏览:370
互联网信息服务提供者包括哪些人 浏览:255
如何对齐两列相同数据 浏览:377
市场发展趋势具体是什么 浏览:799
回力鞋代理怎么样 浏览:830
个人如何申请抖音小程序 浏览:48
肯德基薯条有多少根官方数据 浏览:820
应用程序切分多少个容器 浏览:248
vb怎么创建独立程序 浏览:482
etc信息变更到哪里去 浏览:586
武汉石材修补技术培训班在哪里 浏览:363
开发产品怎么样才不被人模仿 浏览:428
营业员推荐产品运用哪些辅助工具 浏览:693
东方财富哪个软件可以交易股票 浏览:952
如何将网上的数据导入excel 浏览:71
越秀如何开发小程序 浏览:408
母婴用品代理怎么推销 浏览:739
拍产品收费如何 浏览:355
限电卖什么产品赚钱 浏览:547