关于时钟模块DS1302的使用心得
最近在做萬年歷,用到實(shí)時(shí)時(shí)鐘DS1302模塊,花了兩天時(shí)間看資料和寫驅(qū)動(dòng),想記錄一下我的學(xué)習(xí)經(jīng)過,順便做一下總結(jié)。
首先就是在圖書館查各種資料,于是查到的大多是這些,主要時(shí)硬件方面的資料:
其實(shí)能查到很多資料,但是能為我們所用的不是很多。在使用一個(gè)芯片時(shí),我一般時(shí)按照一下步驟去學(xué)習(xí):
1、芯片介紹;
2、查看引腳定義;
3、外圍電路
4、分析時(shí)序圖;
5、模仿著編寫驅(qū)動(dòng)程序,然后自己動(dòng)手寫驅(qū)動(dòng)。
6、實(shí)現(xiàn)功能。
下面我就按照這個(gè)順序去學(xué)習(xí)這款芯片;
一、芯片介紹
DS1302是DALLAS(達(dá)拉斯)公司出的一款涓流充電時(shí)鐘芯片,2001年DALLAS被MAXIM(美信)收購,因此我們看到的DS1302的數(shù)據(jù)手冊(cè)既有DALLAS的標(biāo)志,又有MAXIM的標(biāo)志;
DS1302實(shí)時(shí)時(shí)鐘芯片廣泛應(yīng)用于電話、傳真、便攜式儀器等產(chǎn)品領(lǐng)域,他的主要性能指標(biāo)如下:
1、DS1302是一個(gè)實(shí)時(shí)時(shí)鐘芯片,可以提供秒、分、小時(shí)、日期、月、年等信息,并且還有軟年自動(dòng)調(diào)整的能力,可以通過配置AM/PM來決定采用24小時(shí)格式還是12小時(shí)格式。
2、擁有31字節(jié)數(shù)據(jù)存儲(chǔ)RAM。
3、串行I/O通信方式,相對(duì)并行來說比較節(jié)省IO口的使用。
4、DS1302的工作電壓比較寬,大概是2.0V~5.5V都可以正常工作。采用雙電源供電,當(dāng)主電源比備用電源高0.2V時(shí),由主電源供電,否則采用備用電源,一般是一個(gè)紐扣電池。
5、DS1302這種時(shí)鐘芯片功耗一般都很低,它在工作電壓2.0V的時(shí)候,工作電流小于300nA。
6、DS1302共有8個(gè)引腳,有兩種封裝形式,一種是DIP-8封裝,芯片寬度(不含引腳)是300mil,一種是SOP-8封裝,有兩種寬度,一種是150mil,一種是208mil。
二、引腳定義
三、外圍電路
一般與單片機(jī)IO口相連時(shí)要加上拉電阻,提高 IO口的驅(qū)動(dòng)能力,這樣信號(hào)比較穩(wěn)定,計(jì)時(shí)也比較準(zhǔn)確。
四、分析時(shí)序圖
這是單字節(jié)寫入的時(shí)序圖,可見,先拉高使能端,進(jìn)行使能選擇,然后在時(shí)鐘上升沿寫入一個(gè)字節(jié)。
DS1302在進(jìn)行讀寫操作時(shí)最少讀寫兩個(gè)字節(jié),第一個(gè)是控制字節(jié),就是一個(gè)命令,說明是讀還是寫操作,第二個(gè)時(shí)需要讀寫的數(shù)據(jù)。
對(duì)于單字節(jié)寫,只有在SCLK為低電平時(shí)才能將 CE置高電平,所以剛開始將SCLK置低,CE置高,然后把需要寫入的字節(jié)送入 IO口,然后跳變SCLK,在SCLK下降沿時(shí),寫入數(shù)據(jù)
五、編寫驅(qū)動(dòng)程序
有了上面的分析,我們就可以學(xué)著編寫驅(qū)動(dòng)程序了,可以把驅(qū)動(dòng)程序分為幾個(gè)模塊來寫,由底層慢慢往上累加,比如,我們先編寫單個(gè)字節(jié)的讀寫操作,在編寫整個(gè)數(shù)據(jù)的讀寫,
#include "DS1302.h"
//*******************
void ds1302_writebyte(uchar byte){
uint i;
uint t = 0x01;
for(i=0;i<8;i++){
SCIO = byte & t;
t<<=1;
DOWN(); //下降沿完成一個(gè)位的操作
}
SCIO = 1;//確保釋放io引腳
}
//********************
void ds1302_writedata(uchar addr,uchar data_){
CE = 0; nop();
SCLK = 0; nop();
CE = 1; nop(); //使能片選信號(hào)
ds1302_writebyte((addr<<1)|0x80); //方便后面寫入
ds1302_writebyte(data_);
CE = 0; nop();//傳送數(shù)據(jù)結(jié)束
}
//*************************
uchar ds1302_readbyte(){
uint i;
uchar data_ = 0;
uint t = 0x01;
for(i=0;i<7;i++){ //c51好像不支持直接在for循環(huán)里面直接定義變量
if(SCIO){
data_ = data_ | t; //低位在前,逐位讀取,剛開始不對(duì),估計(jì)是這個(gè)的問題
}
t<<=1;
DOWN();
}
return data_;
}
//************************
uchar ds1302_readdata(uchar addr){
uchar data_ = 0;
CE = 0; nop();
SCLK = 0; nop();
CE = 1; nop();
ds1302_writebyte((addr<<1)|0x81);
data_ = ds1302_readbyte();
CE = 0; nop();
SCLK = 1; nop();
SCIO = 0; nop();
SCIO = 1; nop();
return data_;
}
//*********************
void init_ds1302(){
uchar i;
CE = 0; //初始化引腳
SCLK = 0;
i = ds1302_readdata(0x00); //讀取秒寄存器,秒在最低位
if((i & 0x80 != 0)){
ds1302_writedata(7,0x00); //撤銷寫保護(hù),允許寫入數(shù)據(jù)
for(i = 0;i<7;i++){
ds1302_writedata(i,init_time[i]);
}
}
}
//**************
void ds1302_readtime(){ //讀取時(shí)間
uint i;
for(i = 0;i<7;i++){
init_time[i] = ds1302_readdata(i);
}
}
其中頭文件為:
#ifndef __DS1302_H
#define __DS1302_H
#include "reg52.h"
#include "intrins.h"
#define uint unsigned int
#define uchar unsigned char
#define nop() _nop_()
#define UP() {SCLK = 0;nop();SCLK = 1;nop();} //上升沿 ,使用宏定義函數(shù)時(shí)最后一定家分號(hào)
#define DOWN() {SCLK = 1;nop();SCLK = 0;nop();} //下降沿
//這個(gè)模塊內(nèi)沒有集成上拉電阻,使用時(shí)最好接上2
sbit CE = P2^5;//RET,使能輸入引腳,當(dāng)讀寫時(shí),置高位
sbit SCIO = P2^6;//IO ,雙向通信引腳,讀寫數(shù)據(jù)都是通過這個(gè)完成
sbit SCLK = P2^7;//SCLK,時(shí)鐘信號(hào)
//為什么有時(shí)候好好的,也會(huì)出錯(cuò)顯示少了分號(hào)呢?還氣人啊!!!!
void ds1302_writebyte(uchar byte);//寫一個(gè)字節(jié);
void ds1302_writedata(uchar addr,uchar data_);//給某地址寫數(shù)據(jù),data是c51內(nèi)部的關(guān)鍵字,表示將變量定義在數(shù)據(jù)存儲(chǔ)區(qū),故此處用data_;
uchar ds1302_readbyte();//讀一個(gè)字節(jié)
uchar ds1302_readdata(uchar addr);//讀取某寄存器數(shù)據(jù) ;
void init_ds1302();
void ds1302_readtime();
extern uchar init_time[];
#endif
六、功能實(shí)現(xiàn)
功能實(shí)現(xiàn)就簡單了,就是加上主函數(shù)嘛,然后加上我們可以親眼看見并感知的模塊,比如用數(shù)碼管顯示時(shí)間:
#include "DS1302.h"
#define DIG P0
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
uchar init_time[] = {0x50,0x15,0x14,0x22,0x10,0x06,0x17};//初始化的時(shí)間 //秒 分 時(shí) 日 月 周 年
uchar code DIG_CODE[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //數(shù)碼管數(shù)字表
uint disp[8]={0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f};//把要顯示的數(shù)字傳給他
uchar Num=0;
uint count_flag = 0; //中斷溢出次數(shù)
void time0_init();//定時(shí)器0初始化
void display();//數(shù)碼管顯示時(shí)間
void main(void){
init_ds1302(); //初始化時(shí)寫入起始時(shí)間
time0_init();
while(1){
display();
}
}
//***************
void display(){
ds1302_readtime(); //讀取時(shí)間
disp[7] = DIG_CODE[init_time[0]&0x0f];
disp[6] = DIG_CODE[init_time[0]>>4];
disp[5] = 0X40; //顯示一個(gè)橫線
disp[4] = DIG_CODE[init_time[1]&0x0f];
disp[3] = DIG_CODE[init_time[1]>>4];
disp[2] = 0X40;
disp[1] = DIG_CODE[init_time[2]&0x0f];
disp[0] = DIG_CODE[init_time[2]>>4];
}
//******************
void time0_init(){
TMOD=0X02;//選擇為定時(shí)器模式,工作方式2,8位自動(dòng)重裝模式,僅用TRX打開啟動(dòng)。
TH0=0X9C; //給定時(shí)器賦初值,定時(shí)100us,0x9c就是156,就是還需計(jì)數(shù)100次產(chǎn)生溢出,就是0.1ms
TL0=0X9C;
ET0=1;//打開定時(shí)器0中斷允許
EA=1;//打開總中斷
TR0=1;//打開定時(shí)器
}
void DigDisplay() interrupt 1 //中斷入口函數(shù),掃描以實(shí)現(xiàn)動(dòng)態(tài)顯示
{
//定時(shí)器在工作方式二會(huì)自動(dòng)重裝初,所以不用在賦值。
// TH0=0X9c;//給定時(shí)器賦初值,定時(shí)0.1ms
// TL0=0X00;
count_flag++;
if(count_flag==1)
{
count_flag = 0;
DIG=0;
switch(Num) //位選,選擇點(diǎn)亮的數(shù)碼管,
{
case(7):
LSA=0;LSB=0;LSC=0; break;
case(6):
LSA=1;LSB=0;LSC=0; break;
case(5):
LSA=0;LSB=1;LSC=0; break;
case(4):
LSA=1;LSB=1;LSC=0; break;
case(3):
LSA=0;LSB=0;LSC=1; break;
case(2):
LSA=1;LSB=0;LSC=1; break;
case(1):
LSA=0;LSB=1;LSC=1; break;
case(0):
LSA=1;LSB=1;LSC=1; break;
}
DIG=disp[Num]; //段選,選擇顯示的數(shù)字。
Num++;
if(Num>7)
Num=0;
}
}
總結(jié)一下:
這個(gè)芯片基本上不是很難,但是想要用的靈活,用的上手,還是得多練的,最好是先把上面的驅(qū)動(dòng)程序?qū)χ鴷r(shí)序圖自己分析一遍,然后自己親手編寫一下。
還有就是看數(shù)據(jù)手冊(cè),一個(gè)芯片所能用到的數(shù)據(jù),在數(shù)據(jù)手冊(cè)上基本都能查到。資料誰都能查到,就看怎么用了。
總結(jié)
以上是生活随笔為你收集整理的关于时钟模块DS1302的使用心得的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信支付 商户号虚拟类目的单笔限额300
- 下一篇: 源码方式安装 lrzsz 库