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