(1小時學會C語言51單片機)C語言入門教程_第1頁
(1小時學會C語言51單片機)C語言入門教程_第2頁
(1小時學會C語言51單片機)C語言入門教程_第3頁
(1小時學會C語言51單片機)C語言入門教程_第4頁
(1小時學會C語言51單片機)C語言入門教程_第5頁
已閱讀5頁,還剩15頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、相信很多愛好電子的朋友 ,對單片機這個詞應該都不會陌生了吧。不過有些朋友可能只聽說 他叫單片機,他的全稱是什么也許并不太清楚, 更不用說他的英文全稱和簡稱了。 單片機是一塊在集成電路芯片上集成了一臺有一定規(guī)模的 微型計算機。簡稱為:單片微型計算機或單片機( Single Chip Computer) 。單片機的應用到處可見,應用領域廣泛,主要應用在智能儀表、 實時控制、通信、家電等方面。不過這一切都沒 什么關系,因為我(當然也包括任何人)都是從不知道轉變成知道的,再轉變成精通的。現(xiàn) 在我只想把我學習單片機的經歷,詳細地講敘給大 家聽聽,可能有些大蝦會笑話我,想:那么簡單的東西還在這里賣弄。但是

2、你錯了,我只是 把我個人學習的經歷講述一遍而已,僅僅對那些想學習單片機, 但又找不到好方法或者途徑的朋友, 提供一個幫助,使他們在學習過程中, 盡 量少走些彎路而已!首先, 你必須有學習單片機的熱情, 不是說今天去圖書館看了一個下午關于單片機的書, 而明天玩上半天,后天就不知道那個本書在講什 么東西了。 還是先說說我吧, 我從大二的第一個學期期末的時候才開始接觸單片機, 但在這 之前,正如上面所說的:我知道有種芯片叫單片機, 但是具體長成什么樣子, 卻一點也不知道! 看到這里很多朋友一定會忍不住發(fā)笑。 嘿嘿, 你 可千萬別笑,有些大四畢業(yè)的人也同樣不知道單片 機長成什么樣子呢! 而我對單片機的

3、癡迷更是常人所不能想象的地步, 大二的期末考試, 我 全放棄了復習,每當室友拿著書在埋頭復習的時候, 我卻捧著自己從圖書館借的單片機書在那看, 雖然有很多不懂, 但是我還是堅持了下來, 當 時我就想過,為了單片機值不值得我這樣去付出, 或許這也是在一些三流學校的好處吧, 考試掛科后, 明年開學交上幾十元一門的補考費, 應 該大部分都能過了。于是,我橫下一條心,堅持看 我的單片機書和資料。當你明白了單片機是這么一回事的時候,顯而易見的問題出來了:我要選擇那種語言為 單片機編寫程序呢?這個問題,困擾了我好久。具 體選擇 C51 還是 A51 呢?匯編在我們大二之前并沒有開過課,雖然看著人家的講解,

4、很容 易明白單片機的每一時刻的具體工作情況,但是一合上 書或者資料, 自己卻什么也不知道了, 根本不用說自己寫程序了。于是, 我最終還是決定學 C51,畢竟C51和我們課上講的 C語言,有些類似, 編程的思想可以說是相通的。而且 C51 還有更大的優(yōu)點就是編寫大程序時的優(yōu)越性更不言 而喻,當然在那時,我并沒有想的那么深遠, C51 的特點,還是在后來的實踐過程中,漸漸體會到的!朋友如果你選擇了C51,那么請繼續(xù)往下看,如果你選擇了 A51,那么你可以不要看了 !因為下面講 的全是C方面的,完全在浪費你的時間! 呵呵A_A第二,既然你想學好單片機,你必須得舍得花錢,如果不買些芯片回來自己動手焊焊

5、拆 拆的 (但是在后期會介紹給大家一個很好用的硬件仿真軟件,并不需要你用實驗板和仿真器了 ,直接在你的PC上完成,但是軟件畢竟是軟件,從某 個特定的意義上來說是并不能代替硬件的 ),即使你每天捧著本書, 把那本書翻爛, 也永遠學不會單片機的! 剛接觸單片機的朋友, 看了資料, 一定會對以下幾個詞見的比較多,但是具體的概念還是比較模糊,現(xiàn)作如下說明:(1)編程器 編程器是用來燒單片機芯片的,是把 HEX 或者 BIN 文件燒到單片機 ROM 里 的,供單片機運行的。(2)實驗板 實驗板是專為初學者根據某些要求而特做的板, 一般上面就有一個單片機的最 小系統(tǒng),使用者只需寫好程序,燒好芯片,放 到上

6、面加以驗證的這么一個工具。 有了實驗板, 對與初學者來說, 省去了焊個最小系統(tǒng)的麻 煩。但是對于電子開發(fā)人員來說,作用并不是很大(3)仿真器 仿真器是直接把 HEX 或者 BIN 文件暫時放在一個芯片里, 再通過這個芯片的 引腳連接到實驗板或者系統(tǒng)上工作。這樣以來,可 以省去了來回插拔芯片帶來的不必要麻煩。我一開始也不知道上面 3 個的概念和作用 ,嘿嘿,原本想買個實驗板 (不想焊板 ,因為不可能 為了點亮幾個流水燈 ,而去焊個單片機的最小系統(tǒng) )的, 可是結果 , 確和我想的正好相反 ,人家出售的是編程器。 等貨物寄到后, 才知道自己搞錯了! 汗。嘿嘿。現(xiàn)在想想實在是又氣又笑。我花了 160

7、 大樣買了個編程器 (很不幸的是, 這個編程器更本用不了, 一燒芯片, 芯片就燒壞了) 把我給氣的,這個編程器,現(xiàn)在還躺在我的抽屜里呢不過, 現(xiàn)在想想, 唯一讓我覺得欣慰的是, 那個老板每次能解答我的問題, 連那種超級幼 稚的問題,他也能不嫌麻煩地盡量幫我解答!這點讓我很感動!第三,想學單片機的必需品 -PC。因為寫程序,編譯或者是仿真都是通過PC完成的。如果沒有PC,什么也做不了! ! !有了 PC最好還要可以上網, 因為如果你沒有可以和你交流單片機的人, 遇到自己解決不了的問題, 一直都想不 通,那么估計你學習單片機的熱情就會隨著時間的推移而慢慢耗盡。 如果你能上網通過論壇或者 QQ 群,

8、 問題就很快得到解決。 這樣的學習效 率一定很高!真正的高手是從論壇中泡出來的!有了上述 3 個條件后,你就可以開始學你的單片機了。但是,真的做起來并沒有我所說 的那么簡單。你一定會遇到很多很多的問題。比如 為了讓單片機實現(xiàn)某個功能, 你可能不知道怎么去寫某個程序。 或是你看懂了資料上某個相 似的程序,你自己卻寫不出來。遇到類似的情況, 記?。呵f不要急噪,就行!說了這么多了, 相信你也看了很多資料了, 手頭應該也有必備的工具了吧! (不要忘了上 面講過幾個條件的哦) 。那個單片機究竟有什么功能和作用呢?先不要著急!接下來讓我們點亮一個LED (搞電子的應該知道 LED是什么吧人_人)我們在單

9、片機最小系統(tǒng)上接個 LED, 看我們能否點亮它 !對了 ,上面也有好幾次提到過單片 機最小系統(tǒng)了,所謂單片機最小系統(tǒng)就是在單片機 上接上最少的外圍電路元件讓單片機工作。一般只須連接晶體、VCC、GND、RST 即可,一般情況下, AT89C51 的 31 腳須接高電平。#include/頭文件定義。或用 #include 其具體的區(qū)別在于:后者定義了更多的地址空間。/在 Keil 安裝文件夾中,找到相應的文件,比較一下便知!sbit P1_0 = P1 A 0;/ 定義管腳void main (void) while(1) P1_0 = 0;/低電平有效,如果把 LED 反過來接那么就是高電平

10、有效 就那么簡單, 我們就把接在單片機 P1_0 上的 LED 點亮了, 當然 LED 是低電平, 才能點 亮。因為我們把 LED 的正通過電阻接至 VCC 。P1_0 = 0;類似與C語言中的賦值語句,即把0賦給單片機的P1_0引腳,讓它輸出相應的電平。那么這樣就能達到了我們預先的要求了。while(1) 語句只是讓單片機工作在死循環(huán)狀態(tài),即一直輸出低電平。如果我們要試著點亮其 他的 LED ,也類似上述語句。這里就不再講了。點亮了幾個 LED 后,是不是讓我們聯(lián)想到了繁華的街區(qū)上流動的彩燈。 我們是不是也可 以讓幾個 LED 依次按順序亮呢?答案是肯定的!其 實顯示的原理很簡單,就是讓一個

11、 LED 滅后,另一個立即亮,依次輪流下去。 假設我們有 8 個 LED 分別接在 P1 口的 8 個引腳上。硬件連接,在P1_1-P1_7 上再接 7 個 LED 即可。例程如下: #include sbit P1_0 = P1 A 0; sbit P1_1 = P1 a 1; sbit P1_2 = P1 A 2; sbit P1_3 = P1 A 3; sbit P1_4 = P1 A 4; sbit P1_5 = P1 A 5; sbit P1_6 = P1 A 6; sbit P1_7 = P1 A 7;void Delay(unsigned char a)unsigned char

12、 i;while( -a != 0)for(i = 0; i 125; i+); / 一個 ; 表示空語句 ,CPU 空轉。/i 從 0 加到 125, CPU 大概就耗時 1 毫秒void main(void)while(1)P1_0 = 0;Delay(250);P1_0 = 1;P1_1 = 0; Delay(250);P1_1 = 1;P1_2 = 0;Delay(250);P1_2 = 1;P1_3 = 0;Delay(250);P1_3 = 1;P1_4 = 0;Delay(250);P1_4 = 1;P1_5 = 0; Delay(250);P1_5 = 1;P1_6 = 0;D

13、elay(250);P1_6 = 1;P1_7 = 0;Delay(250);P1_7 = 1;sbit定義位變量,unsigned char a定義無符字符型變量 a,以節(jié)省單片機內部資源,其有效值為0255。main函數(shù)調用 Delay()函數(shù)。Delay 函數(shù)使單片機空轉, LED 持續(xù)點亮后,再滅,下一個 LED 亮。 while(1) 產生循環(huán)。面我們講了如何使 LED 產生流動, 但是你是否發(fā)現(xiàn)一個問題: 寫的太冗長了! 能不能 再簡單點呢?可以!可以使用 C51 的內部函數(shù) INTRINS.H 實現(xiàn)。函數(shù) unsigned char _crol_(unsigned char a,

14、 unsigned char n) 可以使變量 a 循環(huán)左移 n 位,如果我們先給 P1 口賦0000 0001 那么當 n 為 1 時,便會產生和上面一樣的效果! #include#include void Delay(unsigned char a) unsigned char i;while( -a != 0)for(i = 0; i 125; i+);void main(void)unsigned char b, i;while(1)b = 0xfe;for(i = 0; i New Project- 輸入文件名 - 選擇我們所以使用 的芯片(這里我們一般用到 Atmel 的AT89C

15、51 或 AT89C2051 ,點確定。3. 點 File-New- 輸入我們編寫的程序,保存為 .C 文件。(一般情況下,我們保存的文件名 和前面的工程名一樣。 )4. 展開 Target 1 - 右擊 Source Group 1 -Add Files to Group Source Group 1- 選擇剛才保存 的.C文件點擊ADD后,關閉對話框。這樣 .C 文件就被加到了 Source Group 1 下。5. 右擊 Target 1-Options for Target 1 -Target 中填寫晶體的大小, Output 中,在 Create HEX Files 前打上鉤,點確定

16、。6. 點 Project-Rebuild All Traget Files ,若提示creating hex file from XXX.XXX - 0 Error(s), 0 Waring(s).表示編譯和生成 HEX 文件成功!接下來的就是把 HEX 文件燒到單片機中,或是仿真器上, 看是否達到預先的目的!嘿嘿! 現(xiàn)在是否自己好有成就感了,如果讓你去做個流水彩燈, 開發(fā)一個簡單的產品, 只要加上驅動電路,就可以做出漂亮的流動彩燈了!到現(xiàn)在為止, 你應該知道單片機的功能有多強大了吧, 如果單純的用數(shù)字電路或模擬電 路的知識去設計一個流動彩燈,可能要花點工夫和時間才行, 有了單片機, 那就不

17、一樣了, 你只要寫程序控制他就行! 有人說過這樣一句話, 也并不無道理的,學單片機,程序思想很重要!(四)呵呵,朋友!相信你的流水燈也做的不錯了吧,現(xiàn)在能玩出幾種花樣了?你可能會說, 只要你想得到,想怎么流就怎么流!呵呵,是的。但是工程師們設計這么一個單片機, 并不是只為了讓它做流水燈的, 那樣也太浪費點了吧 .A A學過數(shù)字電路的朋友,一定動手做過 8 路或者 6 路的搶答器。用純粹的數(shù)字電路知識來 做,自己設計電路,感到比較困難!搶答器上用的顯 示器多為 7 段數(shù)碼管,這里我們來講講,如何用單片機讓數(shù)碼管顯示 0-9。搶答器的實現(xiàn), 我們放到后面再來探討,因為搶答器還涉及了鍵盤的 內容。8

18、 段數(shù)碼管分為共陰和共陽兩種。 8 段數(shù)碼管是由 8 個 LED 組成(還包括一個小數(shù)點) 。 若為共陽,則 8 個 LED 的陽級是連接在一起的,同理若為共陰,則陰極連接在一起。8個LED 對應的標號如下:(0x3f, 0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f; /0-9 數(shù)字 )a01 23456789_ 0011 1111,0000 0110,0100 1111,0101 1011 f | | b|_|g | ce |_| . dpd一般情況下, 為了計算或取碼的方便, 我們把 a-dp 依次接到單片機某個口上的Px.0-Px.7 上。 x

19、 表示 0,1,2,3 其中的一個。這樣我們只 要給某個口,賦一個值,則相應的 LED 段就被點亮,但是在硬件連接上要注意了:單片機 可能不能直接驅動 LED ,所以我們可以通過控制三級管 的導通或截止,來控制 LED 的亮與滅!如果我們把共陰的數(shù)碼管的a-dp 依次接到單片機的 P0.0-P0.7 上,注意: P0 口需接上拉電阻。何為上拉電阻,簡單的說,就是把電平拉高,以提高驅動能力。那么比如: P0 = 0X3F ;則顯示為數(shù)字 0 。因為 0X3F 即為 2 進制的 0011 1111 我們低位往高位數(shù),依次為1111 1100,其 I/O 的電平分別為高、高、高、高、高、高、低、低,

20、即對應的a-dp 為亮、亮、亮、亮、亮、亮、滅、滅,由上圖我們可以看出 g 和 dp 段不 亮其他段均亮,即為我們所看到的數(shù)字 0 字樣。其他的數(shù)字或字符,也同理可以得到。但 是有些朋友就會問,那我們每取一個字模,豈不是很麻煩?還有自己考慮高低電平什么的?A-A呵呵,其實網上有很多LED取模軟件,如果有一定計算機編程語言的朋友,也可以試著自己寫個 取模的程序,讓計算機為我們計算,諸如上述 0X3F 的數(shù)值。#includevoid Delay(unsigned char a)unsigned char i;while( -a != 0)for(i = 0; i 125; i+);void ma

21、in(void)P0 = 0X3F; / 顯示 0Delay(250);/ 延時P0 = 0X00;/ 短暫的關閉顯示,若不關閉,可能會造成顯示模糊不清。P0 = 0X06; / 顯示 1Delay(250);P0 = 0X00;. / 以下顯示數(shù)字 2-F ,略??吹竭@里,想必大家一定可以把 0-F 顯示出來了吧!但是如果要你顯示兩位數(shù),三位數(shù) 呢?或許,有的朋友會這么想:在 P0 口上接一個數(shù)碼管,再在 P1 口上接個數(shù)碼管!但是,如果要顯示4位、5位的數(shù)字呢?那豈不是一塊AT8951 都接不過來!難到就不能接 4 位或 5 位以上的嗎?肯定不是的!說到這里,我們來講講數(shù)碼管的顯示方式,可

22、分為兩種:動態(tài)掃描和靜態(tài)顯示。上面我 們所說的即為靜態(tài)顯示。但是如果我們采用動態(tài)掃 描顯示, 那么就可以解決上面的問題, 即可以顯示多個數(shù)碼管了。 上面我們所說的靜態(tài)顯示 把數(shù)碼管的 COM 腳接至 VCC 或 GND 端,其他的接至 PX 口上,這樣只要 PX 口上輸出相應的高低電平,就可以顯示對應的數(shù)字或字符。但是如果我 們采用動態(tài)掃描的方法,比如顯示 6 個數(shù)碼管,硬件 連接可以這樣解決: a-dp 還是接至 P0.0-P0.7 上,還有 6 個 COM 腳再接至另外口的 P2.0-P2.5。 P0 口作段選(控制數(shù)字字符)P2 口作位選(選通哪個數(shù)碼管導通)這樣我們控制 P0 和 P2

23、 口就可以控制 6 個數(shù)碼管了。但是,細心的朋 友,會問這樣的問題: P2 位選,是讓數(shù)碼管一個一個亮的,那還是不能控制 6個一起亮或滅嘛?。緼_A想想好象是對的哦?怎么辦 難道錯了?嘿嘿,問你個問題?黑夜里,拿著一支煙,在你面前快速的晃動,你會發(fā)現(xiàn)什么樣的現(xiàn) 象?是不是原本不連續(xù)的點變成了一條看上去連 續(xù)的曲線或者直線!再回過頭來,仔細想想我們的數(shù)碼管!原理是一樣的,你可別忘了,我 們的單片機可是一個計算機哦,計算機的運算速 度,大家可想而知吧!這里再說說 51 單片機的機器周期和時鐘周期等概念。 所謂機器周期就是訪問一次存儲器 的時間。而 1 個機器周期包括 12 個時鐘周期。如果單片機工

24、作在 12M 晶體下,那么一個時鐘周期為: 1/12 微妙。一個機器周期 12*1/12 = 1 微 妙。如果晶體為 6M,時鐘周期和機器周期各是多少呢?在匯編中,我們還要關心,指令執(zhí)行的機器周期長短不一,有 1個周期、 2個周期和 4個 周期等。說著說著,跑了這么遠了還是回到原來的話題,如果我們把位選的 P2也看作上面的煙” 一劃而過,那么我們看到的是不是 6個一起亮 或一起滅了! A_A 哈哈,原來如此 . 記住,在任何某一時刻,有且只有一個數(shù)碼管能 發(fā)光。如果你能把這句話理解了,你是真明白我的意思了!朋友,現(xiàn)在給你個任務,讓 6 個數(shù)碼管分別顯示 1、2、3、4、5、6。看你自 己可以搞

25、定不?你自己先試著寫寫看咯 .#includevoid Delay(unsigned char a) unsigned char i; while( -a != 0) for(i = 0; i 125; i+); void main(void) while(1)P0 = 0x06;/1 的碼段P2 = 0x01;/ 選通一位,或者 P2_0 = 1;Delay(20);/ 延時約 20 毫秒P0 = 0X00;/ 關閉顯示P0 = 0x5b;/2 的碼段P2 = 0x02; / 選通一位,或者 P2_1 = 1;Delay(20);P0 = 0X00;P0 = 0x4f;/3 的碼段P2 =

26、0x04; / 選通一位,或者 P2_2 = 1;Delay(20);P0 = 0X00;P0 = 0x66;/4 的碼段P2 = 0x08; / 選通一位,或者 P2_3 = 1;Delay(20);P0 = 0X00;P0 = 0x6d;/5 的碼段P2 = 0x10;/ 選通一位,或者 P2_4 = 1;Delay(20);P0 = 0X00;P0 = 0x7d;/6 的碼段P2 = 0x20;/ 選通一位,或者 P2_5 = 1;Delay(20);P0 = 0X00;五)相信大家一定見過數(shù)字時鐘,教學樓大廳一定有吧。每次路過,基本上只是隨便瞟上一 眼,根本沒去想過他的工作原理什么。但

27、是今天你也可以把他做出來了,是不是覺得自己很有成就感呢!呵呵!A_A接上面所講的,我們先來做個簡單的實驗:在一個數(shù)碼管上輪流顯示0-9這10 個數(shù)字。還楞著干什么,快動手寫程序呀!好象有點難哦, 要不先不要往下看了,嘿嘿,關機吧,自己先去想想,怎么樣?#includeunsigned char code SEG_TAB =0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f; /0-9 數(shù)字void Delay(unsigned int a) /unsigned int 定義為無符整形,取值范圍為 0-32768unsigned char i;wh

28、ile( -a != 0)for(i = 0; i 125; i+);void main(void)unsigned char i; while(1) for(i = 0; i 10; i+) P0 = SEG_TAB i ; / 取 SEG_TAB 數(shù)組中的值P2 = 0X01;Delay(1000);是不是顯示從 0-9 ,跳動顯示,你的心是不是也跟著一起跳呀,離我們的目標又邁進了 一步!不錯,繼續(xù)努力!上面只顯示了一個數(shù)碼管的數(shù)字0-9 ,但是怎么樣要讓他顯示 6 個數(shù)字呢?這樣我們就可以做個時鐘出來玩玩了!還記不記得我們前面 講過的 P2 口的位選作用!嘿嘿,沒忘記就好!#includ

29、eunsigned char hour = 12, min = 0, sec = 0;unsigned char code SEG_TAB = 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f; /0-9 數(shù)字void Delay(unsigned char a)unsigned char i;while( -a != 0)for(i = 0; i 125; i+);void disp(void)P0 = SEG_TAB sec % 10 ;/ 顯示秒的個位P2 = 0X01;Delay(15);P2 = 0;P0 = SEG_TAB sec

30、/ 10 ;/ 顯示秒的十位P2 = 0X02;Delay(15);P2 = 0;P0 = SEG_TAB min % 10 ;/ 顯示分的個位P2 = 0X04;Delay(15);P2 = 0;P0 = SEG_TAB min / 10 ;/ 顯示分的十位P2 = 0X08;Delay(15);P2 = 0;P0 = SEG_TAB hour % 10 ;/ 顯示時的個位P2 = 0X10;Delay(15);P2 = 0;P0 = SEG_TAB hour / 10 ;/ 顯示時的十位P2 = 0X20;Delay(15);P2 = 0;void main(void)while( 1 )

31、disp( );編譯燒錄芯片后, 觀察運行現(xiàn)象。 矣 .怎么一直顯示 12:00:00,難道是時鐘沒有啟動? 還是,另外的原因呢? 哦,原來是 3 個變量 sec,min,hour 初始化后,其值一直沒有改變!那我們怎么樣才能讓他改變數(shù)值呢?有的朋友 一定會這么認為:讓秒個位延時 1 秒,后加 1,而秒十位延時 10 秒后,再加 1,一直加到 6,分個位加 1,依次類推 .這樣的想法是不錯, 但是朋友你有沒有想過 C 語言的一般延時(除非你 把他放到中斷里)極不精確!這樣累計下來,一天 24 小時的誤差,肯定很大很大,我曾經 也用延時的方法寫過時鐘, 1 個小時誤差 8 秒,那是個什么概念!一

32、天 24 小時就要 24*8=192 ,約為 3 分鐘,一個月就是 10 分鐘 .有沒有其他 的方法可以改進些呢?有!這里就要涉及到單片機中另一個比較重要的核心部分: 單片機的中斷和定時器的運用! 想寫出比較精確 (這里說的只 的相對前面的做法而言比較精確而已,如果要做 更加精確的時鐘,用時鐘芯片比較好點,常用的有 DS12887 和 DS1302 等)的時鐘程序, 就一定要調用中斷和定時器。還是大家先看看教材和書 吧,畢竟人家出的書,肯定比我要寫的系統(tǒng)多了,下面我們再來簡單的講講!六)什么是中斷呢?講個比較通俗的例子:比如你正在家中看電視,突然電話響了,你的第 一反應是什么?是不是先跑過去接

33、電話!接完電話 后,繼續(xù)看電視。這就是個中斷的例子,中斷是由電話引起了,你跑過去就是響應中斷,接 電話就是中斷的處理!接完電話后,接續(xù)看電視,即恢復中斷,等待下個中斷的到來!但是這個好象和單片機沒什么聯(lián)系呀?有的朋友或許會這樣疑問。是的。單片機當然不 會看電視了,也不會接電話了! A_A但是,類比一下: 比如單片機正在執(zhí)行某個任務, 突然要有更重要的事件,要求單片機響應, 單片機 就會應答響應,去執(zhí)行更為重要的任務(中斷處理),原來的任務就繼續(xù)等待(現(xiàn)場的保護) 。執(zhí)行完更重要的任務后,回到中斷的入口處,繼 續(xù)執(zhí)行原來的任務(現(xiàn)場中斷的恢復) 。 51 系列的單片機共有 5個中斷源,分別為:外

34、中斷0 、定時器 T0 中斷、外中斷 1、定時器 T1 中斷、串口中斷?;蛟S,有些朋友已經大概領會了其中的意思,有些朋友還迷迷糊糊。不過不要緊,我們 繼續(xù)往下看,下面我們來講講單片機的定時器是什么?如何工作的?定時器, 大家從字面上就可以看出其大概的意思吧?簡單的說: 就是起定 時作用!也就是讓單片機計數(shù)。定時器分為:方式0 方式 1、方式 2 和方式 3 等 4 種工作方式。有些朋友一定會問:定時器如何啟動?風扇的 定時器,相信大家一定都用過吧!但是單片機的定時器, 該如何啟動呢?總不該也用手一擰定時器吧 ! A_A 當然不是,我們只要給單片機一些指令, 就可以啟動定時器了!下面我們就定時器

35、0,來說說怎么啟動定時器 0。TMOD = 0X01;/ 設置定時器 0 工作方式 0 TH0 = (65536 - 5000) / 256;/ 載入高 8 位初值TL0 = (65536 - 5000) % 256;/ 載入低 8 位初值TMOD 為 T/C 方式控制寄存器:TR0 = 1;/啟動定時器A_A,簡單吧,這樣我們就可以把定時器啟動了。其中D7 D6 D5 D4 D3 D2 D1 D0GATE C/T M1 M0 GATE C/T M1 M0| | | | T/C1| |T/C0 |C/T就是counter (記數(shù)器)和timer (定時器)的選擇位,若值為 1則作計數(shù)器用。為

36、0,則為定時期用! GATE 為門控位。 M1 和 M0 工作方式的選擇:若 M1=0 ; M0=0則為方式0: 13位定時/記數(shù)器。若 M仁0 ; M0=1則為方式1, 16 定時/記數(shù)器。若 M1=1; M0=0 則為方式 2,自動裝載 8 位 定時/記數(shù)器。若 M1=1; M0=1 則為方式 3,只適用于 T/C0, 2個8位定時 /記數(shù)器。說了一大堆, 感到有點困惑了吧。 那我們還是來說說上面的。 TMOD= 0X01 ; /至于為什 么是 0X01 ,大家看:我們選擇的是定時器 0 方式 0,所以 T/C1 全為 0,而 T/C0 的 M1 為 0。 M0 為 1,所以 D0-D7

37、為 0X01 ; 0X01 表示的是 16 進制數(shù),這個大家應該都知道吧!還有 D0-D7 表示的是 2 進制數(shù)。還需要轉換一下!TH0 = (65536 - 5000) / 256;/ 載入高 8 位初值。若在 12M 晶體下,定時 5000 微秒,即為 5 毫秒;但是如果不是在 12M 下,那又該怎么計算 了呢?如果是 11.0592M 呢?還記不記得,我們前面講過的機器周期和時鐘周期的概念?A_A忘了,還是看看前面吧!呵呵!沒事,學習嘛,忘了再翻翻書,看看就可以了!其實上訴的5000 = 1 * C 很顯然C=5000,但是如果是11.0592M 那么就不是 1 了,應該是 1.085了

38、,那么 5000 =1.085 * C ,則 C 就為 5000 / 1.085 = ? 具體多少, 大家自己去算算吧?同理 TL0 也是一樣的! 但是,細心的朋友會發(fā)現(xiàn)網上或者是資料上的TH0, TL0 并不是和上面一樣的, 而是直接 TH0 = 0XEC; TL0 = 0X78 是不是和上面的一樣 的,別忘了單片機也是計算機的一種哦。用C的話,直接寫上計算公式就行,計算就交給單片機完成。TR0 = 1 ;這句就是啟動定時器 0,開始記數(shù)! 哦, 還有一點, 有些朋友會問, 你是 65536 是哪里來的呢?呵呵你可別忘了:設置定時器 0 工作方式 0 是 16位的(2的 16次方是多少,自己

39、算算就知道了)簡單吧?但是如何和中斷 一起使用呢?請繼續(xù)看下面的講解!TMOD = 0X01;/ 設置定時器 0 工作方式 0TH0 = (65536 - 5000) / 256;/ 載入高 8 位初值TL0 = (65536 - 5000) % 256;/ 載入低 8 位初值TR0 = 1;/啟動定時器EA = 1 ; /開總中斷 ET0 = 1 ;/開定時器中斷。若為 0則表示關閉! 這樣我們,就初始化定時器 T0 和中斷了,也就是定時器滿 5 毫秒后,產生一次中斷。 產生中斷后,我們怎么處理呢?嘿嘿!仔細想想?A A每次中斷后,我們可以讓一個變量自加1,那么 200 次中斷后,不就是 1

40、 秒的時間了嗎?比起上面我們說的延時來出來是不是更加精確多了呢?那是肯定的!但是想想 1 秒種的時間就讓單片機產生那么多次的中斷,單片機會不會累著 呢?恩,那么不好。如果在 12M 的晶體下, T0 每次中斷不是可以產生最多 65.336 毫秒的時間嗎?那么我們讓他每 50 毫秒中斷一次好了! 這樣我 們就20次搞定一秒的時間了!爽好了,講了那么多,現(xiàn)在我們來寫個時間的程序吧!a_a#include#define HI(65536 - 50000) / 256)#define LO(65536 - 50000) % 256)#define _TH0_TL0_ (65536 - 50000)#d

41、efine M 20 /(1000/25)/*/unsigned hou = 12, min = 0, sec = 0;unsigned char SEG_TAB_B = 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90; /0-9 數(shù)字unsigned char SEG_TAB_A = 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10;/0.-9. 數(shù)字/*/void Delay(unsigned char a)/ 延時程序 a*1MSunsigned char j;while(a- != 0

42、)for (j = 0; j 125; j+);/*/void Disp(void)/ 數(shù)碼管顯示P2_0 = 1;P1 = SEG_TAB_B hou / 10 ;Delay(5);P2_0 = 0;P2_1 = 1;P1 = SEG_TAB_A hou % 10 ;Delay(5);P2_1 = 0;P2_2 = 1;P1 = SEG_TAB_B min / 10 ;Delay(5);P2_2 = 0;P2_3 = 1;P1 =S EG_TAB_A min % 10 ;Delay(5);P2_3 = 0;P2_4 = 1;P1 = SEG_TAB_B sec / 10 ;Delay(5);

43、P2_4 = 0;P2_5 = 1;P1 = SEG_TAB_B sec % 10 ;Delay(5);P2_5 = 0;/*/void IsrTimer0(void) interrupt 1 using 1/定時 50msstatic unsigned char count = 0; / 定義靜態(tài)變量 countcount+;if(count = M)count = 0;sec+;if(sec = 60)min+;sec = 0;if(min = 60)hou+;min = 0;if(hou = 24)hou = 0;/if/if/if/*/void Timer0Init(void) / 定

44、時器 0TMOD = 0x01;TH0 = HI;TL0 = LO;TR0 = 1;ET0 = 1; EA = 1;/*/void main(void) / 主函數(shù)Timer0Init();while(1)Disp();簡單吧,還是有點看不懂哦,那你自己慢慢體會吧,如果你自己能寫個時鐘程序來,那 么你的 51 單片機也就學了 80 % 了。中斷和定時 /記數(shù)器器,是個很重要的東西,幾乎用到單片機的地方都會涉及到中斷和定時!所以 大家要好好掌握哦!A_A哈哈,趕緊編譯 HEX 文件,搭好硬件,燒入單片機,上電看看效果先!呵呵,現(xiàn)在你 應該有成就感了吧,想不到一個時鐘居然那么簡單, 嘿嘿!但是問題

45、來了!時鐘雖然做出來了,但是他的精度怎么樣呢?一兩個小時, 或許看不出什么誤差,但是一天或者一年呢? 暈,我的天呀,要是按年來算的話,那這個時鐘根本沒有實用價值!人家都說用C 寫不出,精度高的時鐘程序來的! !是不是有點后悔了,去學匯編吧!但是既然選擇了C,那么就不要后悔!嘿嘿,想想 C的高級語言,怎么會輸給匯編呢 A_A 呵呵!看下面這段代碼:static unsigned char count = 0;TR0 = 0;TL0 += (_TH0_TL0_ + 9) % 256;TH0 += (_TH0_TL0_ + 9) / 256 + (char)CY ;TR0 = 1;count+;在中

46、斷處理服務程序中,我們加入上面的代碼。TR0 = 0;先關閉定時器TO,然后重新給 TH0 和 TL0 賦值,再開啟 TR0 = 1; 燒入單片 機看看效果,怎么樣,你第一次精確多了吧。但是還是有誤差!郁悶!為什么呢?那是硬件 造成的誤差,我們可以用軟件來彌補!我們先 把時鐘點亮,讓他走上幾個小時或者是幾天,看看到底誤差是多少!取個平均值。(這里比如我們 10 小時快 1 秒)那么可以通過以下語句 if(hour % 10 = 0) sec-; 來彌補!這樣可能會出現(xiàn)這樣的現(xiàn)象:秒直接跳變!我們可以再通過細分來實現(xiàn),不要10小時那么大,小些的就行!具體的操作還是留給朋友們吧!七)這回我們來講講

47、鍵盤,大家肯定見過銀行柜員機吧,取錢輸入密碼就要用到鍵盤,超市 購物取回寄存物品要輸入密碼,還有你現(xiàn)在在用的 PC 機的鍵盤。但是鍵盤的是怎么工作的呢?一般有2 種方式:(1)掃描法,不斷掃描鍵盤的狀態(tài),送 CPU 判斷并處理。如果鍵盤數(shù)目一大的話,顯然不適合( 2)線反轉法,通過行列狀態(tài)的改變來判斷有無鍵被按下!現(xiàn)在我們在 P1 口接個 4*4 的鍵盤, P1.0 P1.3 接行 ,P1.4-P1.7 接列 ,再接 4 個 4K7 的上拉電阻至 VCC。代碼如下:/ 鍵盤掃描法程序 / 用數(shù)碼管顯示相應的鍵值 /P1.0 P1.3 接行 /P1.4-P1.7 接列 #includeunsig

48、ned char code tab =0x3F ,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71;/0 到 F 的 16 個鍵植 /*/void Delayt(unsigned char t)/ 延時函數(shù)unsigned char i;for(t=0;i=t;t+)for(i=0;i255;i+);/*/bit pkey(void)/ 判斷鍵的否被按下,通過返回值確定P1=0xf0;if(P1!=0xf0)Delayt(25);if(P1!=0xf0)return 1;elsereturn 0

49、;elsereturn 0;/*/void main(void)/ 主函數(shù)unsigned char key,j,k,s;while(1)if(pkey()=1)P1=0xfe;k=0xfe;for(j=0;j4;j+)s=P1&0xf0; switch(s)case 0xe0: key=4*j+0; break; case 0xd0: key=4*j+1; break;case 0xb0: key=4*j+2; break;case 0x70: key=4*j+3; break; default: break;k=(k1)|0x01;P1=k;/for/if/if(P1&0xf0)=0xf0

50、)P0=tabkey;P2=1;Delayt(50);/while還有一種就是線反轉法,實現(xiàn)如下:1. 和掃描法相同,把列線置低電平,行置高,讀行狀態(tài)2. 與 1 相反,把行置低,列置高,讀列狀態(tài)3. 若有鍵按下,則為 2 次所讀狀態(tài)的結果即為鍵所在的位置,這樣 2 次輸出和 2 次讀入可以 完成鍵的識別! !子函數(shù)如下:unsigned char key_vscan(void)unsigned char row, col;P1 = 0xF0;row = P1&0xF0;row = row&0xF0;P1 = 0x0F; col = P1&0x0F;col = col&0x0F;return(key_val(row|col);下面我們再來介紹介紹一鍵多能的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論