精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于單片機的DS1302實時時鐘實驗 實時時鐘芯片DS1302的工作原理

CHANBAEK ? 來源:RYMCU ? 作者:RYMCU ? 2023-07-27 18:27 ? 次閱讀

概述

在許多系統當中都需要精確的時鐘功能,因此時鐘芯片孕育而生。其中美國達拉斯 DALLAS 公司設計的 DS1302 是一款非常流行的數字時鐘芯片。DS1302 是一款具有涓細電流充電能力的低功耗實時時鐘芯片。它可以對年、月、日、星期、時、分、秒進行計時,并且具有閏年功能。年計數可達到 2100 年。

15.1 DS1302 功能簡介

DS1302 內部包含 31 字節的通用 RAM,實現設置備用電池功能。采用 3 線制的串行數據通信接口,并且適用于大多數的微處理器。工作電壓范圍達到 2~5V,與 5VTTL 電平完全兼容。支持單字節或多字節時鐘、RAM 數據讀、寫操作。當工作電壓為 2V 時,工作電流低至 320nA。工業級 DS1302 正常工作溫度范圍為:-40℃ ~85℃,芯片包括直插和貼片兩種封裝模式,封裝示意圖如下所示:
圖片

DS1302 典型通信電路如下圖所示:
圖片
如上圖所示,只需 3 根線 CE、I/O、SCLK 便可實現處理器與 DS1302 之間通信,上圖中 X1,X2 之間為外接時鐘晶振,VCC2 為電源供電端,VCC1 為備用電池端。各管腳定義及功能如下所示:
圖片

15.2 單字節操作模式

與 DS1302 進行數據通信時,首先得向 DS1302 傳輸一個字節的控制指令,控制指令位定義如下所示。
圖片
字節的最高位 bit7 必須為 1,否則無法向 DS1302 寫入數據。Bit6 為 1 時,表示后續對 31 字節的 RAM 進行讀寫操作,為 0 時,表示后續將對時鐘寄存器進行讀寫操作。Bit5~bit1 為后續操作的時鐘寄存器或 RAM 的地址。最低位 bit0 為 1 時,表示讀取 DS1302 的數據,為 0 時,表示向 DS1302 寫入數據。對 DS1302 進行單字節模式的讀、寫操作時序如下圖所示。
圖片

單字節寫操作(Single-Byte Write)時序為首先向 DS1302 寫入控制指令,緊接著寫入一個字節的數據。寫入的順序為低位在前,高位在后的傳輸方式,要求在時鐘上升沿準備好數據。單字節讀操作(Single-Byte Read)時序為首先向 DS1302 寫入控制指令,緊接著 SCLK 的的下降沿 DS1302 有數據 D0 輸出,因此在接下來的上升沿前讀取穩定的 D0 值,依次類推至 D7。根據上圖時序要求,往 DS1302 寫入一個字節和讀取一個字節的函數如下所示:

//寫字節
void WrByte_1302(uchar dat)
{
	uchar j;
	bit flag;

	for(j=1;j<=8;j++)
 	{	//從低到高依次將1Byte數據寫入DS1302
		flag = dat&0x01;

		IO_1302 = flag;//將要寫的位放到總線
		SCLK_1302 = 0;
		SCLK_1302 = 1;//產生一個上升沿,完成1位數據寫入

		dat=dat >>1;//將數據移到下一位
	}	
}
//讀字節
uchar RdByte_1302(void)
{
	uchar dat,flag,j;
	for(j=1;j<=8;j++)
	{		
		SCLK_1302 = 1;//產生一個下降沿
		SCLK_1302 = 0;

		flag = IO_1302;//讀取DS1302發出的一位數據
		dat=(dat >>1)|(flag< 

如上所示,寫字節函數 WrByte_1302()中,要求單片機在時鐘 SCLK_1302 上升沿前將數據放到數據總線 IO_1302 上,然后產生一個 SCLK_1302 上升,完成一 bit 數據的寫入,同時要求 1Byte 的數據低位在前,高位在后依次發送。讀字節函數 RdByte_1302()中,要求在時鐘 SCLK_1302 下降沿之后,將總線 IO_1302 數據讀出,同時要求 1Byte 的數據低位在前,高位在后依次讀取。

在上述函數的基礎上,單字節操作模式的讀、寫函數如下所示:

//單字節寫模式
void WrSingle_1302(uchar addr,uchar dat)
{
	CE_1302 = 1;//拉高片選
	WrByte_1302(addr);//寫入地址及控制指令
	WrByte_1302(dat);//寫入數據
	CE_1302 = 0;//拉低片選
	SCLK_1302 = 0;//釋放始終總線,滿足下次操作時序要求(非常重要)

}
//單字節讀模式
uchar RdSingle_1302(uchar addr)
{
	uchar dat;

	CE_1302 = 1;//拉高片選
	WrByte_1302(addr);//寫入地址及控制指令
	dat = RdByte_1302();//讀取一個字節數據
 	CE_1302 = 0;//拉低片選

	return dat;
}

我們這里重點講述 DS1302 的時鐘功能,因此與涓流充電有關的 31 字節 RAM 操作這里不做詳細的介紹。與實時時鐘有關的寄存器如圖所示。
圖片
與時鐘有關的寄存器總共有 9 個如上圖所示,前 7 個分別為:秒、分、時、日、月、星期、年,均為 8 位寄存器。以秒寄存器為例介紹時間的表示法,其中 bit6-bit4 為秒的十位,bit3-bit0 為秒的個位。59 秒時,bit6-bit4=“101”,bit3-bit0=“1001”,其它依此類推。另外,設置“時”寄存器的 bit7 可以設置為 12 小時或 24 小時制。上述寄存器的讀寫控制指令字節分別如圖左側兩列所示。

秒寄存器的 CH(bit7)定義為時鐘運行標志位,當該位被設置成 1 時,時鐘計時停止,并且 DS1302 進入低功耗模式。當設置為 0 時,啟動計時。上電初始狀態時,該位狀態不定,因此在時鐘初始化時確保該位被清 0,保證后續時鐘芯片正常運行。

第 8 個寄存器為控制寄存器,WP(bit7)為寫保護位,當設置為 1 時,無法向 DS1302 寫入數據,上電時該位狀態不定,因此,需要對 DS1302 其它寄存器進行寫操作之前,務必先將 WP 設置為 0。第 9 個寄存器不影響實現時鐘功能,暫不做介紹。

因此,在 DS 1302 應用時要對它進行初始化,首先解除寫保護,然后將與時間有關的 7 個寄存器賦初值,將初始化的內容放到函數 Init_1302(Uchar *SetTime)中。另外,我們將從 DS1302 讀取 7 個時間值的操作放到函數 GetTime(*CurrentTime)中,如下代碼所示。

//1302初始化
void Init_1302(uchar *SetTime)
{
	  uchar j;

	  CE_1302 = 0;//初始化通信引腳
	SCLK_1302 = 0;

	WrSingle_1302(0x8E,0x00);//解除寫保護(WP=0)
	
	for(j=0;j<=6;j++)
	{
		WrSingle_1302(0x80+2*j,SetTime[j]);//寫入7個時鐘數據
	}
	//WrBurst_1302(SetTime);//當采用Burst模式時,使用此語句替代上面for循環語句
}
//獲取當前時間值
void GetTime(uchar *CurrentTime)
{
	  uchar j;

	  CE_1302 = 0;//初始化通信引腳
	SCLK_1302 = 0;

	for(j=0;j<=6;j++)
	{
		 *CurrentTime = RdSingle_1302(0x81+2*j);//讀取7個時鐘數據
		 CurrentTime++;
	}
	
	//RdBurst_1302(CurrentTime); //當采用Burst模式時,使用此語句替代上面for循環語句
}

到目前為止,我們已經學習了時鐘芯片 DS1302 的功能介紹,以及初始化和時鐘獲取函數的編寫,RY-51 單片機開發板上 DS1302 電路原理圖如下所示,三根通信線分別接 4.7K 上拉電阻,分別與單片機的 I/O 口相連接。
圖片
按照慣例我們將和 DS1302 有關的函數打包放入"Drive_DS1302.h","Drive_DS1302.c"中,方便后續調用及移植。"Drive_DS1302.h"代碼如下:

#ifndef __DS1302_H__
#define __DS1302_H__

//1302初始化
extern void Init_1302(unsigned char *SetTime);
//獲取時間
extern void GetTime(unsigned char *CurrentTime);
//單字節模式寫
void WrSingle_1302(unsigned char addr,unsigned char dat);
//單字節模式讀		  
unsigned char RdSingle_1302(unsigned char addr);
//突發模式寫
void WrBurst_1302(unsigned char *SetTime);
//突發模式讀
void RdBurst_1302(unsigned char *CurrentTime);

#endif

"Drive_DS1302.c"代碼如下:

#include< reg52.h >
#include"Drive_DS1302.h"

#define uchar unsigned char
#define  uint unsigned int

sbit   CE_1302 = P1^2;	//DS1302通信引腳CE,I/O,SCLK定義
sbit   IO_1302 = P1^1;
sbit SCLK_1302 = P1^0;	

//寫字節
void WrByte_1302(uchar dat)
{
	uchar j;
	bit flag;

	for(j=1;j<=8;j++)
 	{	//從低到高依次將1Byte數據寫入DS1302
		flag = dat&0x01;

		IO_1302 = flag;//將要寫的位放到總線
		SCLK_1302 = 0;
		SCLK_1302 = 1;//產生一個上升沿,完成1位數據寫入

		dat=dat >>1;//將數據移到下一位
	}	
}
//讀字節
uchar RdByte_1302(void)
{
	uchar dat,flag,j;
	for(j=1;j<=8;j++)
	{		
		SCLK_1302 = 1;//產生一個下降沿
		SCLK_1302 = 0;

		flag = IO_1302;//讀取DS1302發出的一位數據
		dat=(dat >>1)|(flag< 7);//讀出的值最低位在前面
	}
	return dat;	
}
//單字節寫模式
void WrSingle_1302(uchar addr,uchar dat)
{
	CE_1302 = 1;//拉高片選
	WrByte_1302(addr);//寫入地址及控制指令
	WrByte_1302(dat);//寫入數據
	CE_1302 = 0;//拉低片選
	SCLK_1302 = 0;//釋放始終總線,滿足下次操作時序要求(非常重要)

}
//單字節讀模式
uchar RdSingle_1302(uchar addr)
{
	uchar dat;

	CE_1302 = 1;//拉高片選
	WrByte_1302(addr);//寫入地址及控制指令
	dat = RdByte_1302();//讀取一個字節數據
 	CE_1302 = 0;//拉低片選

	return dat;
}
//突發寫模式
void WrBurst_1302(uchar *SetTime)
{
	uchar j;

	CE_1302 = 1;//拉高片選
	WrByte_1302(0xBE);//Burst模式寫專用指令
	for(j=0;j<=6;j++)
	{
		WrByte_1302(SetTime[j]);//寫入7位時鐘數據
	}
	CE_1302 = 0;//拉低片選	
}
//突發讀模式
void RdBurst_1302(uchar *CurrentTime)
{
	uchar j;

	CE_1302 = 1;//拉高片選
	WrByte_1302(0xBF);//Burst模式讀專用指令
	for(j=0;j<=6;j++)
	{
		*CurrentTime = RdByte_1302();//讀取一個字節數據;
		CurrentTime++;
	}
	CE_1302 = 0;//拉低片選	
}
//1302初始化
void Init_1302(uchar *SetTime)
{
	  uchar j;

	  CE_1302 = 0;//初始化通信引腳
	SCLK_1302 = 0;

	WrSingle_1302(0x8E,0x00);//解除寫保護(WP=0)
	
	for(j=0;j<=6;j++)
	{
		WrSingle_1302(0x80+2*j,SetTime[j]);//寫入7個時鐘數據
	}
	//WrBurst_1302(SetTime);//當采用Burst模式時,使用此語句替代上面for循環語句
}
//獲取當前時間值
void GetTime(uchar *CurrentTime)
{
	  uchar j;

	  CE_1302 = 0;//初始化通信引腳
	SCLK_1302 = 0;

	for(j=0;j<=6;j++)
	{
		 *CurrentTime = RdSingle_1302(0x81+2*j);//讀取7個時鐘數據
		 CurrentTime++;
	}
	
	//RdBurst_1302(CurrentTime); //當采用Burst模式時,使用此語句替代上面for循環語句
}

下面我們利用上面編寫的函數以及學習的單片機的知識,開始編寫一個小的時鐘顯示綜合應用程序。程序的功能為:上電時由單片機對 DS1302 進行初始化,設置時間為 2017 年、星期日、12 月 31 日、23 時 58 分 56 秒,初始化完成后,每隔 500ms 獲取 DS1302 的時間,并將時間顯示到 1602 液晶顯示器上,主函數程序如下所示:

#include< reg52.h >
#include"Drive_1602.h"
#include"Drive_DS1302.h"

#define uchar unsigned char
#define  uint unsigned int

#define FOSC 11059200 //單片機晶振頻率
#define T_1ms (65536 - FOSC/12/1000)  //定時器初始值計算

sbit DU = P2^7;//數碼管段選、位選引腳定義
sbit WE = P2^6;
sbit DU_L = P2^3;
	
uchar T_flag  = 0;//定時500ms標志位
uchar str[23]=0;  //字符臨時存儲變量
unsigned char code SetTime[7]={//2017年,星期日,12月31日,23時58分56秒,時間初始值
	 			0x56,0x58,0x23,0x31,0x12,0x07,0x17};
uchar CurrentTime[7]={0};//存儲時間變量

void main()
{
 	Init_1602();//1602初始

	P0 = 0xff;//關閉所有數碼
	WE = 1;
	WE = 0;
	DU_L = 0;

	TMOD = 0x01;	 //定時器工作模式配置
	TL0  = T_1ms;	//裝載初始值
	TH0  = T_1ms >>8;
	TR0  = 1;		 //啟動定時器
	ET0  = 1;		 //允許定時器中斷
	EA   = 1;		 //開總中斷


	Init_1302(SetTime);//1302初始化

	while(1)
	{
		if(T_flag)//500ms定時
		{
			T_flag = 0;
			GetTime(CurrentTime);//獲取時間

			str[0] = '2';	 
			str[1] = '0';	 
			str[2] = (CurrentTime[6] >>4)+'0';	 //年
			str[3] = (CurrentTime[6]& 0x0F)+'0';
			str[4] = '-';
			str[5] = (CurrentTime[4] >>4)+'0';	 //月
			str[6] = (CurrentTime[4]& 0x0F)+'0';
			str[7] = '-';
			str[8] = (CurrentTime[3] >>4)+'0';	 //日
			str[9] = (CurrentTime[3]& 0x0F)+'0';
		   str[10] = '?';
		   str[11] = (CurrentTime[2] >>4)+'0';	 //時
		   str[12] = (CurrentTime[2]& 0x0F)+'0';
		   str[13] = ':';
		   str[14] = (CurrentTime[1] >>4)+'0';	 //分
		   str[15] = (CurrentTime[1]& 0x0F)+'0';
		   str[16] = ':';	   
		   str[17] = (CurrentTime[0] >>4)+'0';	 //秒
		   str[18] = (CurrentTime[0]& 0x0F)+'0';
		   str[19] = ' ';
		   str[20] = (CurrentTime[5] >>4)+'0';	 //星期
		   str[21] = (CurrentTime[5]& 0x0F)+'0';
		   str[22] = '?';
		    
		  	Disp_1602_str(1,4,str);	//將獲得的時間分別顯示到1602的第一二行
			Disp_1602_str(2,3,str+11);	
		}
	}
}

//定時器0中斷子程序,定時1ms
void timer0() interrupt 1
{
	static uint T_500ms = 0;

	TL0 = T_1ms;//重裝初始值
	TH0 = T_1ms >>8;	

	T_500ms++;
	if(T_500ms >=500)//500ms,置位T_flag
	{
		T_500ms = 0;
		T_flag = 1;	
	}
}

將程序下查看結果是否與預想的一致吧。

15.3 突發操作模式

上面我們講解的是以單字節的模式,從 1302 中連續讀取時間數據。仔細的同學可能會發現一個問題,就是我們連續讀 7 個時間寄存器是有先后順序的,會有讀錯數據的風險。例如我們要讀的時間為 23 時 59 分 59 秒,最開始時我們把 59 秒讀出來了,如果剛好在你讀完的時候 59 秒變成了 00 秒,59 分變成了 00 分,23 時變成了 00 時,接下來把分、時依次讀出來,因此我們讀出來的時間為 00 時 00 分 59 秒,很顯然這個時間是不對的。下面我們講解的突發操作模式有效的解決了這個問題。

在突發操作讀模式下,當 DS1302 收到突發讀數據指令,DS1302 首先會把 8 個時間寄存器的數據同時讀出存放在 8 個二級時間寄存器中,然后依次把 8 個二級時間寄存器的數據輸出給單片機,突發讀專用指令為 0xBF。同樣,當我們需要寫 DS1302 時,當收到突發寫指令后,DS1302 將接收到的 8 個連續數據存儲到 8 個二級時間寄存器中,然后同時將 8 個數據寫到時間寄存器中,突發寫專用指令為 0xBE。根據上述原理,編寫突發寫模式和突發讀模式函數如下代碼所示。

//突發寫模式
void WrBurst_1302(uchar *SetTime)
{
	uchar j;

	CE_1302 = 1;//拉高片選
	WrByte_1302(0xBE);//Burst模式寫專用指令
	for(j=0;j<=6;j++)
	{
		WrByte_1302(SetTime[j]);//寫入7位時鐘數據
	}
	CE_1302 = 0;//拉低片選	
}
//突發讀模式
void RdBurst_1302(uchar *CurrentTime)
{
	uchar j;

	CE_1302 = 1;//拉高片選
	WrByte_1302(0xBF);//Burst模式讀專用指令
	for(j=0;j<=6;j++)
	{
		*CurrentTime = RdByte_1302();//讀取一個字節數據;
		CurrentTime++;
	}
	CE_1302 = 0;//拉低片選	
}

如上圖所示,首先為向 DS1302 寫入突發讀或者寫指令,然后緊接著是讀取或寫入 7 個時間數據。前面講解的都是 8 個連續的數據,我們這里寫 7 個的原因是,時間顯示這 7 個就足夠了。上述完整代碼詳見完整代碼"Drive_DS1302.h"、"Drive_DS1302.c"中。

突發模式的應用與單字節模式類似,只需將如下代碼中的for循環語句替換成“RdBurst_1302(CurrentTime)”即可。

//獲取當前時間值
void GetTime(uchar *CurrentTime)
{
	  uchar j;

	  CE_1302 = 0;//初始化通信引腳
	SCLK_1302 = 0;

	for(j=0;j<=6;j++)
	{
		 *CurrentTime = RdSingle_1302(0x81+2*j);//讀取7個時鐘數據
		 CurrentTime++;
	}
	
	//RdBurst_1302(CurrentTime); //當采用Burst模式時,使用此語句替代上面for循環語句
}

15.4 本章小結

本章詳細介紹了實時時鐘芯片DS1302的工作原理,驅動程序的編寫,以及DS1302的簡單應用。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 單片機
    +關注

    關注

    6032

    文章

    44514

    瀏覽量

    632946
  • 微處理器
    +關注

    關注

    11

    文章

    2247

    瀏覽量

    82310
  • 時鐘芯片
    +關注

    關注

    2

    文章

    243

    瀏覽量

    39846
  • DS1302
    +關注

    關注

    8

    文章

    449

    瀏覽量

    50614
收藏 人收藏

    評論

    相關推薦

    實時時鐘芯片DS1302應用

    時鐘程序 完整內容下載: 實時時鐘芯片DS1302應用.docx
    發表于 07-05 10:09

    實時時鐘芯片DS1302有哪些性能

    實時時鐘 DS1302一、實時時鐘芯片DS13021、DS1302的主要性能指標(1)
    發表于 12-10 08:01

    DS1302實時時鐘芯片介紹

    DS1302電子時鐘DS1302如上圖所示,它是由美國DALLAS公司推出的具有涓細電流充電能力的低功耗實時時鐘芯片
    發表于 01-17 06:44

    DS1302實時時鐘芯片介紹

    文章目錄實時時鐘芯片 DS1302 介紹DS1302 的特點實時時鐘芯片
    發表于 02-18 07:57

    實時時鐘芯片DS1302應用資料

    子函數供讀者調用。本章最后通過一個具體的實例,講解了如何使用51系列單片機來操作實時時鐘芯片DS1302
    發表于 09-26 08:27

    實時時鐘DS1302程序列子

    實時時鐘DS1302程序列子     /*********************************************************************//* 實時時鐘
    發表于 07-08 16:26 ?142次下載

    實時時鐘電路DS1302的原理及應用

    實時時鐘電路DS1302的原理及應用 現在流行的串行時鐘電路很多,如DS1302DS1307、PCF8485等。這些電路的接口簡單、
    發表于 01-01 00:19 ?5482次閱讀
    <b class='flag-5'>實時時鐘</b>電路<b class='flag-5'>DS1302</b>的原理及應用

    ds1302實時時鐘

    ds1302實時時鐘 現在流行的串行時鐘電路很多,如DS1302DS1307、PCF8485等。這些電路的接口簡單、價格低廉、使用方便,
    發表于 10-09 09:34 ?3837次閱讀
    <b class='flag-5'>ds1302</b><b class='flag-5'>實時時鐘</b>

    基于單片機的1602液晶顯示的DS1302實時時鐘

    基于單片機的1602液晶顯示的DS1302實時時鐘
    發表于 11-25 14:57 ?39次下載

    單片機制作RTC實時時鐘(DS1302)程序【C語言版】

    單片機制作RTC實時時鐘(DS1302)程序【C語言版】,感興趣的可以看看。
    發表于 12-30 13:48 ?0次下載

    基于51單片機ds1302實時時鐘數碼管程序

    基于51單片機ds1302實時時鐘數碼管程序,帶按鍵調時,整點報時 和勿擾時段。可以修改 親測通過
    發表于 10-16 09:26 ?20次下載

    基于實時時鐘模塊 時鐘芯片DS1302

    基于實時時鐘模塊 時鐘芯片DS1302
    發表于 10-16 11:35 ?40次下載
    基于<b class='flag-5'>實時時鐘</b>模塊 <b class='flag-5'>時鐘</b><b class='flag-5'>芯片</b><b class='flag-5'>DS1302</b>

    51單片機DS1302實時時鐘驅動程序

    本文首先闡述了ds1302引腳及功能,其次介紹了DS1302的控制字節及電路圖,最后詳細介紹了51單片機DS1302實時時鐘驅動程序。
    發表于 05-15 08:45 ?9440次閱讀
    51<b class='flag-5'>單片機</b><b class='flag-5'>DS1302</b><b class='flag-5'>實時時鐘</b>驅動程序

    實時時鐘芯片 DS1302 介紹

    文章目錄實時時鐘芯片 DS1302 介紹DS1302 的特點實時時鐘芯片
    發表于 12-23 19:47 ?11次下載
    <b class='flag-5'>實時時鐘</b><b class='flag-5'>芯片</b> <b class='flag-5'>DS1302</b> 介紹

    實時時鐘DS1302開源項目

    電子發燒友網站提供《實時時鐘DS1302開源項目.zip》資料免費下載
    發表于 07-29 11:29 ?4次下載
    <b class='flag-5'>實時時鐘</b><b class='flag-5'>DS1302</b>開源項目