找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 19651|回復: 15
打印 上一主題 下一主題
收起左側

單片機電子時鐘設計-DS1302 1602 可調鬧鐘

  [復制鏈接]
跳轉到指定樓層
樓主
ID:467200 發(fā)表于 2019-1-12 23:01 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
摘要
隨著單片機技術的飛速發(fā)展,在其推動下,現(xiàn)代的電子產品幾乎滲透到了社會的各個領域,有力地推動了社會生產力的發(fā)展和社會信息化程度的提高,同時也使現(xiàn)代電子產品性能進一步提高。
時間就是金錢、時間就是生命、時間就是勝利……,準確的掌握時間和分配時間對人們來說至關重要,時鐘是我們生活中必不可少的工具。電子鐘的設計方法有很多種,但是基于單片機并通過LCD顯示的電子時鐘具有編程靈活、精確度高、便于攜帶、顯示直觀等特點。
    利用STC89C52單片機對DS1302時鐘芯片進行讀寫操作并通過1602字符液晶顯示實時時鐘信息,這樣便構成了一個單片機電子時鐘。

目錄

緒論
概述
研究目的
第1章 設計要求與方案論證
1.1 設計要求
1.2 系統(tǒng)基本方案選擇和論證
1.2.1 單片機芯片的選擇方案和論證
1.2.2 顯示模塊選擇方案和論證
1.2.3 時鐘芯片的選擇方案和論證2
1.3 電路設計最終方案決定
第2章 主要元件介紹3
2.1  STC89C52以及最小系統(tǒng)介紹3
2.1.1  STC89C52主要功能及PDIP封裝
2.1.2  STC89C52引腳介紹
2.1.3  STC89C52最小系統(tǒng)4
2.2  DS1302時鐘芯片以及集成時鐘模塊介紹5
2.2.1  DS1302概述6
2.2.2  DS1302引腳介紹6
2.2.3  DS1302使用方法6
        2.2.4  時鐘集成模塊內部原理圖以及實物圖8
2.3 1602字符液晶以及顯示模塊介紹
2.3.1 1602液晶概述
2.3.2 1602引腳介紹
2.3.3 1602字符液晶使用方法
2.3.4 LCD顯示模塊原理圖13
第3章 系統(tǒng)硬件設計
3.1 電路設計框圖
3.2 系統(tǒng)硬件概述
第4章 系統(tǒng)的軟件設計
4.1 程序流程框圖
第5章 系統(tǒng)測試與總結
5.1 系統(tǒng)測試17
5.2 總結17
致謝18
參考文獻18
源程序清單18
附錄35

概述
時間,對人們來說是非常寶貴的,準確的掌握時間和分配時間對人們來說至關重要。因此自從時鐘發(fā)明的那刻起,就成為人類的好朋友。隨著時間的流逝,科學技術的不斷發(fā)展和提高,人們對時間計量的精度要求越來越高,應用越來越廣。怎樣讓時鐘更好、更方便、更精確的顯示時間,這就要求人們不斷設計研發(fā)出新型的時鐘。
高精度的計時工具大多數(shù)都使用了石英晶體振蕩器,由于電子鐘,石英表,石英鐘都采用了石英技術,因此走時精度高,穩(wěn)定性好,使用方便,不需要經(jīng)常調校。數(shù)字式電子鐘用集成電路計時時,譯碼代替機械式傳動,用LED顯示器代替指針進而顯示時間,減小了計時誤差,這種表具有時,分,秒顯示時間的功能,還可以進行時和分的校對,片選的靈活性好。
時鐘電路在計算機系統(tǒng)中起著非常重要的作用,是保證系統(tǒng)正常工作的基礎。在單片機的應用系統(tǒng)中,時鐘有兩個方面的含義:一是指為保障系統(tǒng)正常工作的基準振蕩定時信號,主要由晶振和外圍電路組成,晶振頻率的大小決定了單片機系統(tǒng)工作的快慢;二是指系統(tǒng)的標準定時時鐘,即定時時間,它通常有兩種實現(xiàn)方法:一是用軟件實現(xiàn),即用單片機內部的可編程定時器/計數(shù)器來實現(xiàn);二是用專門的時鐘芯片實現(xiàn)。
研究目的
通過利用STC89C52單片機和DS1302芯片以及外圍的按鍵和LCD顯示器等部件,設計一個基于單片機的電子時鐘。設計的電子時鐘通過液晶顯示器顯示,并能通過按鍵對時間以及鬧鐘進行設置。
   第1章 設計要求與方案論證
1
.1 設計要求
  • 具有年、月、日、星期、時、分、秒顯示功能()
  • 具備年、月、日、星期、時、分、秒校準功能
  • 具有鬧鐘顯示、調節(jié)設定、鳴叫功能

1.2 系統(tǒng)基本方案選擇和論證
1
.2.1 單片機芯片的選擇方案和論證:
方案一:
采用STC89C52芯片作為硬件核心。STC89C52內部具有8KB ROM 存儲空間,512字節(jié)數(shù)據(jù)存儲空間,帶有2K字節(jié)的EEPROM存儲空間,與MCS-51系列單片機完全兼容,STC89C52可以通過串口下載。
方案二:
   采用AT89S52。AT89S52片內具有8K字節(jié)程序存儲空間,256字節(jié)的數(shù)據(jù)存儲空間沒有EEPROM存儲空間,也與MCS-51系列單片機完全兼容,具有在線編程可擦除技術。
              兩種單片機都完全能夠滿足設計需要,STC89C52相對ATS89C52價格便宜,且抗干擾能力強?紤]到成本因素,因此選用STC89C52。

1.2.2 顯示模塊選擇方案和論證:
方案一:
     采用點陣式數(shù)碼管顯示。點陣式數(shù)碼管是由八行八列的發(fā)光二極管組成,對于顯示文字比較適合,如采用在顯示數(shù)字顯得太浪費,且也相對較高,所以不用此種作為顯示。
方案二:
采用LED數(shù)碼管動態(tài)掃描。LED數(shù)碼管價格便宜,對于顯示數(shù)字最合適,但功耗較大,且顯示容量不夠,所以也不用此種方案。
方案三:
   采用LCD液晶顯示屏。液晶顯示屏的顯示功能強大,可顯示大量文字,顯示多樣,清晰可見,且價格適中,所以采用了LCD數(shù)碼管作為顯示。

1.2.3 時鐘芯片的選擇方案和論證:
方案一:
   直接采用單片機定時計數(shù)器提供秒信號,使用程序實現(xiàn)年、月、日、星期、時、分、秒計數(shù)。采用此種方案雖然減少芯片的使用,節(jié)約成本,但是,實現(xiàn)的時間誤差較大。所以不采用此方案。
方案二:
  采用DS1302時鐘芯片實現(xiàn)時鐘,DS1302芯片是一種高性能的時鐘芯片,可自動對秒、分、時、日、周、月、年以及閏年補償?shù)哪赀M行計數(shù),而且精度高,工作電壓2.5V~5.5V范圍內,2.5V時耗電小于300nA.

1.3 電路設計最終方案決定
綜上各方案所述,對此次作品的方案選定: 采用STC89C52單片機作為主控制系統(tǒng);采用DS1302作為時鐘芯片;采用1602 LCD液晶作為顯示器件。

2.2  DS1302時鐘芯片以及時鐘集成模塊介紹
2.2.1  DS1302概述
DS1302 是美國DALLAS公司推出的一種高性能、低功耗、帶RAM的實時時鐘芯片,它可以對年、月、日、周日、時、分、秒進行計時,具有閏年補償功能,工作電壓為2.5V~5.5V。采用雙電源供電(主電源和備用電源),同時提供了對后背電源進行涓細電流充電的能力。采用三線接口與CPU進行同步通信
圖4:DS1302封裝圖

2.2.2  DS1302引腳介紹
各引腳功能為:
Vcc:    主電源;Vcc2:備用電源。當Vcc2>Vcc1+0.2V時,由Vcc2向DS1302供電;當Vcc2<Vcc1時,由Vcc1向DS1302供電。
SCLK:串行時鐘輸入端,控制數(shù)據(jù)的輸入與輸出
I/O:   三線接口時的雙向數(shù)據(jù)線
CE:   輸入信號,在讀、寫數(shù)據(jù)期間必須為高

2.2.3  DS1302使用方法
(1) 時鐘芯片DS1302的工作原理:
     DS1302在每次進行讀、寫程序前都必須初始化,先把SCLK端置 “0”,接著把RST端置“1”,最后才給予SCLK脈沖;讀/寫時序如圖5所示。表2為DS1302的控制字,此控制字的位7必須置1,若為0則不能把對DS1302進行讀寫數(shù)據(jù)。對于位6,若對程序進行讀/寫時RAM=1,對時間進行讀/寫時,CK=0。位1至位5指操作單元的地址。位0是讀/寫操作位,進行讀操作時,該位為1;該位為0則表示進行的是寫操作?刂谱止(jié)總是從最低位開始輸入/輸出的。表6為DS1302的日歷、時間寄存器內容:“CH”是時鐘暫停標志位,當該位為1時,時鐘振蕩器停止,DS1302處于低功耗狀態(tài);當該位為0時,時鐘開始運行!癢P”
是寫保護位,在任何的對時鐘和RAM的寫操作之前,WP必須為0。當“WP”為1時,寫保護位防止對任一寄存器的寫操作。
(2) DS1302的控制字節(jié)
DS1302的控制字如表所示。控制字節(jié)最高有效位(位7)必須是邏輯1,如果它為0,則不能把數(shù)據(jù)寫入DS1302中,位6如果0,則表示存取日歷時鐘數(shù)據(jù),為1表示存取RAM數(shù)據(jù);位5至位1指示操作單元的地址;最低有效位(位0)如為0表示要進行寫操作,為1表示進行讀操作,控制字節(jié)總是從最低位開始傳輸
1
RAM
A4
A3
A2
A1
A0
RD
CK
WR

表2:DS1302控制字
(3) 數(shù)據(jù)輸入輸出(I/O)
在控制指令字輸入后的下一個SCLK時鐘的上升沿時,數(shù)據(jù)被寫入DS1302,數(shù)據(jù)輸入從低位即位0開始。同樣,在緊跟8位的控制指令字后的下一個SCLK脈沖的下降沿讀出DS1302的數(shù)據(jù),讀出數(shù)據(jù)時從低位0位到高位7。其讀寫時序如圖示
圖5:DS1302讀寫時序
(4)DS1302寄存器
DS1302中與時間、日期有關的寄存器共有12個,其中7個存放數(shù)據(jù)的格式為BCD碼格式,其讀寫地址如下表所示
讀寄存器
寫寄存器
Bit7
Bit7
Bit7
Bit7
Bit7
Bit7
Bit7
Bit7
范圍
81H
80H
CH
10秒
00--59
83H
82H

10分
00--59
85H
84H
12
0
10
0--23
24
AM/PM
1--12
87H
86H


10日
1--31
89H
88H



10月
1--12
8BH
8AH
0
0
0
0
0
1--7
8DH
8CH
10年
00--99
8FH
8EH
WP
0
0
0
0
0
0
0
――
表3:DS1302時鐘寄存器
第一行秒寄存器,CH為時鐘暫停標志位,該位為1時時鐘停止,該位為0時時鐘運行
第二行分寄存器,bit0~bit6表示分鐘數(shù),因采用BCD編碼,所以低四位最大能表示的數(shù)字為9,計數(shù)滿向高三位進1。
第三行時寄存器,12/24用來定義DS1302小時的運行模式,12小時模式下bit5為1表示PM下午,bit5為0表示AM上午
第八行控制寄存器,bit7是寫保護位WP,當WP為1時,寫保護位可防止對任一寄存器的寫操作,在任何的對時鐘和RAM的寫操作之前,WP位必須為0
此外,DS1302 還有年份寄存器、控制寄存器、充電寄存器、時鐘突發(fā)寄存器及與RAM相關的寄存器等。時鐘突發(fā)寄存器可一次性順序讀寫除充電寄存器外的所有寄存器內容。 DS1302與RAM相關的寄存器分為兩類:一類是單個RAM單元,共31個,每個單元組態(tài)為一個8位的字節(jié),其命令控制字為C0H~FDH,其中奇數(shù)為讀操作,偶數(shù)為寫操作;另一類為突發(fā)方式下的RAM寄存器,此方式下可一次性讀寫所有的RAM的31個字節(jié),命令控制字為FEH(寫)、FFH(讀)。
2.2.4  時鐘集成模塊內部原理圖以及實物圖
       圖6:DS1302內部原理圖
圖7:DS1302實物圖

2. 3  1602字符液晶以及顯示模塊介紹2.3.1  1602液晶概述
工業(yè)字符型液晶,1602是指顯示的內容為16*2,即能夠同時顯示兩行,每行16個字符。常見的1602字符液晶有兩種,一種顯示的是綠色背光黑色字體,另一種顯示藍色背光白色字體,目前市面上字符液晶絕大多數(shù)是基于HD44780液晶芯片的,控制原理是完全相同的。本課題所用1602液晶模塊,顯示屏是藍色背光白色字體。如圖6所示
圖8:1602字符液晶
2.3.2 1602引腳介紹
編號
符號
引腳說明
編號
符號
引腳說明
1
GND
電源地
2
VCC
電源正極
3
VO
液晶顯示對比度調節(jié)端
4
RS
數(shù)據(jù)/命令選擇端
5
R/W
讀寫選擇
6
E
使能信號
7
D0
數(shù)據(jù)口
8
D1
數(shù)據(jù)口
9
D2
數(shù)據(jù)口
10
D3
數(shù)據(jù)口
11
D4
數(shù)據(jù)口
12
D5
數(shù)據(jù)口
13
D6
數(shù)據(jù)口
14
D7
數(shù)據(jù)口
15
BLA
背光電源正
16
BLK
背光電源負
表4:1602字符液晶引腳說明
各個引腳具體功能說明:
第1腳:GND為地電源。
第2腳:VCC接5V正電源。
第3腳:VO為液晶顯示器對比度調整端,接正電源時對比度最弱,接地電源時對比度最高,對比度過高時會產生重影,使用一個1K的電位器調整對比度。
第4腳:RS為寄存器選擇,高電平時選擇數(shù)據(jù)寄存器,低電平時選擇指令寄存器。
第5腳:R/W為讀寫信號線,高電平時進行讀操作,低電平時進行寫操作。
第6腳:E端為使能端,當E端由高電平跳變成低電平時,液晶模塊執(zhí)行命令。
第7~14腳:DB0~DB7為8位雙向數(shù)據(jù)線。
第15~16腳:背光燈電源。
2.3.3  1602字符液晶使用方法
(1)基本操作時序
操作
輸入
輸出
讀狀態(tài)
RS=L,RW=H,E=H
D0~D7=狀態(tài)字
寫指令
RS=L,RW=L,D0~D7=指令碼,E=高脈沖
讀數(shù)據(jù)
RS=H,RW=H,E=H
D0~D7=數(shù)據(jù)
寫數(shù)據(jù)
RS=H,RW=L,D0~D7=數(shù)據(jù),E=高脈沖
圖9:1602液晶讀時序圖
圖10:1602液晶寫時序圖
(2)RAM            
1602液晶控制器芯片內部帶有80個8位的RAM緩沖區(qū),其地址和屏幕的對應關系如圖7示
圖11
(3)1602字符液晶字庫
     1602液晶模塊內部的字符發(fā)生存儲器(CGROM)已經(jīng)存儲了160個不同的點陣字符圖形,如下表所示,這些字符有:阿拉伯數(shù)字、英文字母的大小寫、常用的符號、和日文假名等,每一個字符都有一個固定的代碼,比如大寫的英文字母“A”的代碼是01000001B(41H),顯示時模塊把地址41H中的點陣字符圖形顯示出來,我們就能看到字母“A”

2.3.4 LCD顯示模塊原理圖

圖13 LCD顯示模塊原理圖


第3章 系統(tǒng)硬件設計
3.1 電路設計框圖
圖14:硬件框圖
3.2 系統(tǒng)硬件概述
電路以STC89C52單片機最小系統(tǒng)為控制核心,時鐘電路由高精度低功耗的DS1302提供,采用三線接口與CPU進行同步通信,輸入部分采用四個獨立式按鍵S1、S2、S3、S4。1602液晶顯示部分,D0-D7口與單片機P0口相連。具體電路連接,詳見附錄1

4章 系統(tǒng)的軟件設計
4.1程序流程框圖
圖15:主程序框圖

圖16:按鍵程序圖
第五章 系統(tǒng)測試與總結
5.1 系統(tǒng)測試

從開始準備到寫完論文大概花了一周時間,原理圖和PCB制作花了一天時間,在這期間主要遇到的問題是Altium Designer軟件的使用,遇到問題主要到百度上查找答案,PCB做出之后緊接著就是焊接元器件,這部分由于粗心將電解電容正負極焊反,后面經(jīng)過萬用表不斷的測試才判斷出來,及時糾正過來,焊接與硬件調試大概花了半天時間。緊接著大部分的時間都花費在硬件與軟件的結合調試上,在調試過程中使用自己在網(wǎng)上買的51單片機開發(fā)板上進行一步一步的調試。由于是第一次做課程設計,同時也是第一次寫這么綜合的程序,所以在調試過程中遇到很多問題,一部分是關于DS1302與1602的硬件特點以及在硬件的基礎之上驅動程序的調用,這里主要是網(wǎng)上找資料去學會調用與編寫,主要是通過網(wǎng)上視頻教學 ;另一部分是自己做的硬件存在很多誤差,特別是電源供電部分,剛開始是用廢棄的鼠標上的那個USB接口線插在電腦上供電,但由于電源介入硬件的是兩個排針,所以很不穩(wěn)定,1602上總亂碼,或者5個按鍵隨便一個按下都是復位,而且從電腦輸出5V接到硬件系統(tǒng)后只有4.5V了,想了一下,最后拿出上學期期末自己做的電源將它調節(jié)到6V后,接入硬件系統(tǒng)就能達到5V。


5.2 總結

通過本次論文設計,使我加深了對單片機的認識,并且熟悉了單片機系統(tǒng)的設計流程,收獲豐碩。功能上基本達標:時鐘與鬧鐘的顯示,調時間和鬧鐘功能以及鬧鐘鳴叫功能。時鐘與鬧鐘顯示功能,精確度完全可以滿足日常生活顯示時間的需要;調時間與鬧鐘功能,方便快捷。硬件設施基本合乎要求,軟件設計可以配合硬件實現(xiàn)其功能。
技術在不斷進步,機械式時鐘已經(jīng)被淘汰,取而代之的是具有高度準確性和直觀性且無機械裝置,具有更長的使用壽命等優(yōu)點的電子時鐘。電子時鐘更具人性化,更能提高人們的生活質量,更受人們歡迎。機械時代已經(jīng)遠去,電子時代已經(jīng)到來。做為新時代的我們,更應該提高自身能力,適應新時代的發(fā)展。知識來自實踐,多從生活中探尋所需要的。
從這次的論文設計中,我真正的體會到,知識的重要性,特別是要理論聯(lián)系實際,把我們所學的理論知識運用到實際生活當中,要用知識改變一切。

附錄一:



                      系統(tǒng)原理圖



附錄二:


                         PCB


附錄三:
首先上電進入歡迎界面,如上圖所示,顯示5S鐘。
上電后的整體外觀圖,各按鍵的功能都有標注
按K1進入調時狀態(tài)按得次數(shù)不同光標顯示的位置不同,從而進行年、月、日、時、分、秒、的調整,按8次時退出,按K2調時,K3確定鍵,確認所調時間。
按K4進入鬧鈴調整狀態(tài),按一次光標顯示在鬧鈴秒位置,從而進行秒的調整,當按二次光標顯示在鬧鈴時位置,從而進行時的調整,按第三次退出調整狀態(tài)。

單片機源程序如下:
  1. #include<reg52.h>//52單片機頭文件,規(guī)定了52單片機的寄存器和IO口等
  2. #include<intrins.h>//_nop_空指令及左右循環(huán)移位子函數(shù)庫
  3. #define uchar unsigned char//宏定義
  4. #define uint unsigned int//宏定義
  5. sbit lcden=P2^7;//定義下面通過lcden來操作P2^7口,1602液晶使能控制端
  6. sbit lcdwr=P2^5;//定義下面通過lcdrw來操作P2^5口,1602讀寫選擇端
  7. sbit lcdrs=P2^6;//定義選數(shù)據(jù)寄存器選指令寄存器控制端
  8. sbit sda=P3^4;//定義DS1302數(shù)據(jù)總線
  9. sbit rst=P3^5;//DS1320復位
  10. sbit sck=P3^6;//定義時鐘總線
  11. sbit s1=P1^0;//定義設置按鈕
  12. sbit s2=P1^1;//定義調時按鈕
  13. sbit s3=P1^2;//定義確定按鈕
  14. sbit s4=P1^3;
  15. sbit ACC0=ACC^0;
  16. sbit ACC7=ACC^7;
  17. sbit BELL=P1^5;
  18. char fen,shi,miao,ri,yue,nian,zhou,s1num,s2num,s4num,flag1,flag2,lshi,lfen;
  19. uchar code table[]={" 2012-  -       "};//要寫入1602液晶的數(shù)據(jù)
  20. uchar code table1[]={"   :  :     :   "};//字庫中的字可直接以外加""號的形式直接寫入
  21. uchar code table2[]={" Welcome To Lcd!"};//歡迎界面
  22. uchar code table3[]={"Happy Every Day!"};                 //歡迎界面
  23. /*******************************************************************************
  24. 時函數(shù),z的取值為這個函數(shù)的延時ms數(shù),delay(200);大約延時200ms. delay(500);大約延時500ms
  25. *******************************************************************************/
  26. void delay(uint z)
  27. {                                                                                    
  28.               uint x,y;
  29.               for(x=z;x>0;x--)
  30.               for(y=110;y>0;y--);
  31. }
  32. /*********************蜂鳴器函數(shù)************************************************/
  33. void didi()
  34. {               
  35.     uchar i;
  36.      for(i=0;i<60;i++)
  37.       {
  38.         BELL = 0;
  39.                             delay(1);
  40.                    BELL = 1;
  41.                             delay(1);
  42.        }
  43. }

  44. /*******************向1602液晶中寫一個指令**************************************/
  45. void write_com(uchar com)
  46. {            
  47.               lcdwr=0;                                          //lcdwr為讀寫控制端,lcdwr=0,這里可不寫
  48.               lcdrs=0;           //液晶rs接口為0時,寫指令,rs為1時寫數(shù)據(jù)
  49.               P0=com;          //將要寫的指令賦給P0口,
  50.               delay(5);    //由1602讀寫操作時序圖,先將指令賦給P0口,延時后將使能
  51.               lcden=1;    //  端lcden置高,再延時一段時間,然后將lcden置低,這樣指令
  52.               delay(5);                // 就寫入到LCD了            
  53.               lcden=0;
  54. }
  55. /****************************向液晶寫數(shù)據(jù)***************************************/
  56. void write_data(uchar date)//與寫指令類似,這里lcdrs設為1
  57. {
  58.               lcdrs=1;
  59.               P0=date;
  60.               delay(5);
  61.               lcden=1;
  62.               delay(5);
  63.               lcden=0;
  64. }
  65. /*****************************初使化1602液晶************************************/
  66. void init_1602()
  67. {

  68.               lcdwr=0;
  69.               lcden=0;
  70.               write_com(0x38);//設置LCD為16*2顯示、5*7點陣、8位數(shù)據(jù)接口模式
  71.               write_com(0x0c);//開顯示、不顯示光標
  72.               write_com(0x06);//寫一個字符后,地址指針加1
  73.               write_com(0x01);//顯示清0
  74. }
  75. /*******************************************************************************/
  76. void gudingtime_1602()
  77. {
  78.     uchar num;
  79.               write_com(0x80);//將指針指向初始位置
  80.               for(num=0;num<16;num++)//循環(huán)函數(shù),用于將" 2012-  -     "寫入液晶
  81.                                           write_data(table[num]);
  82.               write_com(0x80+0x40);//將指針指向1602液晶的第二行
  83.               for(num=0;num<16;num++)//功能與上同,用于將"   :  :     :   "寫入
  84.                                           write_data(table1[num]);
  85. }
  86. /**************************顯示歡迎界面函數(shù)*************************************/
  87. void displaystar(void)
  88. {
  89.               uchar i;
  90.               write_com(0x80);
  91.               for(i=0;i<16;i++)
  92.               write_data(table2[i]);
  93.               write_com(0x80+0x40);
  94.               for(i=0;i<16;i++)
  95.               write_data(table3[i]);
  96. }
  97. /***************************顯示時間、日期子函數(shù)*********************************/
  98. void write_sfm(uchar add,uchar time)//用于在1602上顯示年、月、日、時、分、秒。Add為顯示位置,time為要顯示的內容
  99. {                             
  100.               uchar shiwei,gewei;                                                                                   
  101.               shiwei=time/16;   //將從DS1302中讀取的BCD碼數(shù)據(jù)轉化成10進制個位和10
  102.               gewei=time%16;   //進制十位
  103.               write_com(add+0x80);//定義顯示在液晶的什么位置
  104.               write_data(0x30+shiwei);//由1602液晶字庫可知,0~9的數(shù)據(jù)碼分別對應0x30~0x39
  105.               write_data(0x30+gewei);              //初使化中設定了寫一個字符后,地址指針加1,因此這里
  106. }                     // 不用重新光標寫位
  107. /**************************顯示周子函數(shù)*****************************************/
  108. void write_zhou(uchar time1)//用于在1602上顯示周信息,與顯示
  109. {                        //時間日期子函數(shù)類似
  110.               uchar gewei;
  111.               gewei=time1%16;//一周七天,因此只需個位
  112.               write_com(0x80+13);
  113.               write_data(0x30+gewei);
  114. }
  115. /***************************寫數(shù)據(jù)字節(jié)子函數(shù)************************************/
  116. void Input_1byte(uchar TD)//寫一字節(jié)數(shù)據(jù)
  117. {
  118.     uchar i;
  119.     ACC=TD;
  120.     for(i=8;i>0;i--)
  121.     {
  122.        sda=ACC0;
  123.        sck=1;
  124.        sck=0;
  125.        ACC=ACC>>1;
  126.     }
  127. }


  128. /*************************讀數(shù)據(jù)字節(jié)子函數(shù)**************************************/
  129. uchar Output_1byte(void)//讀一字節(jié)數(shù)據(jù)
  130. {
  131.     uchar i;
  132.     for(i=8;i>0;i--)
  133.      {
  134.          ACC=ACC>>1;
  135.          ACC7=sda;
  136.          sck=1;
  137.          sck=0;
  138.      }

  139.      return(ACC);

  140. }
  141. /***************************寫DS1302數(shù)據(jù)函數(shù)***********************************/
  142. void write_1302(uchar DS_ADD,uchar DS_DAT)//寫操作
  143. {  
  144.                             rst=0;
  145.                             sck=0;
  146.                             rst=1;
  147.                             Input_1byte(DS_ADD);
  148.                             Input_1byte(DS_DAT);
  149.                             sck=1;
  150.                             rst=0;
  151. }

  152. /***************************讀DS1302數(shù)據(jù)函數(shù)***********************************/
  153. uchar read_1302(uchar DS_ADD)//讀操作
  154. {  
  155.                 uchar DS_INF;
  156.                 rst=0;
  157.                 sck=0;
  158.                 rst=1;
  159.                 Input_1byte(DS_ADD);
  160.                 DS_INF=Output_1byte();
  161.                 sck=1;
  162.                 rst=0;
  163.                 return(DS_INF);
  164. }

  165. /*************************初始化DS1302子函數(shù)***********************************/
  166. void inital_1302()
  167. {
  168.     write_1302(0x8e,0x00);//禁止寫保護
  169.     write_1302(0x90,0xaa);//定義充電
  170.               write_1302(0x80,0x53);//秒  
  171.     write_1302(0x84,0x13);//時   
  172.               write_1302(0x82,0x43);//分
  173.               write_1302(0x8c,0x12);//年
  174.               write_1302(0x88,0x06);//月
  175.               write_1302(0x86,0x03);//日
  176.               write_1302(0x8a,0x06);//星期
  177.     write_1302(0xc0,0x08);//鬧鐘小時初始化
  178.               write_1302(0xfc,0x00);//鬧鐘分鐘初始化
  179.               write_1302(0x8e,0x80);//開保護

  180. }
  181. /********************************************************************************
  182.                               掃描函數(shù)
  183. ********************************************************************************/

  184. void keyscan()
  185. {
  186.               if(s1==0&&s4num==0)              //按鍵1按下且s4再次之前未曾按過
  187.               {
  188.                             delay(5);
  189.                             if(s1==0&&s4num==0)
  190.                             {  
  191. flag1=1;
  192.                                 s1num++;
  193.                                           while(!s1);didi();
  194.                                           if(s1num==1)
  195.                                           {                                                      
  196.                                                         write_com(0x80+0x40+8);//光標移動到**位置
  197.                                                         write_com(0x0f);//顯示光標
  198.                                           }

  199.                                           if(s1num==2)
  200.                                           {
  201.                                                            write_1302(0x8e,0x00);//禁止寫保護
  202.                                                         write_1302(0x80,miao);//寫入秒信息
  203.                                                         write_1302(0x8e,0x80);//開寫保護
  204.                                                         write_com(0x80+0x40+5);
  205.                                           }
  206.                                           if(s1num==3)
  207.                                           {
  208.                                                            write_1302(0x8e,0x00);
  209.                                                         write_1302(0x82,fen);
  210.                                                         write_1302(0x8e,0x80);
  211.                                                         write_com(0x80+0x40+2);                                                                                                               
  212.                                           }
  213.                                           if(s1num==4)
  214.                                           {
  215.                                                         write_1302(0x8e,0x00);
  216.                                                         write_1302(0x88,yue);
  217.                                                         write_1302(0x8e,0x80);
  218.                                               write_com(0x80+13);
  219.                                           }
  220.                                           if(s1num==5)
  221.                                           {
  222.                                                         write_1302(0x8e,0x00);
  223.                                                         write_1302(0x84,shi);
  224.                                                         write_1302(0x8e,0x80);
  225.                                                         write_com(0x80+10);
  226.                                           }
  227.                                           if(s1num==6)
  228.                                           {
  229.                                                         write_1302(0x8e,0x00);
  230.                                                         write_1302(0x86,ri);
  231.                                                         write_1302(0x8e,0x80);
  232.                                                         write_com(0x80+7);
  233.                                           }
  234.                                           if(s1num==7)
  235.                                           {
  236.                                                         write_1302(0x8e,0x00);
  237.                                                         write_1302(0x8c,nian);
  238.                                                         write_1302(0x8e,0x80);
  239.                                                         write_com(0x80+4);
  240.                                           }
  241.             if(s1num==8)
  242.                                           {
  243.                                     flag1=0;
  244.                                                         s1num=0;
  245.                                                         write_1302(0x8e,0x00);
  246.                                                         write_1302(0x8a,zhou);
  247.                                                         write_1302(0x8e,0x80);
  248.                                                         write_com(0x0c);//不顯示光標
  249.                                           }
  250.                             }
  251.               }            
  252. /*******************************************************************************/              if(s1num!=0&&s4num==0)//按鍵1按下*次且s4再次之前未曾按過
  253.                             {
  254.                                           if(s2==0)
  255.                                           {
  256.                                                         delay(5);
  257.                                                         if(s2==0)
  258.                                                         {  
  259.                                                                       while(!s2);didi();
  260.                                                                       if(s1num==1)
  261.                                                                       {
  262.                                                                                     int x1,x2;
  263.                                                                                     x1=miao%16;
  264.                                                                                     x2=miao/16;
  265.                                                                                     x1++;
  266.                                                                                     if(x1==10)
  267.                                                                                     {
  268.                                                                                                   x1=0;
  269.                                                                                                   x2++;
  270.                                                                                                   if(x2>=6)
  271.                                                                                                                 x2=0;
  272.                                                                                     }
  273.                                                                                     miao=x1+x2*16;
  274.                                                                                     write_sfm(7+0x40,miao);//將修改的數(shù)送到1602顯示
  275.                                                                                     write_com(0x80+0x40+8);//挪回光標
  276.                                                                       }
  277.                                                                       if(s1num==2)
  278.                                                                       {
  279.                                                                                     int x3,x4;
  280.                                                                                     x3=fen%16;
  281.                                                                                     x4=fen/16;
  282.                                                                                     x3++;
  283.                                                                                     if(x3==10)
  284.                                                                                     {
  285.                                                                                                   x3=0;
  286.                                                                                                   x4++;
  287.                                                                                                   if(x4>=6)
  288.                                                                                                                 x4=0;
  289.                                                                                     }
  290.                                                                                     fen=x3+x4*16;
  291.                                                                                     write_sfm(4+0x40,fen);
  292.                                                                                     write_com(0x80+0x40+5);
  293.                                                                       }            
  294.                                                                       if(s1num==3)
  295.                                                                       {
  296.                                                                                     int x5,x6;
  297.                                                                                     x5=shi%16;
  298.                                                                                     x6=shi/16;
  299.                                                                                     x5++;
  300.                                                                                     if(x6>=2&&x5>=4)            
  301.                                                                                     {
  302.                                                                                                   x5=0;
  303.                                                                                                   x6=0;
  304.                                                                                     }
  305.                                                                                     if(x5==10)
  306.                                                                                     {
  307.                                                                                                   x5=0;
  308.                                                                                                   x6++;
  309.                                                                                     }
  310.                                                                                     shi=x5+x6*16;
  311.                                                                                     write_sfm(1+0x40,shi);
  312.                                                                                     write_com(0x80+0x40+2);
  313.                                                                       }
  314.                                                                       if(s1num==4)
  315.                                                                       {
  316.                                                                                     zhou++;
  317.                                                                                     if(zhou==8)
  318.                                                                                     zhou=1;
  319.                                                                                     write_zhou(zhou);
  320.                                                                                     write_com(0x80+13);
  321.                                                                                    
  322.                                                   }
  323.                                                                       if(s1num==5)
  324.                                                                       {
  325.                                                                                     int x5,x6;
  326.                                                                                     x5=ri%16;
  327.                                                                                     x6=ri/16;
  328.                                                                                     x5++;
  329.                                                                                     if(x6>=3&&x5>=1)            
  330.                                                                                     {
  331.                                                                                                   x5=1;
  332.                                                                                                   x6=0;
  333.                                                                                     }
  334.                                                                                     if(x5==10)
  335.                                                                                     {
  336.                                                                                                   x5=0;
  337.                                                                                                   x6++;
  338.                                                                                     }
  339.                                                                                     ri=x5+x6*16;
  340.                                                                                     write_sfm(9,ri);
  341.                                                                                     write_com(0x80+10);
  342.                                                                       }
  343.                                                                       if(s1num==6)
  344.                                                                       {
  345.                                                                                     int x5,x6;
  346.                                                                                     x5=yue%16;
  347.                                                                                     x6=yue/16;
  348.                                                                                     x5++;
  349.                                                                                     if(x6>=1&&x5>=3)            
  350.                                                                                     {
  351.                                                                                                   x5=1;
  352.                                                                                                   x6=0;
  353.                                                                                     }
  354.                                                                                     if(x5==10)
  355.                                                                                     {
  356.                                                                                                   x5=0;
  357.                                                                                                   x6++;
  358.                                                                                     }
  359.                                                                                     yue=x5+x6*16;
  360.                                                                                     write_sfm(6,yue);
  361.                                                                                     write_com(0x80+7);
  362.                                                   }
  363.                                                                       if(s1num==7)
  364.                                                                       {
  365.                                                                                     int x5,x6;
  366.                                                                                     x5=nian%16;
  367.                                                                                     x6=nian/16;
  368.                                                                                     x5++;
  369.                                                                                     if(x6>=2&&x5>=1)            
  370.                                                                                     {
  371.                                                                                                   x5=1;
  372.                                                                                                   x6=0;
  373.                                                                                     }
  374.                                                                                     if(x5==10)
  375.                                                                                     {
  376.                                                                                                   x5=0;
  377.                                                                                                   x6++;
  378.                                                                                     }
  379.                                                                                     nian=x5+x6*16;
  380.                                                                                     write_sfm(3,nian);
  381.                                                                                     write_com(0x80+4);
  382.                                                   }
  383.                                                         }
  384.                                           }
  385.                   }
  386. /*******************************************************************************/

  387.               if(s1num!=0||s4num!=0)// 在調整模式下
  388.                             {
  389.                                           if(s3==0)//如果確定鍵按下
  390.                                           {
  391.                                                         delay(5);
  392.                                                         if(s3==0) //延時并重新檢測S3是否按下,用于差小誤差
  393.                                                         {
  394.                                                            if(s1num!=0)
  395.                                                            {
  396.                                                             while(!s3);didi();//在松手時將調整后的時間、日期及周信息寫入DS1302,退出調整模式并隱藏光標,按鍵次數(shù)清0
  397.                                                                       write_1302(0x8e,0x00);
  398.                                                                          write_1302(0x80,miao);
  399.                                                             write_1302(0x84,shi);
  400.                                                                       write_1302(0x82,fen);
  401.                                                                       write_1302(0x8a,zhou);
  402.                                                                       write_1302(0x8c,nian);//年
  403.                                                                       write_1302(0x88,yue);//月
  404.                                                                       write_1302(0x86,ri);
  405.                                                                       write_1302(0x8e,0x80);
  406.                                                                       flag1=0;
  407.                                                                       write_com(0x0c);
  408.                                                                       s1num=0;
  409.                    }
  410.                                                            if(s4num!=0)
  411.                                                            {
  412.                                                                          while(!s3);didi();//在松手時將調整后的時間、日期及周信息寫入DS1302,退出調整模式并隱藏光標,按鍵次數(shù)清0
  413.                     write_1302(0x8e,0x00);
  414.                                                                write_1302(0xc0,lshi);
  415.                     write_1302(0xfc,lfen);
  416.                                                                       write_1302(0x8e,0x80);
  417.                                                                       flag2=0;
  418.                                                                       s4num=0;
  419.                                                                       write_com(0x0c);
  420.                    }

  421.                                                         }
  422.                                           }            
  423.         }

  424.    if(s4==0&&s1num==0)//按鍵4按下*次且s1再次之前未曾按過
  425.         {
  426.                                 
  427.               delay(5);
  428.                                               if(s4==0&&s1num==0)
  429.                                             {   
  430.                                         s4num++;
  431.                                                                       flag2=1;
  432.                     while(!s4);didi();
  433.                                                               if(s4num==1)
  434.                                                                       {                                                      
  435.                                                                                                                                           
  436.                                                                                     write_com(0x80+0x40+14);
  437.                                                                                     write_com(0x0f);
  438.                                                                       }
  439.                                                                           
  440.                                                                         if(s4num==2)
  441.                                                                       {
  442.                                                                                        write_1302(0x8e,0x00);//禁止寫保護
  443.                                                                           write_1302(0xfc,lfen);//鬧鐘初始化
  444.                                                                                     write_1302(0x8e,0x80);//開寫保護
  445.                                                                                     write_com(0x80+0x40+11);
  446.                                                                       }
  447.                                                                       if(s4num==3)
  448.                                                                       {  
  449.                                                                           s4num=0;
  450.                                                                                     flag2=0;
  451.                                                                                        write_1302(0x8e,0x00);//禁止寫保護
  452.                                                                                     write_1302(0xc0,lshi);//鬧鐘初始化
  453.                                                                                     write_1302(0x8e,0x80);//開寫保護
  454.                                                                                     write_com(0x0c);//不顯示光標
  455.                                                                       }
  456.                                             }
  457.                             }
  458.             
  459.                                           if(s4num!=0&&s1num==0)
  460.                                           {
  461.                                                         if(s2==0)
  462.                                                         {
  463.                                                                       delay(5);
  464.                                                                       if(s2==0)
  465.                                                                       {  
  466.                                                                                     while(!s2);didi();
  467.                                                                                     if(s4num==1)
  468.                                                                                     {
  469.                                                                                                   int x1,x2;
  470.                                                                                                   x1=lfen%16;
  471.                                                                                                   x2=lfen/16;
  472.                                                                                                   x1++;
  473.                                                                                                   if(x1==10)
  474.                                                                                                   {
  475.                                                                                                                 x1=0;
  476.                                                                                                                 x2++;
  477.                                                                                                                 if(x2>=6)
  478.                                                                                                                               x2=0;
  479.                                                                                                   }
  480.                                                                                                   lfen=x1+x2*16;
  481.                                                                                                   write_sfm(13+0x40,lfen);
  482.                                                                                                   write_com(0x80+0x40+14);
  483.                                   }
  484.                                                                                     if(s4num==2)
  485.                                                                                     {
  486.                                                                                                   int x5,x6;
  487.                                                                                                   x5=lshi%16;
  488.                                                                                                   x6=lshi/16;
  489.                                                                                                   x5++;
  490.                                                                                                   if(x6>=2&&x5>=4)            
  491. ……………………

  492. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

以上全部Word格式文檔51hei提供下載:
電子時鐘設計-DS1302 1602 可調鬧鐘.doc (3.36 MB, 下載次數(shù): 572)

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏24 分享淘帖 頂2 踩
回復

使用道具 舉報

沙發(fā)
ID:21545 發(fā)表于 2019-2-7 21:24 | 只看該作者
謝謝介紹的很詳細了,適合初學者!!
回復

使用道具 舉報

板凳
ID:504761 發(fā)表于 2019-4-5 20:34 | 只看該作者
這個最后出現(xiàn)亂碼是不是程序的問題?我的供電5V沒有問題啊,用萬用表測了,所以有人能告訴我這個程序哪兒有問題嗎?
回復

使用道具 舉報

地板
ID:523687 發(fā)表于 2019-4-28 20:14 | 只看該作者
我下載的里頭怎么沒有程序 只有設計報告啊。。。
回復

使用道具 舉報

5#
ID:505337 發(fā)表于 2019-5-4 21:37 來自手機 | 只看該作者
只有word
回復

使用道具 舉報

6#
ID:591254 發(fā)表于 2019-7-27 14:32 | 只看該作者
系統(tǒng)原理圖怎么沒有DS1302的晶振呀求解
回復

使用道具 舉報

7#
ID:597910 發(fā)表于 2019-8-15 19:16 | 只看該作者
為什么LCD1602沒顯示
回復

使用道具 舉報

8#
ID:597910 發(fā)表于 2019-8-15 19:19 | 只看該作者
LCD沒顯示和按鍵不管用,只有1302管用是代碼的問題嗎
回復

使用道具 舉報

9#
ID:285380 發(fā)表于 2019-9-27 10:52 | 只看該作者
高手啊 ,辛苦了,內容很詳細  。
回復

使用道具 舉報

10#
ID:606251 發(fā)表于 2019-9-27 11:24 | 只看該作者
謝謝樓主分享,學習了!
回復

使用道具 舉報

11#
ID:436945 發(fā)表于 2019-12-24 12:36 | 只看該作者
高手 確實是高手
回復

使用道具 舉報

12#
ID:858511 發(fā)表于 2020-12-11 09:37 | 只看該作者
哇,超詳細的喔,要是有Proteus仿真就好了
回復

使用道具 舉報

13#
ID:858511 發(fā)表于 2020-12-11 09:39 | 只看該作者
要是加上仿真就好了
回復

使用道具 舉報

14#
ID:895836 發(fā)表于 2021-4-26 23:12 | 只看該作者
只有一個文檔
回復

使用道具 舉報

15#
ID:186161 發(fā)表于 2021-5-1 00:32 | 只看該作者
很好,怎么沒給加分
回復

使用道具 舉報

16#
ID:1080083 發(fā)表于 2023-5-30 10:27 | 只看該作者
怎么燒錄不了?有解決辦法嗎
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表