一、前言
1.1 功能說(shuō)明
本項(xiàng)目以STC90C51單片機(jī)為核心,結(jié)合DS1302實(shí)時(shí)時(shí)鐘芯片和IIC協(xié)議的OLED顯示屏,設(shè)計(jì)了一款功能豐富、操作簡(jiǎn)便的電子時(shí)鐘。
【1】項(xiàng)目目標(biāo)
- 實(shí)現(xiàn)高精度的時(shí)間顯示,包括時(shí)、分、秒。
- 提供按鍵調(diào)整時(shí)間的功能,方便用戶校準(zhǔn)時(shí)間。
- 利用OLED顯示屏以直觀的方式展示時(shí)間信息。
【2】系統(tǒng)架構(gòu)
- 微控制器:采用STC90C51單片機(jī)作為核心控制器,負(fù)責(zé)整個(gè)系統(tǒng)的數(shù)據(jù)處理和邏輯控制。
- 實(shí)時(shí)時(shí)鐘芯片:選用DS1302作為實(shí)時(shí)時(shí)鐘芯片,提供高精度的時(shí)間信息。DS1302通過(guò)I2C接口與STC90C51進(jìn)行通信,實(shí)現(xiàn)時(shí)間的讀取和設(shè)置。
- 顯示屏:采用IIC協(xié)議的OLED顯示屏作為顯示設(shè)備,用于顯示時(shí)間信息。顯示屏與STC90C51通過(guò)SPI I2C接口連接,實(shí)現(xiàn)數(shù)據(jù)的傳輸和顯示。
- 按鍵模塊:設(shè)計(jì)一組按鍵用于調(diào)整時(shí)間。按鍵模塊通過(guò)GPIO接口與STC90C51連接,實(shí)現(xiàn)按鍵信號(hào)的輸入和識(shí)別。
【3】功能實(shí)現(xiàn)
- 時(shí)間顯示:STC90C51定時(shí)從DS1302讀取時(shí)間信息,并通過(guò)OLED顯示屏進(jìn)行顯示。顯示屏可以實(shí)時(shí)更新時(shí)間,保證時(shí)間的準(zhǔn)確性。
- 時(shí)間調(diào)整:用戶通過(guò)按鍵模塊輸入調(diào)整時(shí)間的指令,STC90C51根據(jù)指令對(duì)DS1302進(jìn)行設(shè)置,實(shí)現(xiàn)時(shí)間的校準(zhǔn)。
1.2 DS1302介紹
DS1302是由美國(guó)DALLAS公司推出的一款低功耗實(shí)時(shí)時(shí)鐘芯片,具有涓細(xì)電流充電能力。以下是對(duì)DS1302的詳細(xì)介紹:
【1】主要功能特點(diǎn)
- 計(jì)時(shí)功能:DS1302能夠?qū)δ辍⒃?、日、周、時(shí)、分、秒進(jìn)行精確計(jì)時(shí),并具備閏年補(bǔ)償功能,確保時(shí)間的準(zhǔn)確性。
- 低功耗:該芯片功耗極低,工作電壓在2.0V至5.5V范圍內(nèi),使得它非常適合在需要長(zhǎng)時(shí)間運(yùn)行且電源有限的設(shè)備中使用。
- 數(shù)據(jù)存儲(chǔ):DS1302內(nèi)部具有一個(gè)31×8的RAM寄存器,可用于臨時(shí)性存放數(shù)據(jù)。
- 雙電源引腳:DS1302擁有主電源/后備電源雙電源引腳設(shè)計(jì),可以在主電源關(guān)閉的情況下,通過(guò)后備電源保持時(shí)鐘的連續(xù)運(yùn)行。
- 串行I/O通信:采用串行I/O通信方式,相對(duì)于并行通信更節(jié)省IO口的使用。
【2】引腳說(shuō)明
DS1302共有8個(gè)引腳,包括:
- VCC2:主電源正極的引腳。
- X1和X2:晶振輸入和輸出引腳,外接32.768kHz晶振。
- GND:負(fù)極。
- CE:使能引腳,接單片機(jī)的IO口,用于啟動(dòng)和停止時(shí)鐘芯片的工作。
- I/O:數(shù)據(jù)傳輸引腳,接單片機(jī)的IO口,用于數(shù)據(jù)的讀寫(xiě)。
- SCLK:通信時(shí)鐘引腳,接單片機(jī)的IO口,用于同步數(shù)據(jù)傳輸。
- RST:復(fù)位/片選線,通過(guò)把RST輸入驅(qū)動(dòng)置高電平來(lái)啟動(dòng)所有的數(shù)據(jù)傳送。RST也有兩種功能:一是接通控制邏輯,允許地址/命令序列送入移位寄存器;二是提供終止單字節(jié)或多字節(jié)數(shù)據(jù)傳送的方法。
- VCC1:后備電源引腳,在主電源關(guān)閉時(shí),為DS1302提供電源。
【3】應(yīng)用領(lǐng)域
由于其穩(wěn)定可靠、易于使用和低功耗等特點(diǎn),DS1302被廣泛應(yīng)用于各個(gè)領(lǐng)域,包括:
- 電子產(chǎn)品:如手機(jī)、平板電腦等需要準(zhǔn)確顯示時(shí)間的設(shè)備中。
- 工業(yè)控制系統(tǒng):如自動(dòng)化生產(chǎn)線、儀器儀表等需要同步計(jì)時(shí)和記錄數(shù)據(jù)的設(shè)備中。
- 汽車電子系統(tǒng):如車載導(dǎo)航儀、車載音響等需要準(zhǔn)確顯示時(shí)間和日期信息的設(shè)備中。
二、代碼實(shí)現(xiàn)
2.1 main.c
#include <reg51.h>
#include "delay.h"
#include "type.h"
#include "uart.h"
#include "ds1302.h"
//#include "key.h"
//#include "led.h"
//#include "timer.h"
//#include "exti.h"
//#include "infrared.h"
//#include "ds18b20.h"
//#include "at24c02.h"
int main()
{
u8 stat;
UART_Init(); //初始化串口波特率為4800
DS1302_Init();
stat=DS1302_ReadByte(0x80|0x01);//讀取秒
if(stat&0x80)
{
DS1302_WriteTime(2020-2000,1,18,16,33,33,6);
}
else
{
printf("DS1302 OKrn");
}
while(1)
{
DS1302_ReadTime();
printf("DS1302:%d-%d-%d %d:%d:%d %drn",
(int)DS1302_TIME[0]+2000,
(int)DS1302_TIME[1],
(int)DS1302_TIME[2],
(int)DS1302_TIME[3],
(int)DS1302_TIME[4],
(int)DS1302_TIME[5],
(int)DS1302_TIME[6]
);
DelayMs(1000);
}
}
2.2 DS1302.c
#include"ds1302.h"
//定義ds1302使用的IO口
sbit DS1302_IO=P3^4;
sbit DS1302_RST=P3^5;
sbit DS1302_SCLK=P3^6;
u8 DS1302_TIME[7]; //存放讀取的時(shí)間
/*
函數(shù)功能: 將十進(jìn)制數(shù)據(jù)轉(zhuǎn)為BCD碼
*/
u8 DEC_TO_BCD(u8 val)
{
return ((val/10)<<4)+val%10;
}
/*
函數(shù)功能: 將BCD碼數(shù)據(jù)轉(zhuǎn)為十進(jìn)制格式
*/
u8 BCD_TO_DEC(u8 val)
{
return (val&0x0f)+(val>>4)*10;
}
void DS1302_Init(void)
{
DS1302_RST=0;
DS1302_SCLK=0;//先將DS1302_SCLK置低電平。
}
/*
函數(shù)功能: 向DS1302指定寄存器里寫(xiě)一個(gè)字節(jié)數(shù)據(jù)
*/
void DS1302_WriteByte(u8 addr,u8 dat)
{
u8 n;
DS1302_RST=1; //然后將DS1302_RST(CE)置高電平。
/*1. 設(shè)置寫(xiě)入的地址*/
for(n=0;n<8;n++)
{
DS1302_IO=addr&0x01;//數(shù)據(jù)從低位開(kāi)始傳送
addr>>=1;
DS1302_SCLK=1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
DS1302_SCLK=0;
}
/*2. 寫(xiě)入數(shù)據(jù)*/
for(n=0;n<8;n++)
{
DS1302_IO=dat&0x01;
dat>>=1;
DS1302_SCLK=1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
DS1302_SCLK=0;
}
DS1302_RST=0;//傳送數(shù)據(jù)結(jié)束
}
/*
函數(shù)功能: 從DS1302指定寄存器里讀取一個(gè)字節(jié)數(shù)據(jù)
*/
u8 DS1302_ReadByte(u8 addr)
{
u8 n=0,dat=0;
DS1302_RST=1; //然后將DS1302_RST(CE)置高電平。
/*1. 設(shè)置讀取的地址*/
for(n=0;n<8;n++)
{
DS1302_IO=addr&0x01;//數(shù)據(jù)從低位開(kāi)始傳送
addr>>=1;
DS1302_SCLK=1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
DS1302_SCLK=0;//DS1302下降沿時(shí),放置數(shù)據(jù)
}
/*2. 讀取數(shù)據(jù)*/
for(n=0;n<8;n++)
{
dat>>=1;
if(DS1302_IO)dat|=0x80;
DS1302_SCLK=1;
DS1302_SCLK=0;//DS1302下降沿時(shí),放置數(shù)據(jù)
}
DS1302_RST=0;
//必須的操作,復(fù)位時(shí)間
DS1302_IO=0;
DS1302_IO=1;
return dat;
}
/*
函數(shù)功能: 設(shè)置DS1302芯片的時(shí)間
DS1302的時(shí)間基準(zhǔn)是從2000年開(kāi)始的,設(shè)置年份時(shí)要減去2000再傳入設(shè)置
例如:DS1302_WriteTime(20,1,18,14,46,20,6);
*/
void DS1302_WriteTime(u8 year,u8 mon,u8 mday,u8 hour,u8 min,u8 sec,u8 week)
{
DS1302_WriteByte(0x8E,0x00); //禁止寫(xiě)保護(hù),就是關(guān)閉寫(xiě)保護(hù)功能
DS1302_WriteByte(0x8c,DEC_TO_BCD(year)); //設(shè)置年
DS1302_WriteByte(0x88,DEC_TO_BCD(mon)); //設(shè)置月
DS1302_WriteByte(0x86,DEC_TO_BCD(mday)); //設(shè)置日
DS1302_WriteByte(0x84,DEC_TO_BCD(hour)); //設(shè)置時(shí)
DS1302_WriteByte(0x82,DEC_TO_BCD(min)); //設(shè)置分
DS1302_WriteByte(0x80,DEC_TO_BCD(sec)); //設(shè)置秒
DS1302_WriteByte(0x8a,DEC_TO_BCD(week)); //設(shè)置星期
DS1302_WriteByte(0x8E,0x80); //打開(kāi)寫(xiě)保護(hù)功能
}
/*
函數(shù)功能: 讀取DS1302時(shí)鐘的時(shí)間
DS1302寄存器的最低位是讀寫(xiě)位,0是寫(xiě),1是讀
*/
void DS1302_ReadTime(void)
{
DS1302_TIME[0]=BCD_TO_DEC(DS1302_ReadByte(0x8c|0x01));//讀取年
DS1302_TIME[1]=BCD_TO_DEC(DS1302_ReadByte(0x88|0x01));//讀取月
DS1302_TIME[2]=BCD_TO_DEC(DS1302_ReadByte(0x86|0x01));//讀取日
DS1302_TIME[3]=BCD_TO_DEC(DS1302_ReadByte(0x84|0x01));//讀取時(shí)
DS1302_TIME[4]=BCD_TO_DEC(DS1302_ReadByte(0x82|0x01));//讀取分
DS1302_TIME[5]=BCD_TO_DEC(DS1302_ReadByte(0x80|0x01));//讀取秒
DS1302_TIME[6]=BCD_TO_DEC(DS1302_ReadByte(0x8a|0x01));//讀取星期
}
2.2 ds1302.h
#ifndef _DS1302_H
#define _DS1302_H
#include "type.h"
#include <reg51.h>
#include "delay.h"
#include "type.h"
#include "uart.h"
#include <intrins.h>
//定義全局函數(shù)
u8 DEC_TO_BCD(u8 val); //十進(jìn)制轉(zhuǎn)BCD碼
u8 BCD_TO_DEC(u8 val); //BCD碼轉(zhuǎn)十進(jìn)制
u8 DS1302_ReadByte(u8 addr);
void DS1302_WriteByte(u8 addr,u8 dat);
void DS1302_WriteTime(u8 year,u8 mon,u8 mday,u8 hour,u8 min,u8 sec,u8 week);
void DS1302_ReadTime(void);
void DS1302_Init(void);
//加入全局變量
extern u8 DS1302_TIME[7];
#endif
閱讀全文