版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領
文檔簡介
模塊化編程思想原碼工作室模塊化編程概述 為什么要引入模塊化編程? 通過以上幾講內(nèi)容,我們初步掌握了單片機C語言編程的基本原理與基本方法。同時我們可以觀察并體會到,隨著代碼量的增加,將所有代碼都放在同一個.c文件中的做法越發(fā)使得程序結(jié)構(gòu)混亂、可讀性與可移植性變差,而模塊化編程是解決這個問題的常用而有效的方法。模塊化設計原則
高內(nèi)聚:一個c文件里面的函數(shù),只有相互之間的調(diào)用,而沒有調(diào)用其他文件里面的函數(shù),這樣可可以視為高內(nèi)聚。盡量減少不同文件里函數(shù)的交叉引用。
低耦合:一個完整的系統(tǒng),模塊與模塊之間,盡可能的使其獨立存在。也就是說,讓每個模塊,盡可能的獨立完成某個特定的子功能。模塊與模塊之間的接口,盡量的少而簡單。模塊化編程的三種手段 實現(xiàn)模塊化編程的三個主要手段是函數(shù)、宏定義與頭文件。下面講解一下頭文件操作的詳細步驟。
第一步創(chuàng)建頭文件 建立一個.c文件(源文件)和一個.h文件(頭文件)。原則上文件名可以任意命名,但強烈推薦如下原則:.c文件與.h文件同名;文件名要有意義,最好能夠體現(xiàn)該文件代碼的功能。例如延時函數(shù)相關的源文件與頭文件命名為delay.c與delay.h。 第二步防重復包含處理 在.h文件中加入如下代碼:#ifndefXXX#defineXXX ... //此處添加代碼#endif 其中的XXX原則上可以是任意字符,但同一個工程中各個.h文件的XXX不能相同,因此強烈推薦如下的規(guī)則:將.h文件的文件名全部大寫,“.”替換成下劃線“_”,首尾各添加2個下劃線“__”作為XXX。例如對于delay.h文件,其內(nèi)容如下:#ifndef__DELAY_H__#define__DELAY_H__ ... //此處添加代碼#endif 因為在同一個工程內(nèi),文件名都是唯一的,因此這種命名規(guī)則可以保證XXX不會重復。之后要添加到.h文件的代碼都放在第3行的位置。 這樣處理之后,當.h文件第一次被包含時,符號XXX是未被定義過的,因此符合#ifndef的條件,編譯器會繼續(xù)編譯第1行以后的代碼。然后編譯到第2行,先定義一下符號XXX,然后開始編譯第3行直到最后一行#endif的代碼。而此后此.h文件再次被包含時,符號XXX在第一次包含該.h文件時已被定義過了,不符合第一行#ifndef的條件,則該.h文件的內(nèi)容就不會被編譯器編譯??傊?,這樣處理之后既能保證.h文件的有效內(nèi)容被編譯,又能保證.h文件的有效內(nèi)容不被重復編譯。 第三步代碼封裝 將需要模塊化的代碼封裝成函數(shù)與宏定義。函數(shù)體放在.c文件中,需要被外部調(diào)用的函數(shù)還要在.h文件中聲明一下;需要被外部調(diào)用的宏定義放在.h文件中,僅會被本.c文件調(diào)用的宏定義放在.c文件中。第四步盡量少用或不用全局變量 必須要用的全局變量的聲明要放在.c文件中,需要被外部調(diào)用的全局變量還要在.h文件中重新用extern修飾聲明一下,用來告訴編譯器有這個變量的存在(因為編譯器的編譯過程是按文件來的,鏈接過程才是各個文件的合并,如果沒有這一步extern修飾聲明就在另一個文件調(diào)用了這個變量,編譯器會提示沒有此變量)。 第五步添加源文件 將.c文件添加到工程之中,同時在需要調(diào)用.h文件中的宏或者函數(shù)(這里的函數(shù)是對應的.c文件中函數(shù)的聲明)的其他.c文件中添加代碼將該.h文件包含進去(例如#include"delay.h")。 第六步使用 頭文件中的函數(shù)、宏定義、全局變量可以在包含了對應.h文件的.c文件中自由調(diào)用使用了時鐘芯片DS1302及其應用DS1302簡介
★時鐘計數(shù)功能,可以對秒、分鐘、小時、月、星期、年的計數(shù)。年計數(shù)可達到2100年。
★有31*8位的額外數(shù)據(jù)暫存寄存器
★最少I/O引腳傳輸,通過三引腳控制
★工作電壓:2.0-5.5V
★工作電流小于320納安(2.0V)
★讀寫時鐘寄存器或內(nèi)部RAM(31*8位的額外數(shù)據(jù)暫存寄存)可以采用單字節(jié)模式和突發(fā)模式
★8-pinDIP封裝或8-pinSOICs
★兼容TTL(5.0V)
★可選的工業(yè)級別,工作溫度-40–85攝氏度DS1302簡介 ★兼容DS1202,較DS1202增加的功能:
1.可通過Vcc1進行涓流充電
2.雙重電源補給
3.備用電源可采用電池或者超級電容(0.1F以上),可以用老式電腦主板上的3.6V充電電池。如果斷電時間較短(幾小時或幾天)時,就可以用漏電較小的普通電解電容器代替。100μF就可以保證1小時的正常走時。DS1302在第一次加電后,必須進行初始化操作。初始化后就可以按正常方法調(diào)整時間。DS1302引腳DS1302引腳 晶體振蕩器的選擇:一個32.768KHz的晶振可以直接接在DS1302的2、3管腳之間,可以設定規(guī)定載荷電容位6pf。 電源控制:Vcc1可提供單電源控制也可以用來作為備用電源,Vcc2為主電源。在主電源關閉的情況下,也可以保持時鐘的連續(xù)運行。DS1302由Vcc1或Vcc2兩者中的較大者供電。當Vcc2大于Vcc1+0.2V時,Vcc2給DS1302供電;當Vcc2小與Vcc1時,DS1302由Vcc1供電。DS1302功能 DS1302包括時鐘/日歷寄存器和31字節(jié)(8位)的數(shù)據(jù)暫存寄存器,數(shù)據(jù)通信僅通過一條串行輸入輸出口。實時時鐘/日歷提供包括秒、分、時、日期、月份、年份和星期幾的信息。閏年可自行調(diào)整,可選擇12小時制和24小時制,可以設置AM、PM。 只通過三根線(SPI總線)進行數(shù)據(jù)的控制和傳遞:RST、I/O、SCLKSPI總線 (serial
peripheral
interface)串行外圍設備接口SPI總線技術是Motorola公司推出的一種同步串行接口。SPI用于CPU與各種外圍器件進行全雙工、同步串行通訊。它只需四條線就可以完成MCU與各種外圍器件的通訊,這四條線是:串行時鐘線(CSK)、主機輸入/從機輸出數(shù)據(jù)線(MISO)、主機輸出/從機輸入數(shù)據(jù)線(MOSI)、低電平有效從機選擇線CS。內(nèi)部存儲空間 DS1302的所有功能都是通過對其內(nèi)部地址進行操作實現(xiàn)的。其內(nèi)部存儲空間分為2部分:80H~91H為功能控制單元,C0H~FDH為普通存儲單元;所有單元地址中最低位為0表示將對其進行寫數(shù)據(jù)操作,最低位為1表示將對其進行讀數(shù)據(jù)操作。 普通存儲單元是提供給用戶的存儲空間,而特殊存儲單元存放DS1302的時間相關的數(shù)據(jù),用戶不能用來存放自己的數(shù)據(jù)。內(nèi)部存儲空間注意:1、秒寄存器的CH位:置1,時鐘停振,進入低功耗態(tài);置0,時鐘工作。2、小時寄存器的D7位:置1,12小時制(D5置1表示上午,置0表示下午);置0,24小時制(此時D5、D4組成小時的十位)。注意:1、WP:寫保護位:置為1時,寫保護;置為0時,未寫保護。2、TCS:1010時慢充電;DS為01,選一個二極管,為10,選2個二極管;11或00,禁止充電。3、RS:與二極管串聯(lián)電阻選擇。00,不充電;01,2KΩ電阻;10,4KΩ電阻;11,8KΩ電阻。內(nèi)部存儲空間注意:1、TCS:1010時慢充電;其他時禁止充電。2、DS為01,選一個二極管;為10,選2個二極管;11或00,禁止充電。3、RS:與二極管串聯(lián)電阻選擇。00,不充電;01,2KΩ電阻;10,4KΩ電阻;11,8KΩ電阻特殊存儲空間
在突發(fā)模式下,通過連續(xù)的脈沖一次性讀寫完8個字節(jié)的時鐘/日歷寄存器(8個寄存器要全部讀寫完:時、分、秒、日、月、年、星期、寫保護寄存器,充電寄存器在突發(fā)模式下不能操作)普通存儲空間 在突發(fā)模式下,通過連續(xù)的脈沖一次性讀寫完1-31個字節(jié)的RAM數(shù)據(jù)(可按實際情況讀寫一定數(shù)量的字節(jié),可以不必一次全部讀寫完)存儲空間單字節(jié)讀操作 數(shù)據(jù)輸入: 經(jīng)過8個小時周期的控制字節(jié)的輸入,一個字節(jié)的輸入將在下8個時鐘周期的上升沿完成,數(shù)據(jù)傳輸從字節(jié)最低位開始。數(shù)據(jù)輸出: 經(jīng)過8個小時周期的控制讀指令的輸入,控制指令串行輸出后,一個字節(jié)的數(shù)據(jù)將在下個8個時鐘周期的下降沿被輸出,注意第一位輸出是在最后一位控制指令所在的脈沖的下降沿被輸出,要求RST保持位高電平。單字節(jié)寫操作CE必須在高電平時,才能對DS1302讀/寫操作低位在前,高位在后,一個SCLK周期傳遞一位上升沿輸入,下降沿輸出先寫地址(RW=0,允許寫數(shù)據(jù)的單元地址),然后寫數(shù)據(jù)先寫地址(RW=1,允許讀數(shù)據(jù)的單元地址),然后讀數(shù)據(jù)DS1302時序圖R/W:1——可以讀;0——可以寫R/C:1——普通存儲器;0——特殊寄存器地址(命令)字節(jié)格式 R/W:1——可以讀;0——可以寫 R/C:1——普通存儲器;0——特殊寄存器 不管是單字節(jié)的讀寫還是突發(fā)模式的讀寫,首先傳遞的是地址(命令)字節(jié),然后才是數(shù)據(jù)字節(jié),每個時鐘周期上升或下降沿發(fā)送1位,低位在前,高位在后。R/W:1——可以讀;0——可以寫R/C:1——普通存儲器;0——特殊寄存器R/W:1——可以讀;0——可以寫R/C:1——普通存儲器;0——特殊寄存器R/W:1——可以讀;0——可以寫R/C:1——普通存儲器;0——特殊寄存器時鐘設計
利用DS1302和LCD1602設計一個時鐘,能顯示時間、日期及星期,還能通過按鍵進行調(diào)節(jié): 分析:根據(jù)要求可知這個時鐘的軟件應該包含3個大模塊,分別是:DS1302模塊、LCD1602模塊和按鍵模塊,然后就是主函數(shù)的整合。
因為模塊很多,而且按照前面的相關模塊的介紹可知道每個模塊都會有很多子函數(shù)及相關的參數(shù),所以如果放在一個.c文件中會很不方便,而且.c文件會很長,不方便閱讀和修改,所以這就可以利用前面講解的模塊化編程思想,將每個模塊都寫成單獨的.c和.h文件,然后再建一個main.c文件,進行程序的整合和功能的實現(xiàn)。
根據(jù)前面的講解,建好工程及相關模塊的.c和.h文件后就可以開始寫代碼了,因為工程比較大,模塊比較多,所以建議單個模塊調(diào)試,比如先調(diào)試LCD1602的程序,就先不要寫其他模塊的代碼,等1602調(diào)試通過之后再加第二個模塊,這樣一邊寫代碼一邊調(diào)試,如果調(diào)試過程除了問題比較容易查出問題的所在。 因為前面調(diào)試過LCD1602,所以只需將相關的函數(shù)拷貝到LCD1602.c和.h中即可,一般函數(shù)的實現(xiàn)都在.c中完成,定義在.h中,不過為了方便別的模塊進行調(diào)用,所以需要在.h文件中進行函數(shù)的申明,這樣其他模塊如果需要調(diào)用LCD1602的話,只需要包含LCD1602.h即可,如果定義的變量也可能被其他模塊所調(diào)用的話,就需要在.c文件中進行相關變量的定義,然后在調(diào)用的.c中進行申明即可。 LCD1602的.c和.h文件寫好之后,可在main.c中進行測試,如果測試通過即可進行下一個模塊的調(diào)試,接下來調(diào)試DS1302模塊,同1602一樣,在.c和.h文件中寫好相關的功能函數(shù),然后進行測試,因為1602的程序已經(jīng)調(diào)試通過,所以調(diào)試DS1302的時候可以調(diào)用1602的相關函數(shù)進行顯示,這樣就使兩個模塊有了交集。 前面已經(jīng)講過DS1302的相關原理,只需將相關讀寫函數(shù)寫對,DS1302的相關寄存器中存儲著時間及日期,所以取出進行顯示即可,但可能需要調(diào)節(jié),這即可以通過在函數(shù)中隊DS1302寫入初始化的時間和日期,也可以通過后面的按鍵模塊進行調(diào)節(jié),原理其實一樣,只不過是想方法不同而已。 為了方便進行修改,在.h文件中對相關的引腳進行宏定義,這樣方便在移植的時候進行修改,前面的1602亦是如此。/***********向DS1302寫入一字節(jié)數(shù)據(jù)**********************/voidDS1302InputByte(unsignedchard) {unsignedchari;ACC=d;for(i=8;i>0;i--){DS1302_IO=ACC0;//相當于匯編中的RRCDS1302_CLK=1;DS1302_CLK=0;ACC=ACC>>1;}}/***********從DS1302讀出一字節(jié)數(shù)據(jù)***********/unsignedcharDS1302OutputByte(void) {unsignedchari;for(i=8;i>0;i--){ACC=ACC>>1; //相當于匯編中的RRCACC7=DS1302_IO;DS1302_CLK=1;DS1302_CLK=0;}return(ACC);}/***********向DS302某個地址寫入數(shù)據(jù)*********/voidWrite1302(unsignedcharucAddr,unsignedcharucDa) //ucAddr:DS1302地址,ucData:要寫的數(shù)據(jù){DS1302_RST=0;DS1302_CLK=0;DS1302_RST=1;DS1302InputByte(ucAddr); //地址,命令
DS1302InputByte(ucDa); //寫1Byte數(shù)據(jù)
DS1302_CLK=1;DS1302_RST=0;}/*************從DS302讀出時鐘數(shù)據(jù)**********/unsignedcharRead1302(unsignedcharucAddr) //讀取DS1302某地址的數(shù)據(jù){unsignedcharucData;DS1302_RST=0;DS1302_CLK=0;DS1302_RST=1;DS1302InputByte(ucAddr|0x01);//地址,命令
ucData=DS1302OutputByte();//讀1Byte數(shù)據(jù)
DS1302_CLK=1;DS1302_RST=0;return(ucData);}/**************DS302初始化函數(shù)***************/voidInitial_DS1302(void)//時鐘芯片初始化{ unsignedcharSecond=Read1302(DS1302_SECOND); if(Second&0x80) //判斷時鐘芯片是否關閉
{ Write1302(0x8e,0x00);//寫入允許
Write1302(0x8c,0x0B);//以下寫入初始化時間日期:07/07/25.星期:3.時間:23:59:55 Write1302(0x88,0x05); Write1302(0x86,0x05); Write1302(0x8a,0x04); Write1302(0x84,0x23); Write1302(0x82,0x59); Write1302(0x80,0x55); Write1302(0x8e,0x80);//禁止寫入
}}/*************獲取時鐘芯片的時鐘數(shù)據(jù)*******************/voidDS1302_GetTime(SYSTEMTIME*Time)//獲取時鐘芯片的時鐘數(shù)據(jù)到自定義的結(jié)構(gòu)型數(shù)組{ unsignedcharReadValue; ReadValue=Read1302(DS1302_SECOND); Time->Second=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); ReadValue=Read1302(DS1302_MINUTE); Time->Minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); ReadValue=Read1302(DS1302_HOUR); Time->Hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); ReadValue=Read1302(DS1302_DAY); Time->Day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); ReadValue=Read1302(DS1302_WEEK); Time->Week=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); ReadValue=Read1302(DS1302_MONTH); Time->Month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); ReadValue=Read1302(DS1302_YEAR); Time->Year=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F); }/************液晶顯示程序**************/voidshow_time(){ DS1302_GetTime(&CurrentTime);//獲取時鐘芯片的時間數(shù)據(jù)
TimeToStr(&CurrentTime);//時間數(shù)據(jù)轉(zhuǎn)換液晶字符
DateToStr(&CurrentTime);//日期數(shù)據(jù)轉(zhuǎn)換液晶字符
GotoXY(0,1); Print(CurrentTime.TimeString);//顯示時間
GotoXY(0,0); Print(CurrentTime.DateString);//顯示日期
GotoXY(15,0); Print(week_value);//顯示星期
GotoXY(11,0); Print("Week"); //在液晶上顯示字母week Delay1302ms(400);//掃描延時} 前面兩個模塊都測試通過之后,基本就實現(xiàn)了始終計數(shù)的功能,只是不能進行調(diào)節(jié)而已,所以接下來需要調(diào)試調(diào)節(jié)時間用的4個獨立按鍵,基本實現(xiàn)思想跟前面一樣,因為按鍵的調(diào)節(jié)既會改變DS1302中的相關參數(shù),也會涉及到1602的顯示內(nèi)容,所以按鍵模塊中會涉及到前面調(diào)試的兩個模塊,所以key.c文件中需要包含DS1302.h和LCD1602.h。 獨立按鍵的識別前面已經(jīng)講過,很簡單,但是在本次設計中,需要通過按鍵進行時間和日期等的調(diào)節(jié),所以需要事先清楚相關的邏輯和自己的編程思維,如果過于復雜的話可以試著畫出相關的流程圖,根據(jù)流程圖進行編程會簡單明了很多。
這次試用了4個獨立按鍵,分別實現(xiàn)的功能是退出調(diào)試模式、減計數(shù)、增計數(shù)和調(diào)試模式。需要了解其中的邏輯關系才能順利的進行編程,4個案件中只要按了退出調(diào)試模式即不能進行調(diào)試,禁止對DS1302進行寫入,按下調(diào)試模式后,1602即停止對當前時間的顯示,進入調(diào)試模式,每按一次調(diào)試按鍵即改變一個參數(shù)的調(diào)節(jié),然后通過增計數(shù)和減計數(shù)按鍵進行調(diào)節(jié),所以調(diào)試按鍵按下一次是調(diào)節(jié)秒?yún)?shù),按下第二次是調(diào)節(jié)分參數(shù)。。。。以此類推。voidoutkey()//跳出調(diào)整模式,返回默認顯示{ unsignedcharSecond;if(out==0){ GotoXY(0,0); Print("Exit!"); GotoXY(0,1); Print(""); mdelay(4000); mdelay(4); count=0; hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0; Second=Read1302(DS1302_SECOND); Write1302(0x8e,0x00);//寫入允許
Write1302(0x80,Second&0x7f); Write1302(0x8E,0x80);//禁止寫入
done=0;
while(out==0); LCD_clear(); mdelay(40); }}/******************菜單選擇*********************/voi
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度城市照明工程承包服務合同3篇
- 2025年度幼兒園窗戶安全改造及責任認定合同4篇
- 2024年綜合安防系統(tǒng)集成服務合同
- 2025年度商業(yè)場所蟲害防治與形象維護服務合同4篇
- 2025年度生態(tài)園區(qū)代建工程合同模板4篇
- 2025年度殯儀館遺體運輸與悼念活動全程服務合同書3篇
- 2024年版婚內(nèi)共同財產(chǎn)管理及使用合同
- 2025年度新能源儲能項目搭建與銷售合同4篇
- 2025年度化工企業(yè)環(huán)境風險防控合同3篇
- 2025年度大豆國際貿(mào)易結(jié)算與清算服務合同3篇
- 直播帶貨助農(nóng)現(xiàn)狀及發(fā)展對策研究-以抖音直播為例(開題)
- 腰椎間盤突出疑難病例討論
- 《光伏發(fā)電工程工程量清單計價規(guī)范》
- 2023-2024學年度人教版四年級語文上冊寒假作業(yè)
- (完整版)保證藥品信息來源合法、真實、安全的管理措施、情況說明及相關證明
- 營銷專員績效考核指標
- 陜西麟游風電吊裝方案專家論證版
- 供應商審核培訓教程
- 【盒馬鮮生生鮮類產(chǎn)品配送服務問題及優(yōu)化建議分析10000字(論文)】
- 肝硬化心衰患者的護理查房課件
- 2023年四川省樂山市中考數(shù)學試卷
評論
0/150
提交評論