中斷是單片機系統的重點中的重點,因為有了中斷,單片機_第1頁
中斷是單片機系統的重點中的重點,因為有了中斷,單片機_第2頁
中斷是單片機系統的重點中的重點,因為有了中斷,單片機_第3頁
中斷是單片機系統的重點中的重點,因為有了中斷,單片機_第4頁
中斷是單片機系統的重點中的重點,因為有了中斷,單片機_第5頁
已閱讀5頁,還剩10頁未讀, 繼續免費閱讀

下載本文檔

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

文檔簡介

1、中斷是單片機系統的重點中的重點 , 因為有了中斷 , 單片機6.1 C 語言的數組 6.1.1 數組的差不多概念 我們第四章學過變量的差不多類型, 比如 char 、int 等等。 這種類型描述的數據 是比較有限的, 當我們要處理特別大量數據的時候, 就能夠用到數組了, 比如我 們上節課的那個數碼管的真值表,我們就能夠用一個數組來表達。從概念上講, 數組是具有相同數據類型的有序數據的組合, 一般來講,數組定義 后滿足以下三個條件。(1) 具有相同的數據類型;(2) 具有相同的名字;(3) 在存儲器中是被連續存放的。比如我們上節課定義的那個數碼管真值表, 假如我們把關鍵字 code 去掉, 數組

2、元素將被保存在RAM中,在程序中可讀可寫,同時我們也能夠在中括號里邊 標明那個數組元素的個數,比如: unsigned char LedChar16 = 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8e; 在那個數組中的每個值都稱之為數組的一個元素, 這些元素都具備相同的數據類 型確實是unsigned char型,他們有一個共同的名字 LedChar,不管放到RAM中 依舊FLASH中,他們基本上存放在一塊連續的存儲空間里的。 有一點要特別注意,那個數組一共有16中括號里面的數值個

3、元素,然而數組的元素的表達方式下標是從 0 開始,因此實際上上邊那個數組的首個元素 LedCharO的值是OxCO,而LedChar15的值是0x8e,下標從0到15 一共是16 個元素。LedChar那個數組只有一個下標,我們稱之為一維數組,還有兩個下標或者多個 下標的,我們稱之為多維數組。比如 unsigned char a23; 表示這是一個 2 行 3 列的二維數組。 在大多數情況下我們使用的是一維數組, 關于初學來說, 我 們先來研究一維數組,多維數組遇到了再了解。6.1.2 數組的聲明 一維數組的聲明格式如下: 數據類型 數組名 數組長度;(1) 數組的數據類型聲明的是該數組的每個

4、元素的類型,即一個數組中的元素具 有相同的數據類型。(2) 數組名的聲明要符合C語言固定的標識符的聲明要求,只能由字母、數字、 下劃線這三種符號組成,且第一個字符只能是字母或者下劃線。(3) 方括號中的數組長度是一個常量或常量表達式,同時必須是正整數。6.1.3 數組的初始化 數組在進行聲明的同時能夠進行初始化操作,格式如下: 數據類型 數組名數組長度 = 初值列表; 依舊以上節課我們用的數碼管的真值表為例來講解考前須知。unsigned char LedChar16 = 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90,0x88,0x83,

5、0xC6,0xA1,0x86,0x8e;(1) 初值列表里的數據之間要用逗號隔開。(2) 初值列表里的初值的數量必須小于或者等于數組長度,當小于數組長度時, 數組的后邊沒有賦初值的元素由系統自動賦值0。(3) 假設給數組的所有元素賦初值,能夠省略數組的長度,上節課的例子中我們 實際上差不多省略了數組的長度。(4) 系統為數組分配連續的存儲單元的時候, 數組元素的相對次序由下標來決定, 確實是說 LedChar0 、LedChar1. . LedChar15是按照順序排下來的。6.1.4 數組的使用和賦值在 C 語言程序中, 是不能一次使用整個數組的, 只能使用單個數組元素。 一個數 組元素相當

6、于一個變量, 使用數組元素的時候與使用相同數據類型的變量的方法 一樣。比如那個LedChar那個數組,假如沒加code關鍵字,那么它可讀可寫, 我們能夠寫成 a = LedChar0 如此來把數組的一個元素的值送個 a 那個變量, 也能夠寫成 LedChar0 = a 如此把 a 那個變量的值送給數組的一個元素,以下*1 ' I I I、I -、八三點要注意:(1) 引用數組的時候,那個方括號里的數字代表的是數組元素的下標,而數組初 始化的時候方括號里的數字代表的是那個數組元素的個數。(2) 數組元素的方括號里的下標能夠是整型常數,整型變量或者表達式,而數組 初始化的時候方括號里的數字

7、必須是常數不能是變量。(3) 數組整體賦值只能夠在初始化的時候操作,功能程序只能對單個元素賦值。6.2 if 語句if 語句差不多不陌生了,前邊程序我們事實上差不多用過了,那個地方我們系 統的介紹一下,方便后邊的深入學習。 if 語句有兩個關鍵字: if 和 else ,把這 兩個關鍵字翻譯一下確實是:“假如”和“否那么”。 if 語句一共有三種格式, 我們分別來看。1.if 語句的默認形式。if ( 條件表達式 ) 語句 1;其執行過程是, if( 假如)條件表達式的值為“真”,那么執行語句 1;假 如條件表達式的值為“假”,那么不執行語句1。真和假的概念不再贅述,參考第五章。那個地方要提醒

8、一句,C語言一個分號表示一句語句的結束,因此假如if后邊只有一條執行語句的時候, 能夠省略大括號, 然而假如有多條執行語句的話, 必須加上大括號。我們上節課的語句就很好理解了 if(16 =j) j = 0; ,假如 j 等于 16 的時候,括號里的值才是“真”,那么就執行 j=0 這一句,假如 j 不等于 16, 那么里邊就為“假”,就不執行這一句。2.if.else語句有些情況下,我們除了判斷一下 if 括號里的是否滿足條件,執行相應的 語句,在不滿足條件的時候, 我們又要執行另外相應的語句, 那個時候就用到了 if.else語句,它的差不多的語法形式是:if ( 條件表達式 ) 語句 1

9、;else 語句 2;比如上節課的后半段程序我們也能夠寫成:P0 = LedCharj;/ 把數組里的對應值送給P0if(15 = j)/ 當顯示到 F 后,歸0 重新開始j = 0;elsej+; 那個程序大伙能夠改改下載進去試試,程序邏輯大伙自己動腦分析一下, 我就不解釋了。3.if else if語句if.esle語句是一個二選一的語句,或者執行 if 條件下的語句,或者執行 else 條件下的語句。還有一種多項選擇一的用法確實是 if.elseif 語句。他的差不多語法格式是:if ( 條件表達式 1) 語句 1;else if (條件表達式 2)語句 2; else if (條件表達

10、式 3)語句 3; else 語句 n; 他的執行過程是:依次判斷條件表達式的值,當出現某個值為“真”時,那么執 行相對應的語句,然后跳出整個if的語句塊,執行“語句n”后邊的程序;假 如所有的表達式都為“假”,那么執行“語句n”后,再執行“語句n”后邊的程序。if語句在C語言編程的過程中使用頻率很高,用法也簡單,因此必須要熟練掌 握。6.3 switch 語句用 ifelse 語句在處理多分支的時候,分支太多就會顯得不方便,且容易出現if和else配對出現錯誤的情況,在C語言中提供了另外一種多分支選擇的語 句 switch 語句,它的差不多語法格式如下: switch ( 表達式 )case

11、 常量表達式 1:執行語句 1;case 常量表達式 2:執行語句 2; case常量表達式n:執行語句n;default:執行語句 n+1;它的執行過程是:首先計算“表達式”的值,然后從第一個case開始,與“常量表達式x”進行比較,假如與當前常量表達式的值不相等,那么就不執行冒號 后邊的程序,一旦發明和一個常量表達式的值相等了, 那么他會執行之后所有的, 注意是所有的“執行語句”,顯然這不是我們想要的結果。在C語言中,有一條break語句,作用是跳出當前循環語句,不管是for和while 循環,依舊 switch 循環,都能夠用其搭配使用跳出循環。 switch 語句一共有 n+1 種可能

12、,而我們盼望要的是一條多項選擇一的語句, 只執行其中一條然后直截了當退出該循環, 不再執行下邊的任何語句, 那個時候就需要用到 break 語句,比 如我們在 switch 表達式上加上 break 語句,如下:switch ( 表達式 )case 常量表達式 1:執行語句 1;break ;case 常量表達式 2:執行語句 2;break ;case 常量表達式 n 執行語句 n; break;default: 語句 n+1;加了那個break語句后,一旦“常量表達式x”與“表達式”相等了,那就執行 “執行語句x”,執行完畢后,由于有了 break,直截了當跳出switch語句,執 行 s

13、witch 語句循環后邊的程序了,如此就能夠幸免執行不必要的語句。了解了 那個 switch 語句,我們將會在本章程序中使用鞏固。6.4 數碼管的動態顯示 6.4.1 動態顯示的差不多原理 我們在上一章學習數碼管靜態顯示的時候說到,74HC138只能在同一時刻導通一個三極管, 而我們的數碼管是靠了 6 個三極管來操縱, 那我們如何來讓數碼管同 時顯示呢?這就用到了我們這節課的動態顯示。多個數碼管顯示數字的時候, 我們實際上是輪流點亮數碼管 一個時刻內只有一 個數碼管是亮的,利用人眼的視覺暫留現象也叫余輝效應,就能夠做到看 起來是所有數碼管都同時亮了,這確實是動態掃描顯示的含義。例如:我們有 2

14、個數碼管,我們要顯示“ 12”那個數字,讓高位的位選三極管導 通,然后給它賦值“ 1”,延時一定時間后讓低位的位選三極管導通,然后給它 賦值“ 2”。把那個流程以一定的速度循環運行就能夠讓數碼管顯示出“12”,由于交替速度特別快,人肉眼識別到的確實是“12”那個數字。那么一個數碼管需要點亮多長時間呢?也確實是說要多長時間完成一次全部數 碼管的掃描呢很明顯: 整體掃描時間 =單個數碼管點亮時間 *數碼管個數?答 案是:10ms以內。當電視機和顯示器還處在 CR電子顯像管時代時,有一句 很流行的廣告語一一“100Hz無閃爍”,沒錯,只要刷新率大于 100Hz即刷新 時間小于10ms就能夠做到無閃爍

15、,這也確實是我們的動態掃描的硬性指標。 那么你也許會問, 有最小值的限制嗎?理論上沒有, 但實際上做到更快的刷新卻 沒有任何進步的意義了, 因為差不多無閃爍了, 再快也依舊無閃爍, 只是徒然增 加CPU勺負荷而已因為1秒內要執行更多次的掃描程序。因此,通常我們設 計程序的時候,基本上取一個接近 10ms又比較規整的值就行了。我們板子上 有 6 個數碼管,我們下面用程序來驗證一下數碼管動態顯示程序。#include <reg52.h>/ 包含寄存器的庫文件sbitADDR0 =P1A0;sbitADDR1 =P1A1;sbitADDR2 =P1A2;sbitADDR3 =P1A3;s

16、bitENLED =P1A4;unsigned char code LedChar = / 用數組來表示數碼管真值表0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8e,;void main()unsigned int counter = 0;unsigned char j = 0;unsigned long stopwatch = 0;unsigned char LedNumber6 = 0;ENLED = 0; ADDR3 = 1;P0 = 0XFF;/74HC138和P0初始化部分T

17、MOD = 0x01; / 設置定時器 0 為模式 1TH0= 0xFC;TL0= 0x67; /定時值初值 , 定時TR0= 1;/ 打開定時器 0while(1)if(1 = TF0)TF0 = 0;TH0 = 0xFC;TL0 = 0x67; counter+;if(1000 = counter) 達到 50 次counter = 0; stopwatch+;/ 秒表數值一秒加 1LedNumber0LedNumber1LedNumber2LedNumber3 管顯示值計算LedNumber4LedNumber5if (0=j)1ms/ 判斷定時器 0 是否溢出/ 一旦溢出后,重新賦值/

18、 判斷定時器 0 溢出是否/stopwatch%10; stopwatch/10%10;stopwatch/100%10;stopwatch/1000%10; / 數碼 stopwatch/10000%10;stopwatch/100000%10; ADDR0=0; ADDR1=0; ADDR2=0; j+;P0=LedCharLedNumber0; else if (1=j) ADDR0=1; ADDR1=0; ADDR2=0; j+;P0=LedCharLedNumber1; else if (2=j) ADDR0=0; ADDR1=1; ADDR2=0; j+;P0=LedCharLed

19、Number2; else if (3=j) ADDR0=1; ADDR1=1; ADDR2=0; j+;P0=LedCharLedNumber3; else if (4=j) ADDR0=0; ADDR1=0; ADDR2=1; j+;P0=LedCharLedNumber4; else if (5=j) ADDR0=1; ADDR1=0; ADDR2=1; j=0;P0=LedCharLedNumber5; / 數碼管動態刷新部分 這程序,大伙自己抄到 Keil 中,然后邊抄邊理解,最終下載到實驗板上實驗一 下效果。其中下邊的if.else 語句確實是每1ms快速的刷新一個數碼管,如此 6

20、個數碼管整體刷新一遍的時間確實是 6ms視覺上確實是6個數碼管無閃爍的 同時亮起來了。另外一個簡單知識點那個地方也提一下, 事實上屬于小學三年級知識, 然而許多 同學剛接觸C語言,可能遇到了也會發懵。確實是在數碼管顯示值計算那個地方, 相信小學我們沒學小數之前,除法運算里邊有“被除數”、“除數”、“商”、“余數”這四個概念年。而在我們 C語言中,“ / ”等同于數學里的除法運算, 而“%”等同于我們小學學的求余數運算。假如是 1 23456那個數字,我們要正常 顯示在數碼管上, 個位顯示, 確實是直截了當對 10取余數, 那個“6”就出來了, 十位數字確實是先除以 10,然后再對 10取余數,

21、以此類推,就把 6個數字全部 顯示出來了。關于多項選擇一的動態刷新數碼管的方式, 我們假如用 switch 會有更好的效果, 大伙來看一下我們用 switch 語句完成的情況。#include <reg52.h>/ 包含寄存器的庫文件sbitADDR0 =P1A0;sbitADDR1 =P1A1;sbitADDR2 =P1A2;sbitADDR3 =P1A3;sbitENLED =P1A4;unsigned char code LedChar = / 用數組來表示數碼管真值表0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90,0x8

22、8,0x83,0xC6,0xA1,0x86,0x8e,;void main()unsigned int counter = 0;unsigned char j = 0;unsigned long stopwatch =0;unsigned char LedNumber6=0;ENLED = 0; ADDR3 = 1;P0 = OXFF;/74HC138 和 P0初始化部分TMOD = 0x01; / 設置定時器 0 為模式 1TH0= 0xFC;TL0= 0x67; / 定時值初值 , 定時 1msTR0= 1; / 打開定時器 0 while(1)if(1 = TF0)TF0 = 0; TH

23、0 = 0xFC;TL0 = 0x67; counter+; if(1000 = counter) 達到 1000 次 counter = 0; stopwatch+;/ 秒表數值一秒加 1LedNumber0 LedNumber1 LedNumber2 LedNumber3 管顯示值計算LedNumber4 LedNumber5 switch(j) case 0: ADDR0=0; A/ 判斷定時器 0 是否溢出/ 一旦溢出后,重新賦值/ 判斷定時器 0 溢出是否/stopwatch%10;stopwatch/10%10;stopwatch/100%10;stopwatch/1000%10;

24、 / 數碼stopwatch/10000%10;stopwatch/100000%10; ADDR2=0; j+;P0=LedCharLedNumber0;break;case 1: ADDR0=1; ADDR1=0; ADDR2=0; j+; P0=LedCharLedNumber1;break;case 2: ADDR0=0; ADDR1=1; ADDR2=0; j+; P0=LedCharLedNumber2;break;case 3: ADDR0=1; ADDR1=1; ADDR2=0; j+;P0=LedCharLedNumber3;break;case 4: ADDR0=0; AD

25、DR1=0; ADDR2=1; j+; P0=LedCharLedNumber4;break;case 5: ADDR0=1; ADDR1=0; ADDR2=1; j=0; P0=LedCharLedNumber5;break;default: break;/ 數碼管動態刷新部分大伙是否能感受到 switch 語句比 if.else語句顯得要整齊的多?6.4.2 數碼管消隱處理 不明白細心的同學能否發明, 我們的兩次數碼管動態刷新顯示的時候大概并不是 那么完美,第一個小問題,大伙認真看,數碼管的不應該顯示的段,大概有微微 的發亮,這種現象叫做“鬼影”,那個“鬼影”嚴峻妨礙了我們的視覺效果,我

26、們該如何解決呢?同 學們今后可能會遇到各種各樣的問題,可能有許多我是沒有講過的問題,遇 到問題如何辦呢?大伙要相信, 你作為初學者, 遇到的問題確信不是第一個遇到 的,確信 有前輩會遇到同類問題, 他們一般會在網上發表各種帖子, 各種討論, 因此大伙遇到問題, 首先解決方法就應該形成一個到網上搜索的條件反射, 那個 問題大伙能夠 到網上搜:“數碼管消隱”或者“數碼管鬼影解決”,多找相關 關鍵詞搜索,會搜索也是一種能力。大伙在網 上搜了一下會發明, 解決這類問題的普遍兩個方法, 其中之一是延時, 延時之后我們肉眼就可能看不到那個 “鬼影” 了。然而延時是一個特別拙劣的手 段,且不說延 時多久能讓

27、我們看不到“鬼影”,延時后,我們的數碼管亮度會 普遍降低。我們解決問題呢,不能只知其然,不知其因此然,因此我們首先要弄 懂什么原因會出現“鬼 影”?!肮碛啊钡某霈F, 要緊是因為我們數碼管位選和段選產生的瞬態所造成的。 舉個 簡單例子, 我們在數碼管動態刷新的那部分程序中, 實際上每一個數碼管點亮的 持續時間是1ms的時間,1ms后進行下個數碼管的切換。在進行數碼管切換的時 候,比如我們從 case 5要切換到 case 0的時候, case 5的位選用的是 ADDR0=1; ADDR仁0; ADDR2=假如此刻case5也確實是最高位數碼管對應的值是 0。我們 要切換成的case 0的數碼管位

28、選是 ADDR0=0; ADDR1=0; ADDR2=而對應的數碼 管的值假如是 1。因為我們的C語言程序是一句一句順序往下執行的,每一條語句都會占用一定的 時間,即使那個時間特別特別短暫。然而當我們把“ ADDR0=”改變成“ADDR0=0 的時候,那個瞬間存在了一個中間狀態 ADDR0=0; ADDR1=0; ADDR2#那個瞬 間上,我們就給case 4對應的數碼管DS5瞬間賦值了 0。當我們全部寫完了 ADDR0=0; ADDR1=0; ADDR2后;,那個時候,我們的 P0還沒有正式賦值,而 P0 此刻卻保持了前一次的值,也確實是在那個瞬間,我們又給 case 0 對應的數碼 管DS

29、1賦值了一個0。直到我們把case 0后邊的語句全部完成后,我們的刷新 才正式完成。 而在那個刷新過程中, 有2次瞬間我們給了錯誤的數碼管賦值, 盡 管很弱因為亮的時間很短,然而我們依舊能夠發明。那 弄懂了原理后,解決起來就不是困難的情況了,我們只要避開那個瞬態就能 夠了。不產生瞬態的方法是, 我們在進行刷新的賦值語句期間, 幸免一切數碼管 的賦值即 可。方法有兩個,一個方法是刷新之前關閉所有的段,改變好了位選 后,再打開段即可;第二個方法是關閉數碼管的位,賦值過程都做好后,再重新 打開即可。那個 不是很難,答案我都公布一下。關閉段:在switch(j)這句程序之前,加一句P0=0XFF如此就

30、把數碼管所有的 段都關閉了,當把“ ADDR的值全部搞定后,再給P0賦對應的值即可。關閉位:在switch(j) 這句程序之前,加上一句ENLED=1等到把“ADDR=0ADDR1=0; ADDR2=0;P0=LedCharLedNumber0; 這幾條刷新程序全部寫完后, 再加上一句 ENLED=0 然后再進行 break 操作即可。那個地方略微有點邏輯思路在里邊, 大伙一定要理解深刻, 深刻理解, 完全弄明 白,把那個瞬態弄明白, 后邊許多牽扯到此類情況的問題, 我們都能夠一并搞定。 上邊的數碼管程序還有第二個問題, 大伙認真看, 我們的數碼管上的數字每一秒 變化一次,變化的時候, 不參加

31、變化的數碼管可能出現一次抖動, 那個抖動沒有 什么專業的名字, 我們就稱之為數碼管抖動吧。 這種數碼管抖動是什么緣故造成 的呢?為何在數據改變的時候才抖動呢? 我們來看我們的程序。 我們的程序在定時到 1秒的時候, 執行了“數碼管顯示值 計算”那個過程,一個 32 位的除法運算,實際上是比較耗費時間的,至于這一 段程序占用了多少時間,大伙能夠通過第四章講的Debug進入看看這段程序運行 一共占據了多少時間。 由于達到 1秒的時候, 程序多運行了這么一段, 導致了某 個數碼管的點亮時間比其他情況下要長一些,時間是1ms程序消耗時間,于此同時,其它的數碼管就熄滅了 5ms4程序消耗時間,假如那個程

32、序消耗時間特別 短,那么能夠忽略不計,但很明顯,現在這段程序差不多比較長了,嚴峻妨礙我 們的視覺效果了,因此我們要采取另外一種思路去解決那個問題。6.5 中斷的學習 6.5.1 中斷的產生背景 比如此刻我正在廚房用煤氣燒一壺水,燒開一壺水剛好需要 10分鐘。我是一個 主體,燒水是一個目的,而且我只能時 時刻刻在那個地方燒水,因為一旦水開 了,溢出來澆滅煤氣的話,有可能引發一場災難。而那個時候呢,我聽到了電視 里傳來天龍八部的主題歌,馬上就要開演了, 我真想奪門而出,去看我最 喜愛的電視劇。然而,聽到那個水壺發出的“咕嘟”的聲音,我清晰:除非水開 了,否那么我是無法享受我喜愛的電視劇的。那個地方

33、邊主體只有我一個, 而我要做的有兩件情況, 一個是看電視, 一個是燒 水,而電視和燒水是兩個獨立的客體,他們是同時進行的。其中燒水需要 10分 鐘,但不需要了解燒水的過程的, 只需要得到水燒開的如此一個結果就行了, 提 下水壺和關閉煤氣只需要幾秒的時間而已。 因此我們采取的方法確實是: 燒水的 時候,定上一個鬧鐘,定時 10 分鐘,然后我就能夠安心看電視了。當 10分鐘時 間到了,鬧鐘響了,此刻水也燒開了,我就過去把煤氣滅掉,然后接著回來看電 視就能夠了。那個場景和單片機有什么關系呢? 在單片機的程序處理過程中也有許多類似的場景, 當單片機正在用心致志的做一 件情況的時候 (如看電視 ),總會

34、有一件或者多件緊迫或者不緊迫的情況發生, 需 要我們去關注, 有一些需要我們停下手頭的工作去馬上完成 ( 比如水開了 ),只有 處理完,才能回頭接著完成剛才的工作 ( 看電視) 。假如在那個地方用上了單片機 的中斷機制, 不僅僅我擁有了處理意外情況的能力, 而且假如我能夠充分發揮那 個機制的妙用,就能夠“同時”完成多個任務了。假如依舊一知半解關于中斷更 6.5.2 定時器中斷應用方法 在第五章我們學過定時器,而實際上定時器一般用法基本上采取中斷方式來做 的,我是有意在第五章用查詢法,確實是使用 if(TR0 =0) 這 樣的語句先講定 時器,目的是明確告訴同學們, 定時器和中斷不是一回事, 定

35、時器是單片機模塊 的一個資源,確真的實存在的一個模塊,而中斷,是單片機的一種運 行機制。 尤其是初學者們, 許多人會誤以為定時器和中斷是一個東西, 只有定時器才會觸 發中斷,但實際上許多事件都會觸發中斷的,除了“燒水”,還有“有人按 門 鈴”,“來標準 51 中與中斷相關的寄存器,一共有 2 個,其中 1 個是中斷使能 寄存器,另外 1 個是中斷優先級寄存器, 那個地方先介紹中斷使能寄存器。 隨著一些增強型 51 單片機的問世,可能會有增加的寄存器,大伙這些理解了那個地 方所講的,其他的通過自己研讀數據手冊全部能夠理解明白同時使用起來??晌粚ぶ?;復位值:0x00;復位源:任何復位位76 54

36、3 210符號EA- ET2ES ET1 EX1ET0EX0表 6-2 IE-中斷使能寄存器的位描述位符號描述76EA總中斷使能位,相當于總開關65ET2定時器 2 中斷使能4ES串口中斷使能3ET1定時器 1 溢出中斷使能2EX1外部中斷 1 使能1ET0定時器 0 中斷使能0EX0外部中斷 0 使能中斷使能寄存器IE 操縱了 6個中斷使能,其中第 6 位臨時不用,第七位是總開關,相當于我們家里或者學生宿舍里的那個電源總閘門。 而0到 5位這 6個相當 于每個分開關。那么也確實是說,我們只要用到中斷,就要寫 EA = 1 這一句, 打開中斷總開關,然后用到哪個分中斷,再打開相對應的位就能夠了

37、。 我們現在就把第五章學的定時器的程序進行改寫, 使用中斷實現出來, 把數碼管 的抖動問題也同時一并處理掉。#include <reg52.h> / 包含寄存器的庫文件sbitADDR0 =P1A0;sbitADDR1 =P1A1;sbitADDR2 =P1A2;sbitADDR3 =P1A3;sbitENLED =P1A4;unsigned char code LedChar = / 用數組來表示數碼管真值表0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8e,;unsig

38、ned char LedNumber6 = 0; / 定義全局變量unsigned char j = 0;unsigned int counter = 0;void main()unsigned long stopwatch =0;ENLED = 0; ADDR3 = 1; P0 = 0XFF;/74HC138 和 P0 初始化部分TMOD = 0x01;/ 設置定時器 0 為模式 1TH0= 0xFC;TL0= 0x67;/ 定時值初值 , 定時 1msTR0= 1;/ 打開定時器 0EA = 1; / 打開中中斷ET0 = 1;/ 打開定時器 0 中斷while(1)if(1000 = c

39、ounter) / 判斷定時器1000次counter = 0; stopwatch+; LedNumber0 = stopwatch%10; LedNumber1 = stopwatch/10%10; LedNumber2 = stopwatch/100%10; LedNumber3 = stopwatch/1000%10; LedNumber4 = stopwatch/10000%10; LedNumber5 = stopwatch/100000%10;void InterruptTimer0() interrupt 1 的特別寫法,數字' 1'為中斷入口號TH0 = 0x

40、FC; / 溢出后進入中斷重新賦值TL0 = 0x67;counter+;/ 計數值 counter 加 1P0 = 0xFF;/ 消隱switch(j)case 0: ADDR0=0; ADDR1=0; ADDR2=0; j+;P0=LedCharLedNumber0; break;case 1: ADDR0=1; ADDR1=0; ADDR2=0; j+;P0=LedCharLedNumber1; break;case 2: ADDR0=0; ADDR1=1; ADDR2=0; j+;P0=LedCharLedNumber2; break;case 3: ADDR0=1; ADDR1=1;

41、 ADDR2=0; j+;P0=LedCharLedNumber3; break;case 4: ADDR0=0; ADDR1=0; ADDR2=1; j+;P0=LedCharLedNumber4; break;case 5: ADDR0=1; ADDR1=0; ADDR2=1; j=0;P0=LedCharLedNumber5; break;default: break; / 動態刷新0 溢出是否達到/ 中斷函數大伙能夠先把那個程序了解明白,下載到單片機里邊實驗一下,看看實際效果。 是否能夠看出來, 近乎完美的顯示效果通過我們的努力終于做成功了。 那下面我 們還要來解析一下我們的那個程序。

42、在我們那個程序中, 有兩個函數,一個是主函數,一個是中斷函數。主函數 main() 我們就不用說了, 重點強調一下中斷函數, 中斷函數的格式是固定的, 首先中斷 函數前邊 void 表示函數返回空,即中斷函數不返回任何值,函數名字是 InterruptTimer0() ,那個函數名字只要符合函數命名規那么的前提下我們就能 夠隨便起, 我如此起名字是為了方便區分和經歷, 而后是 interrupt 那個關鍵字 不能錯,那個是中斷特有的關鍵字,另外后邊還有個數字 1,那個數字 1 如何來 的呢?我們先來看一個表格。表 6-3 中斷查詢序列描述中斷標志中斷使能默認優先級外部中斷 OIEOOOO3HE

43、XO1( 最高 )TO中斷TFOOOOBHETO2外部中斷 1IE1OO13HEX13T1 中斷TF1OO1BHET14UART中 斷TI/RIOO23HES5T2中斷TF2/EXF2OO2BHET26那個表格同樣不需要大伙記住, 需要的時候過來查就能夠了。 我們現在看第二行TO中斷,它的中斷標志是TFO,也確實是當TFO變成1的時候,就會觸發中斷。 而在interrupt 后邊的數字x的計算方法是x*8+3 =向量地址,TO的向量地址是 OOOBH那么我們能夠求得X的值是1。如此那個中斷函數名字我們就完全明白 了。中斷函數和一般函數有個不一樣的地方, 一般函數一般是在程序中調用, 而中斷 函

44、數因為有了中斷入口, 達到中斷條件后, 他會自動進入程序執行。 比如咱那個 程序,平時一直在主程序 while(1)的循環中運行,假如程序有1OO行,當運行 到了 5O行的時候,定時器溢出了,那么 CPU就會趕忙跑到中斷函數中執行中斷 程序,中斷程序運行完畢后再自動返回到剛才的第 5O 行處接著運行下面的程序, 如此就保證了動態刷新是固定的1ms時間,可不能因為程序運行時間不一致的緣 故導致數碼管的抖動了。6.5.3 中斷的優先級中斷優先級的內容, 大伙先通過我的介紹大概了解一下即可, 后邊真正實際應用 的時候我們再詳細理解。在講中斷產生背景的時候, 我們僅僅講了看電視和燒水的例子, 然而實際生活話 的“中斷”程序當中去, 就在接電話的同時, 聽到了水開的聲音, 水開的“中斷” 也發生了,我們要放下手上的電話,先把煤氣關掉,然后再回來聽電話,最后聽 完了電話再看電視,那個地方就產生了一個優先級的問題。還有一種情況, 我們在看電視的時候, 那個時候聽到水開的聲音, 水開的“中斷” 發生了,我們要進入關煤氣的“中斷”程序當中,而在關煤氣的同時,電話聲音 響了,而那個時候,我們的處理方式是先把煤氣關閉,再去接聽電話,最后再看 電視。從這兩個過程中, 我們能夠得到一個結論, 確實是最最緊急的情況, 一旦發生后, 我們不管當時處在哪個“程序”當中,我們必須先去解決最最緊急的情

溫馨提示

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

評論

0/150

提交評論