DS1302時鐘模塊LCD1602顯示
- DS1302時鐘模塊相關介紹
- 基本介紹
- 概述
- 特點
- 各引腳功能
- 相關暫存器
- 時序圖
- 單位元組寫時序
- 單位元組讀時序
- 時鐘/日歷多位元組(Burst)方式
- 代碼
- main.c
- lcd1602.c
- ds1302.c
- 專案展示
DS1302時鐘模塊相關介紹
基本介紹
概述
DS1302 可慢速充電實時時鐘芯片包含實時時鐘/日歷和 31 位元組的非易失性靜態 RAM,它經過一個簡
單的串行介面與微處理器通信,實時時鐘/日歷可對秒,分,時,日,周,月,和年進行計數,對于小于
31 天的月,月末的日期自動進行調整,還具有閏年校正的功能,時鐘可以采用 24 小時格式或帶 AM(上
午)/PM(下午)的 12 小時格式,31 位元組的== RAM== 可以用來臨時保存一些重要資料,使用同步串行通信,
簡化了 DS1302 與微處理器的通信,與時鐘/RAM 通信僅需3 根線:(1)RST(復位),(2)I/O(資料線)
和(3)SCLK(串行時鐘),資料可以以每次一個位元組的單位元組形式或多達 31 位元組的多位元組形式傳輸,DS1302
能在非常低的功耗下作業,消耗小于 1μW 的功率便能保存資料和時鐘資訊,
特點

各引腳功能

各引腳的功能:
Vcc1:主電源;Vcc2:備份電源, 當Vcc2>Vcc1+0.2V時,由Vcc2向DS1302供電,當Vcc2<Vcc1時,由Vcc1向DS1302供電,
SCLK: 串行時鐘,輸入,控制資料的輸入與輸出;
I/O: 三線介面時的雙向資料線;
CE: 輸入信號,在讀和寫的器件必須為高,該引腳有兩個功能:1.開始控制字訪問移位暫存器的控制邏輯;2.提供結束單位元組或多位元組資料傳輸的方法,
相關暫存器
有關日歷、時間的暫存器共有12個,其中有7個暫存器(讀時81H——8DH,寫時80H——8CH==)存放的資料格式是BCD碼形式,如圖所示

小時暫存器
位7用于定義DS1302是采用12小時模式還是24小時模式,高:12小時模式,在12小時模式時,位5 為1時,表示PM,在24小時模式時,為5是第二個10小時位,
秒暫存器
的就位7定義為時鐘暫圖示志(CH),1:時鐘振蕩器停止,DS1302進入低功耗狀態,當該位置為0時,時鐘開始運行,
控制暫存器
的位7是寫保護位(WP),其他7位均置0,對時鐘和RAM進行寫操作時,WP必須為0,也就是關閉寫保護,當WP為1時,就是只讀模式,
DS1302相關的RAM地址
DS1302中附加31位元組靜態RAM的地址如下圖

DS1302的作業模式暫存器
所謂的突發模式(BURST模式)就是一次性傳送多個位元組的時鐘信號和RAM資料,比如我可以一次性把時間和日期寫入,也可以一次性的讀出時間和日期,

通過對 31(十進制)位地址尋址(地址/命令位于 1 至 5=邏輯 1),可以把時鐘/日歷或 RAM 暫存器規定為多位元組方式,如前所述,位 6 規定時鐘或 RAM 而位 0 規定讀或寫,在時鐘\日歷暫存器中的地址 9 至 31或 RAM 暫存器中的地址 31 不能存盤資料,在多位元組方式中讀或寫從地址 0 的位 0 開始,當以多位元組方式寫時鐘暫存器時,必須按資料傳送的次序寫最先 8 個暫存器,意思就是寫我們不是只有7個嗎?時分秒、年月日、周一共七個 但是吧它得位元組數為8 所有要寫夠8次,
但是,當以多位元組方式寫 RAM 時,為了傳送資料不必寫所有 31 個位元組,不管是否寫了全部 31 個位元組,所寫的每一個位元組都將傳送至 RAM,

DS1302充電暫存器
這個我沒整過,全部復制手冊的,哈哈
這個暫存器控制 DS1302 的慢速充電特性,圖 4 的簡化電路表示慢速充電器的基本組成,慢速充電選擇(TCS)位(位 4-7)控制慢速充電器的選擇,為了防止偶然的因素使之作業,只有 1010 模式才能使慢
速充電器作業,所有其它的模式將禁止慢速充電器,DS1302 上電時,慢速充電器被禁止,二極管選擇(DS)位(位 2-3)選擇是一個二極管還是兩個二極管連接在 Vcc2 與 Vcc1 之間,如果 DS 為 01,那么選擇一個二極管;如果 DS 為 10,則選擇兩個二極管,如果 DS 為 00 或 11,那么充電器被禁止,與 TCS 無關,RS 位(位0-1)選擇連接在 Vcc2 與 Vcc1 之間的電阻,電阻選擇(RS)位選擇的電阻如下:

如果 RS 為 00,充電器被禁止,與 TCS 無關,
二極管和電阻的選擇用戶根據電池和超容量電容充電所需的最大電流決定,最大充電電流可以如下列
所說明的那樣進行計算,假定 5V 系統電源加到 Vcc2 而超容量電容接至 Vcc1,再假設慢速充電器作業時在Vcc2 和 Vcc1 之間接有一個二極管和電阻 R1,因而最大電流可計算如下:
Imax =(5.0V-二極管壓降)/R1
=(5.0V-0.7V)/2kΩ
= 2.2mA
顯而易見,當超容量電容充電時,Vcc2 和 Vcc1 之間的電壓減少,因而充電電流將會減小,
時序圖
我們首先得給DS1302時鐘模塊寫入時間和日期,然后呢這個時鐘會自己走,我們之后只需要讀取時間和日期即可,我們直接看時序圖 撰寫代碼

單位元組寫時序
資料輸入
跟隨在輸入寫命令位元組的 8 個 SCLK 周期之后,在下 8 個 SCLK 周期的上升沿輸入資料,如果有額外的SCLK 周期,它們將被忽略,輸入從位 0 開始,


上面時序圖是前8位是地址,后8位是資料,
我們根據上面的時序圖 來撰寫 單位元組寫的一個函式
發現上面的
/*DS1302寫單位元組函式*/
void ds1302_write_byte(unsigned char addrOrData)
{
unsigned char i = 0;
for(i=0;i<8;i++)
{
DAT = addrOrData & 0x01; //開始傳輸低位
addrOrData = addrOrData >> 1;//右移一位
CLK = 1; //拉高時鐘表示已經發送
CLK = 0; //拉低時鐘準備繼續放新的資料位
}
}
/*DS1302寫函式*/
void ds1302_write(unsigned char addr,unsigned char data)
{
RST = 0; //RST拉低
SCLK = 0; //時鐘SCLK也拉低
RST = 1; //準備開始寫
ds1302_writeByte(addr); //寫入要寫的地址
ds1302_writeByte(dat); //寫入地址的資料
RST = 0; //關閉 表示結束
}

看上面的圖,比如我想寫入時 為18點 時的寫暫存器是84H 資料就是18點 但是DS1302存盤格式為 BCD 碼那就是 0x18,
那寫入 時 為18點 的代碼則是:
ds1302_write(0x84,0x18); //寫入時 為 18點
單位元組讀時序


/*DS1302讀單位元組函式*/
unsigned char ds1302_read_byte(unsigned char data)
{
unsigned char i;
for(i=0;i<8;i++)
{
dat = dat >> 1; //右移一位 資料是先從低位開始
if(IO == 1)
dat = dat | 0x80; //1000 0000
else
dat = dat & 0x7f; //0111 1111
SCLK = 1; //時鐘拉高表示這位已經結束
SCLK = 0; //時鐘拉低開始接收新的資料位
}
return data;
}
/*DS1302讀取資料函式*/
unsigned char ds1302_read_data(unsigned char addr)
{
unsigned char data; //用于存放接收的資料
RST = 0; //RST拉低
SCLK = 0; //時鐘SCLK也拉低
RST = 1; //準備開始寫
ds1302_write_byte(addr); //寫入要讀取的地址
data = ds1302_read_byte(data); //讀取地址的資料
RST = 0;//關閉 表示結束
return data; //回傳讀取到的資料
}
我們想讀取時 里面時間 看看現在是幾點 時 讀暫存器是85H
time = ds1302_read_data(0x85);
寫保護暫存器
寫保護暫存器的位 7 是寫保護位,開始 7 位(位 0-6)置為零,在讀操作時總是讀出零,在對時鐘或
功能 位元組數 脈沖數
CLOCK 8 72
RAM 31 256
DS1302
http://www.hgsemi.com.cn - 8 - 2019 NOV
RAM 進行寫操作之前,位 7 必須為零,當它為高電平時,寫保護位禁止對任何其它暫存器進行寫操作,
時鐘/日歷多位元組(Burst)方式
所謂的突發模式(BURST模式)就是一次性傳送多個位元組的時鐘信號和RAM資料,比如我可以一次性把時間和日期寫入,也可以一次性的讀出時間和日期,

代碼
部分代碼呈現
main.c
#include <reg52.h>
#include "lcd1602.h"
#include "ds1302.h"
void main()
{
lcd_init(); //初始化LCD1602
ds1302_init();//初始化DS1302
while(1)
{
ds1302_burst_read(DS1302_READ_TIME); //讀取日期和時間
lcd_display_dateAndTime(); //1602顯示日期和時間
}
}
lcd1602.c
/*初始化LCD1602函式*/
void lcd_init()
{
unsigned char array1[] = "date: - - ";
unsigned char array2[] = "time: : : ";
write_com(CURSOR_RIGHT); //寫入資料后游標自動右移 整屏不移動, 0x40(游標左移 整屏不移動)0x05(左移 整屏右移)0x07(右移 整屏右移)
write_com(CLOSE_DIS_CUR); //開顯示功能 無游標 不閃爍
write_com(DIS_5X7); //資料總線8位 16X2顯示 5*7點陣
write_com(CLEAR_SCREEN); //清屏 0000 0001
lcd_display_str(0,0,array1); //第一行顯示 date: - -
lcd_display_str(0,1,array2); //第二行顯示 time: : :
}
/*LCD1602 顯示DS1302日期和時間 函式*/
void lcd_display_dateAndTime()
{
lcd_display_byte(5,0,(time[7]>>4)+48); //顯示年
lcd_display_byte(6,0,(time[7]&0x0f)+48);
lcd_display_byte(7,0,(time[6]>>4)+48); //顯示年
lcd_display_byte(8,0,(time[6]&0x0f)+48);
lcd_display_byte(10,0,(time[4]>>4)+48); //顯示月
lcd_display_byte(11,0,(time[4]&0x0f)+48);
lcd_display_byte(13,0,(time[3]>>4)+48); //顯示日
lcd_display_byte(14,0,(time[3]&0x0f)+48);
lcd_display_byte(5,1,(time[2]>>4)+48); //顯示時
lcd_display_byte(6,1,(time[2]&0x0f)+48);
lcd_display_byte(8,1,(time[1]>>4)+48); //顯示分
lcd_display_byte(9,1,(time[1]&0x0f)+48);
lcd_display_byte(11,1,(time[0]>>4)+48); //顯示秒
lcd_display_byte(12,1,(time[0]&0x0f)+48);
lcd_display_byte(14,1,(time[5]&0x0f)+48); //顯示周
}
ds1302.c
#include "ds1302.h"
unsigned char time[8] = {0x00,0x45,0x19,0x18,0x10,0x01,0x21,0x20};//秒分時 日月周 年
/*DS1302單位元組讀資料函式*/
unsigned char ds1302_readByte(unsigned char dat)
{
unsigned char i = 0;
for(i=0;i<8;i++)
{
dat = dat >> 1; //左移一次 低位開始 共有效左移7次
if(DAT == 1)
dat = dat | 0x80; //高位置1
else
dat = dat & 0x7F; //高位置0
CLK = 1; //時鐘拉高表示這位已經結束
CLK = 0; //時鐘拉低開始接收新的資料位
}
return dat;
}
/*DS1302單位元組寫地址或者資料函式*/
void ds1302_writeByte(unsigned char addrOrData)
{
unsigned char i = 0;
for(i=0;i<8;i++)
{
DAT = addrOrData & 0x01; //開始傳輸低位
addrOrData = addrOrData >> 1;//右移一位
CLK = 1; //拉高時鐘表示已經發送
CLK = 0; //拉低時鐘準備繼續放新的資料位
}
}
/*DS1302時鐘模塊寫命令函式*/
void ds1302_writeCom(unsigned char addr,unsigned char dat)
{
RST = 0; //拉低RST
CLK = 0; //拉低時鐘
RST = 1; //使能打開
ds1302_writeByte(addr); //寫入要寫的地址
ds1302_writeByte(dat); //寫入地址的資料
RST = 0; //關閉 表示結束
}
/*DS1302時鐘模塊讀資料函式*/
unsigned char ds1302_readData(unsigned char addr)
{
unsigned char dat = 0;
RST = 0; //拉低RST
CLK = 0; //拉低時鐘
RST = 1; //打開使能
ds1302_writeByte(addr); //寫入要讀的地址
dat = ds1302_readByte(dat); //讀取地址的資料
RST = 0; //關閉 表示結束
return dat; //回傳讀取到的資料
}
/*DS1302時鐘模塊讀取日期和時間函式*/
void ds1302_read_DateAndTime()
{
time[0] = ds1302_readData(DS1302_READ_YEAR); //讀取年
time[1] = ds1302_readData(DS1302_READ_MONTH); //讀取月
time[2] = ds1302_readData(DS1302_READ_DAY); //讀取日
time[3] = ds1302_readData(DS1302_READ_HOUR); //讀取時
time[4] = ds1302_readData(DS1302_READ_MINUTE);//讀取分
time[5] = ds1302_readData(DS1302_READ_SECOND);//讀取秒
time[6] = ds1302_readData(DS1302_READ_WEEK); //讀取周
}
/*DS1302時鐘模塊初始化函式*/
void ds1302_init()
{
RST = 0; //關閉RST
CLK = 0; //拉低時鐘
ds1302_writeCom(DS1302_WRITE_PROTECT,0x00); //關閉寫保護 這樣才能進行寫操作
ds1302_burst_write(DS1302_WRITE_TIME); //初始化全部時間
//ds1302_initTime(); //初始時間:2021年10月18日 19點45分00秒 周一
ds1302_writeCom(DS1302_WRITE_PROTECT,0x80); //開啟寫保護 只讀模式
}
專案展示

如果覺得這篇文章對你有用,歡迎大家點贊、評論哈哈
需要整個工程代碼,歡迎大家打賞,評論區留上你的郵箱 or vx or qq,o( ̄︶ ̄)o

繼續加油!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/323230.html
標籤:其他
上一篇:STM32學習筆記(CubeMX配HAL)(第六天:前面內容的一個綜合訓練)
下一篇:阿里云物聯網平臺實作MQTT通信
