一、模塊介紹
DS1302時鐘模塊是一款由美國DALLAS公司生產(chǎn)的高性能、低功耗的實時時鐘芯片。它可以對年、月、日、時、分、秒進(jìn)行計時,并具有閏年補(bǔ)償功能。該芯片內(nèi)部集成了一個31字的RAM寄存組,用于臨時存放數(shù)據(jù)。其接口簡單,與TTL兼容。 以下是DS1302時鐘模塊的主要特點:
1. 實時時鐘:DS1302可以準(zhǔn)確地計時年、月、日、時、分、秒,適用于需要精確時間控制的場合。
2. 閏年補(bǔ)償:DS1302能夠自動進(jìn)行閏年補(bǔ)償,確保日歷數(shù)據(jù)的準(zhǔn)確性。
3. 低功耗:DS1302在正常工作狀態(tài)下功耗較低,有利于延長系統(tǒng)續(xù)航時間。
4. 涓流充電:DS1302具備涓流充電功能,可以對備用電源進(jìn)行充電,提高了系統(tǒng)的可靠性。
5. 3線接口:DS1302采用簡單的3線接口與微處理器通訊,便于集成到各種系統(tǒng)中。
6. 兼容性:DS1302與DS1202兼容,可以替代DS1202在相關(guān)應(yīng)用中使用。
7. 寬電壓范圍:DS1302的工作電壓范圍為2.5V至5.5V,適應(yīng)不同電源環(huán)境。
DS1302時鐘模塊在許多應(yīng)用領(lǐng)域都有廣泛的應(yīng)用,如嵌入式系統(tǒng)、智能家居、工業(yè)自動化等。通過與單片機(jī)等微處理器配合使用,可以實現(xiàn)實時時間顯示、數(shù)據(jù)記錄等功能。
二、資料獲取
關(guān)注微信公眾號--星之援工作室 發(fā)送關(guān)鍵字(DS1302)
????
?效果展示
接線規(guī)則(可在ds1302.h中自行修改)
/*
DS1302接口:
VCC -> 5.0/3.3
GND -> GND
GPIOB_14 ->DS1302_RST
GPIOB_13 ->DS1302_DAT
GPIOB_12 ->DS1302_CLK
*/
三、代碼編寫
main
用于顯示處理,當(dāng)時鐘模塊的秒更新之后就會通過串口輸出
/*--------------------------------------------------------*
* *
* 星之援網(wǎng)絡(luò)科技工作室學(xué)習(xí)資料v1.0 *
* 時間:2022.7.14 *
* 程序介紹:DS1302實驗 *
* 實現(xiàn)效果:串口輸出系統(tǒng)時間 *
* *
*--------------------------------------------------------*
*/
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include "ds1302.h"
int main(void)
{
DS1302_Time_t time = {0};
char str[50];
u8 sec=0;
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級,2位響應(yīng)優(yōu)先級
// LED 端口初始化
LED_GPIO_Config();
// KEY 初始化
Key_GPIO_Config();
// 串口初始化
uart_init(115200);
//初始化ds1302端口
DS1302_Init();
printf("init okn");
while(1)
{
DS1302_GetTime(&time); //讀取此時時刻
if(sec==time.second)//判斷秒鐘數(shù)是否有更新
{
delay_ms(5);//沒有更新便延時5ms
}
else
{
sec=time.second;//秒鐘數(shù)有更新,則將變量sec更新
sprintf(str,"Data: %d-%d-%d Time: %d:%d:%d ",time.year,time.month,time.day,
time.hour,time.minute,time.second);
printf("%sn",str);
}
}
}
ds1302.c
驅(qū)動代碼
#include "ds1302.h"
#include "delay.h"
/*
DS1302接口:
VCC -> 5.0/3.3
GND -> GND
GPIOB_14 ->DS1302_RST
GPIOB_13 ->DS1302_DAT
GPIOB_12 ->DS1302_CLK
*/
//DS1302地址定義
#define DS1302_SEC_ADDR 0x80 //秒數(shù)據(jù)地址
#define DS1302_MIN_ADDR 0x82 //分?jǐn)?shù)據(jù)地址
#define DS1302_HOUR_ADDR 0x84 //時數(shù)據(jù)地址
#define DS1302_DAY_ADDR 0x86 //日數(shù)據(jù)地址
#define DS1302_MONTH_ADDR 0x88 //月數(shù)據(jù)地址
#define DS1302_WEEK_ADDR 0x8a //星期數(shù)據(jù)地址
#define DS1302_YEAR_ADDR 0x8c //年數(shù)據(jù)地址
#define DS1302_CONTROL_ADDR 0x8e //控制數(shù)據(jù)地址
#define DS1302_CHARGER_ADDR 0x90 //充電功能地址
#define DS1302_CLKBURST_ADDR 0xbe
//初始時間定義
static u8 time_buf[8] = {0x20,0x19,0x04,0x12,0x15,0x07,0x00,0x06};//初始時間2019年4月12號15點07分00秒 星期五
u8 sec_buf=0; //秒緩存
u8 sec_flag=0; //秒標(biāo)志位
void DS1302_Init()//CE,SCLK端口初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(CE_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = CE_GPIO_PIN; //PC.11 CE
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
GPIO_Init(CE_GPIO_PORT, &GPIO_InitStructure);//初始化GPIOC.11
GPIO_ResetBits(CE_GPIO_PORT,CE_GPIO_PIN);
GPIO_InitStructure.GPIO_Pin = SCLK__GPIO_PIN; //PC.12 SCLK
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
GPIO_Init(SCLK__GPIO_PORT, &GPIO_InitStructure);//初始化GPIOC.12
GPIO_ResetBits(SCLK__GPIO_PORT,SCLK__GPIO_PIN);
}
//配置雙向I/O端口為輸出態(tài)
static void ds1032_DATAOUT_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(DATA_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = DATA__GPIO_PIN; //PC.10 DATA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(DATA__GPIO_PORT, &GPIO_InitStructure);//初始化GPIOC.10
GPIO_ResetBits(DATA__GPIO_PORT,DATA__GPIO_PIN);
}
//配置雙向I/O端口為輸入態(tài)
static void ds1032_DATAINPUT_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(DATA_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = DATA__GPIO_PIN; //PC.10 DATA
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DATA__GPIO_PORT, &GPIO_InitStructure);//初始化GPIOC.10
}
//向DS1302寫入一字節(jié)數(shù)據(jù)
void DS1302_WriteByte(u8 addr,u8 data)
{
u8 i;
DS1302_RST=0; //禁止數(shù)據(jù)傳輸 ?。?!這條很重要
DS1302_CLK=0; //確保寫數(shù)據(jù)前SCLK為低電平
DS1302_RST=1; //啟動DS1302總線
ds1032_DATAOUT_init();
addr=addr&0xFE; //最低位置零,寄存器0位為0時寫,為1時讀
for(i=0;i<8;i++) //寫入目標(biāo)地址:addr
{
if (addr&0x01) DS1302_OUT=1;
else DS1302_OUT=0;
DS1302_CLK=1; //時鐘上升沿寫入數(shù)據(jù)
DS1302_CLK=0;
addr=addr>>1;
}
for (i=0;i<8;i++) //寫入數(shù)據(jù):data
{
if(data&0x01) DS1302_OUT=1;
else DS1302_OUT=0;
DS1302_CLK=1; //時鐘上升沿寫入數(shù)據(jù)
DS1302_CLK=0;
data = data >> 1;
}
DS1302_CLK=1; // 將時鐘電平置于高電平狀態(tài) ,處于已知狀態(tài)
DS1302_RST=0; //停止DS1302總線
}
//從DS1302讀出一字節(jié)數(shù)據(jù)
u8 DS1302_ReadByte(u8 addr)
{
u8 i,temp;
DS1302_RST=0; //這條很重要
DS1302_CLK=0; //先將SCLK置低電平,確保寫數(shù)居前SCLK被拉低
DS1302_RST=1; //啟動DS1302總線
ds1032_DATAOUT_init();
//寫入目標(biāo)地址:addr
addr=addr|0x01; //最低位置高,寄存器0位為0時寫,為1時讀
for(i=0;i<8;i++)
{
if (addr&0x01) DS1302_OUT=1;
else DS1302_OUT=0;
DS1302_CLK=1; //寫數(shù)據(jù)
DS1302_CLK=0;
addr = addr >> 1;
}
//從DS1302讀出數(shù)據(jù):temp
ds1032_DATAINPUT_init();
for(i=0;i<8;i++)
{
temp=temp>>1;
if (DS1302_IN) temp|=0x80;
else temp&=0x7F;
DS1302_CLK=1;
DS1302_CLK=0;
}
DS1302_CLK=1; //將時鐘電平置于已知狀態(tài)
DS1302_RST=0; //停止DS1302總線
return temp;
}
//向DS1302寫入時鐘數(shù)據(jù),用于時間校準(zhǔn)修改
void DS1302_WriteTime()
{
DS1302_WriteByte(DS1302_CONTROL_ADDR,0x00); //關(guān)閉寫保護(hù)
DS1302_WriteByte(DS1302_SEC_ADDR,0x80); //暫停時鐘
//DS1302_WriteByte(DS1302_CHARGER_ADDR,0xa9); //涓流充電
DS1302_WriteByte(DS1302_YEAR_ADDR,time_buf[1]); //年
DS1302_WriteByte(DS1302_MONTH_ADDR,time_buf[2]); //月
DS1302_WriteByte(DS1302_DAY_ADDR,time_buf[3]); //日
DS1302_WriteByte(DS1302_HOUR_ADDR,time_buf[4]); //時
DS1302_WriteByte(DS1302_MIN_ADDR,time_buf[5]); //分
DS1302_WriteByte(DS1302_SEC_ADDR,time_buf[6]); //秒
DS1302_WriteByte(DS1302_WEEK_ADDR,time_buf[7]); //周
DS1302_WriteByte(DS1302_CHARGER_ADDR,0xA5);//打開充電功能 選擇2K電阻充電方式
DS1302_WriteByte(DS1302_CONTROL_ADDR,0x80);//打開寫保護(hù)
}
//從DS1302讀出時鐘數(shù)據(jù)
void DS1302_ReadTime(void)
{
time_buf[1]=DS1302_ReadByte(DS1302_YEAR_ADDR); //年
time_buf[2]=DS1302_ReadByte(DS1302_MONTH_ADDR); //月
time_buf[3]=DS1302_ReadByte(DS1302_DAY_ADDR); //日
time_buf[4]=DS1302_ReadByte(DS1302_HOUR_ADDR); //時
time_buf[5]=DS1302_ReadByte(DS1302_MIN_ADDR); //分
time_buf[6]=(DS1302_ReadByte(DS1302_SEC_ADDR))&0x7f; //秒,屏蔽秒的第7位,避免超出59
time_buf[7]=DS1302_ReadByte(DS1302_WEEK_ADDR); //周
}
//主函數(shù)
void DS1302_GetTime(DS1302_Time_t* time)
{
DS1302_ReadTime(); //讀取時間
time->year=(time_buf[0]>>4)*1000+(time_buf[0]&0x0F)*100+(time_buf[1]>>4)*10+(time_buf[1]&0x0F); //計算年份
time->month=(time_buf[2]>>4)*10+(time_buf[2]&0x0F); //計算月份
time->day=(time_buf[3]>>4)*10+(time_buf[3]&0x0F); //計算日期
time->hour=(time_buf[4]>>4)*10+(time_buf[4]&0x0F); //計算小時
time->minute=(time_buf[5]>>4)*10+(time_buf[5]&0x0F); //計算分鐘
time->second=(time_buf[6]>>4)*10+(time_buf[6]&0x0F); //計算秒鐘
time->week=(time_buf[7]&0x0F); //計算星期
//printf("時間:%d-%d-%d %d:%d:%d %d n",TimeData.year,TimeData.month,TimeData.day,TimeData.hour,TimeData.minute,TimeData.second,TimeData.week);
}
ds1302.h
參數(shù)定義
#ifndef __ds1302_H
#define __ds1302_H
#include "sys.h"
/*
DS1302接口:
VCC -> 5.0/3.3
GND -> GND
GPIOB_14 ->DS1302_RST
GPIOB_13 ->DS1302_DAT
GPIOB_12 ->DS1302_CLK
*/
/* 定義LED連接的GPIO端口, 用戶只需要修改下面的代碼即可改變控制的LED引腳 */
#define CE_GPIO_PORT GPIOB /* GPIO端口 */
#define CE_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口時鐘 */
#define CE_GPIO_PIN GPIO_Pin_14 /* 連接到SCL時鐘線的GPIO */
#define SCLK__GPIO_PORT GPIOB /* GPIO端口 */
#define SCLK_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口時鐘 */
#define SCLK__GPIO_PIN GPIO_Pin_12 /* 連接到SCL時鐘線的GPIO */
#define DATA__GPIO_PORT GPIOB /* GPIO端口 */
#define DATA_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口時鐘 */
#define DATA__GPIO_PIN GPIO_Pin_13 /* 連接到SCL時鐘線的GPIO */
//DS1302引腳定義,可根據(jù)實際情況自行修改端口定義
//#define DS1302_OutPut_Mode() {GPIOB->CRL &= 0xF0FFFFFF;GPIOB->CRL |= 0x03000000;}//將 GPIOA 口的 PA6 引腳設(shè)置成推挽輸出模式,并清空了其他引腳的配置
//#define DS1302_InPut_Mode() {GPIOB->CRL &= 0xF0FFFFFF;GPIOB->CRL |= 0x08000000;}//PA7 引腳既可以作為普通的 GPIO 輸出口
#define DS1302_IN PBin(13)
#define DS1302_OUT PBout(13)
#define DS1302_RST PBout(14)
#define DS1302_CLK PBout(12)
typedef struct TIMEData
{
u16 year;
u8 month;
u8 day;
u8 hour;
u8 minute;
u8 second;
u8 week;
}DS1302_Time_t;
//創(chuàng)建TIMEData結(jié)構(gòu)體方便存儲時間日期數(shù)據(jù)
void DS1302_Init(void);
void DS1302_WriteByte(u8 addr,u8 data);
u8 DS1302_ReadByte(u8 addr);
void DS1302_WriteTime(void);
void DS1302_ReadTime(void);
void DS1302_GetTime(DS1302_Time_t* time);
#endif
四、參考
基于STM32的DS1302時鐘模塊驅(qū)動程序https://blog.csdn.net/qq_43270506/article/details/104952746?ops_request_misc=&request_id=&biz_id=102&utm_term=stmDS1302&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-4-104952746.142%5Ev96%5Epc_search_result_base7&spm=1018.2226.3001.4187
STM32基于標(biāo)準(zhǔn)庫工程驅(qū)動DS1302https://blog.csdn.net/weixin_42880082/article/details/129941871?ops_request_misc=&request_id=&biz_id=102&utm_term=stm%20DS1302&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~sobaiduweb~default-4-129941871.nonecase&spm=1018.2226.3001.4450
完整代碼請關(guān)注公眾號進(jìn)行獲取和咨詢
聯(lián)系方式 微信號:13648103287