|
EM78 系列八位微控器是利用 (1)“call",(2) 改變PC (或“tbl"),(3)“retl k" 三個(gè)步驟來查表的。其中“retl k" 是將常數(shù) k 的值傳至工作寄存器 "A" 中。 步驟 (2) 中若利用“ MOV 0x2,a",或“add 0x2,a" 等等指令來改變PC,則因?yàn)榇说戎噶顣䦟?PC (R2) 的位 8、9 清除 (在 EM78056 只清除位 8),所以查表的內(nèi)容只能放在程序每個(gè) PAGE 的較低的 256 個(gè)位址。步驟 (2) 中若利用“tbl" 指令來改變PC,則因?yàn)榇酥噶畈粫䦟C (R2) 的位 8、9 清除,而保留“tbl" 所在位址的位 8、9,所以查表的內(nèi)容可以放在程序每個(gè) PAGE 中的任何位址。 例:查表 table add 0x02,a ;將相對位置加入 PC 而改變了PC retl @0x19 ;傳回常數(shù)內(nèi)容 19h 至 "A" retl @0x74 ;傳回常數(shù)內(nèi)容 74h 至 "A" retl @0x2e ;傳回常數(shù)內(nèi)容 2eh 至 "A" retl @0x54 ;傳回常數(shù)內(nèi)容 54h 至 "A" retl @0x4b ;傳回常數(shù)內(nèi)容 4bh 至 "A" inc 0x18 mov a,0x18 ;欲查的內(nèi)容的相對位置放在"A" call table ;查表 mov 0x10,a ;查表得到的內(nèi)容移至 R10 中 1. 程序跳 PAGE 的用法: EM78 系列八位微控器將其 Program Memory (ROM) 分成數(shù)個(gè) PAGE,每個(gè) PAGE 的長度是 1K (EM78056 除外)。R3 寄存器的位 5 (6) 是 "PAGE 選擇位",當(dāng)執(zhí)行 "jmp" 或 "call" 指令時(shí),"PAGE 選擇位" 會被載入 Program Counter 的位 10 (11),因此當(dāng)程序超過 1K (EM78056 為 0.5K)時(shí),執(zhí)行 "jmp" 或"call" 指令時(shí),"PAGE 選擇位" 正確的設(shè)定是非常重要的。下面將以 EM78256 為例來說明跳 PAGE 的方法。 例 例:從PAGE 1 跳轉(zhuǎn)到PAGE 0 ; PAGE 0, begin at 000h 049 add 0x11,a 051 mov 0x05,a ;port5<-- 0x55 052 bs 0x03,5 ;select PAGE 1 053 jmp lab1 ;PAGE jump 054 ; PAGE 1, begin at 400h 447 448 mov a,@0x3f 449 xor 0x12,a 450 Lab1 bc 0x06,3 451 mov a,0x05 說明: 052: 將 R3 寄存器的位 5 設(shè)為 "1" (選擇 PAGE 1)。 053: Lab1 會被編譯 為 "50",程序跳轉(zhuǎn)至 PAGE 1 中 "Lab1" (450) 的位址。 注意: 此例中 "052" 和 "053" 是用來跳 PAGE 的,假如沒有 "052" 這行指令,則程序?qū)⑻D(zhuǎn)至"050" 的位址 (在 PAGE 0中),如此將沒有達(dá)到預(yù)期的目的。 2. 不同 PAGE 子程序呼叫的方法: 如第 1 項(xiàng)所述,當(dāng)程序超過 1K 時(shí),執(zhí)行 "call" 指令時(shí),"PAGE 選擇位" 的設(shè)定就必須加以考慮。下面將以 EM78256 為例來說明呼叫不同 PAGE 子程序的方法。 例: 從PAGE 0調(diào)用PAGE 1中的子程序 ; PAGE 0, begin at 000h 049 add 0x11,a 050 mov a,@0x55 051 mov 0x05,a ;port5<-- 0x55 052 bs 0x03,5 ;select PAGE 1 053 call Lab2 ;PAGE jump 054 bc 0x03,5 ;restore 055 jbs 0x15,2 056 ; PAGE 1, begin at 400h 417 418 mov a,@0x3f 419 xor 0x12,a 450 Lab2 bc 0x06,3 451 mov a,0x05 45f ret 說明: 052: 將 R3 寄存器的位 5設(shè)為 "1" (選擇 PAGE 1)。 053: Lab2 將會被編譯為 "50",呼叫 PAGE 1 中 "Lab2" 子程序。 054: 將 R3 寄存器的位5 還原為 "0"。 注意: 此例中 "052" 和 "053" 是用來呼叫 PAGE 1 中 "Lab2" 的子程序,假如果沒有 "052" 這行指令,則程序?qū)⒑艚?"050" 的位址 (在 PAGE 0中),而非 "450" 的位址 (在 PAGE 1中),如此將發(fā)生錯(cuò)誤。 "BS","BC" 等指令會先有 "讀" 再 "寫" 的動(dòng)作,例如 "bc 0x06,3" 指令是將整個(gè) Port 6 (8 pin) 讀進(jìn) CPU,執(zhí)行位運(yùn)算后再寫至 Port 6 上。假如 Port 6 有一些 pin 是雙向 I/O pin (如 P65) 時(shí),假設(shè)當(dāng)執(zhí)行 "bc 0x06,3" 時(shí)P65 是輸入 pin,則 P65 pin 上的內(nèi)容會被讀入再寫至 Latch 上,覆蓋原先 Latch 上的內(nèi)容。因此只要 P65 一直是輸入 pin 將不會有問題,一旦 P65 切換為輸出,則 Latch 上的內(nèi)容將是不可預(yù)知的。 若仔細(xì)研究EM78系列八位微控器的I/O Port構(gòu)造,就可發(fā)現(xiàn)在做"讀"I/O Port的動(dòng)作時(shí)(如"mov a,0x06"),所讀入內(nèi)容有兩個(gè)路徑來源,一是I/O pin上的內(nèi)容,另一是輸出Latch上的內(nèi)容,而由I/O控制寄存器決定此讀入的路徑。 例如I/O pin設(shè)計(jì)為輸入pin時(shí)(對應(yīng)的I/O控制寄存器為"1"),對I/O Port做"讀"的動(dòng)作時(shí),是讀到pin上的內(nèi)容。若I/O pin設(shè)計(jì)為輸出pin時(shí)(對應(yīng)的I/O控制寄存器為"0"),對I/O Port做"讀"的動(dòng)作時(shí),是讀到輸出Latch上的內(nèi)容。 WDT是微控器內(nèi)部RC自振的計(jì)時(shí)器,其超時(shí)溢位(Time-out)的基本周期約18ms,WDT有與TCC共用的倍除器,使得超時(shí)溢位(Time-out)的最大周期可至約2.2sec。WDT計(jì)時(shí)的使能或禁止是可隨時(shí)由指令控制的(控制位在IOCE寄存器)。當(dāng)WDT使能時(shí),其超時(shí)溢位將使微控器發(fā)生RESET(或喚醒),"wdtc"指令是用來清除WDT,令WDT再從頭計(jì)時(shí),因此適當(dāng)?shù)氖褂?wdtc"指令,可使WDT不會發(fā)生RESET。當(dāng)WDT被禁止時(shí),WDT不會使微控器RESET或喚醒。要特別注意的是,Power-on之後WDT是使能的,如果該應(yīng)用中並沒有使用WDT,必須在程序的前頭用指令將WDT計(jì)時(shí)禁止。EM78156/256/456就是依上述所設(shè)計(jì)。 在EM78247/447/248/448/056/P156除了上述的設(shè)計(jì)外,另有一Code Option決定使能或禁止WDT,其功能如下: 1. 假如應(yīng)用中有使用WDT,WDT必須以Code Option使能,則在程序中隨時(shí)可以用指令使能或禁止WDT計(jì)時(shí)。注意:Power-on之後WDT是使能的。 2. 假如應(yīng)用中並沒有使用WDT,WDT可以以Code Option禁止,則WDT是永遠(yuǎn)被禁止的,如此可省去須在程序的前頭用指令將WDT計(jì)時(shí)禁止的麻煩。 用戶可以單獨(dú)設(shè)定任一支I/O腳為輸出模式(Output Mode),或是輸入模式(Input Mode)。只要將每個(gè)I/O的設(shè)定寫入累加器(A)中,再將累加器的內(nèi)容寫到I/O控制寄存器中,設(shè)定就算完成了。 例1:將PORT6設(shè)定為OUTPUT PORT。 PORT6 == 6 ;定義。 MOV A, @0X00 ;設(shè)定A = 0。 IOW PORT6, A ;將PORT6設(shè)定為輸出模式。 例2:將PORT6的低四位設(shè)成INPUT PORT;高四位設(shè)定為OUTPUT PORT。 PORT6 == 6 ;定義。 MOV A, @0X0F ;設(shè)定A= 0X0F,高四位為 IOW PORT6, A ;OUTPUT PORT,低四位為 ;INPUT PORT。 檢查寄存器的內(nèi)容有很多種方法,可以用AND的功能,或SUB的功能…等。在做完AND或SUB的功能之后,可以檢驗(yàn)狀態(tài)標(biāo)志(STATUS FLAG),然后寫一個(gè)判斷式,針對狀態(tài)標(biāo)志的結(jié)果, 處理個(gè)別的情形。 例:判斷寄存器0X20內(nèi)含值是否為0。 CHECK: MOV A, @0XFF ;設(shè)定A = 0XFF。 AND A, 0X20 ;寄存器0X20,和A中的值做and JBS 0X03, 2 ;若是寄存器0x20為0,則寄存 JMP CHECK ;器0X03的bit2位為1。 ;若是寄存器0X20不為零則產(chǎn)生循環(huán)。 1.FOR LOOP的設(shè)計(jì): 如果用戶想讓同一段程序執(zhí)行N次,用戶可以利用一個(gè)寄存器為計(jì)數(shù)器,在程序執(zhí)行前,先將計(jì)數(shù)寄存器設(shè)為N,然后每執(zhí)行一次,計(jì)數(shù)器就減一,再跳為原區(qū)段執(zhí)行,直到計(jì)數(shù)器被減至零。 例:設(shè)計(jì)一個(gè)FOR LOOP循環(huán),讓循環(huán)連續(xù)執(zhí)行10次。 MOV A, @0X0A ;設(shè)A = 0X0A。 MOV 0X10, A ;設(shè)定計(jì)數(shù)值。計(jì)數(shù)寄存器 LOOP: ;為0X10。 ; ; ; DJZ 0X10 ;遞減計(jì)數(shù)寄存器,若計(jì)數(shù) JMP LOOP ;值為0,則跳出循環(huán)。 2.IF…THEN… 程序設(shè)計(jì): IF…THEN…的說法就是,如果…就做…。用戶可以利用檢查兩個(gè)數(shù)值是否相等,例如”IF X = Y THEN GOTO ELSE” 的格式,來完成這種功能。 l 例:判斷兩個(gè)寄存器(0X20, 0X21)的數(shù)值是否相等,如果相等,就將標(biāo)志寄存器設(shè)為1。 BUFFER1 == 0X20 ;定義。 BUFFER2 == 0X21 FLAG == 0X22 MOV A, BUFFER ;將BUFFER1的值存入A中。 XOR A, BUFFER2 ;將A的值和BUFFER2的值做xor JBC 0X03, 2 ;IF BUFFER1 = BUFFER2 JMP FLAG_1 ;THEN JMP FLAG_0 ;ELSE FLAG_0: MOV A, @0 MOV FLAG, A ;設(shè)定FLAG為0。 JMP PROCESS FLAG_1: MOV A, @1 MOV FLAG, A ;設(shè)定FLAG為1。 JMP PROCESS PROCESS: 在一個(gè)沒有規(guī)則性的內(nèi)容轉(zhuǎn)換中,查表程序是相當(dāng)有用的,用戶可以使用查表程序很快速的得到相關(guān)內(nèi)容的轉(zhuǎn)換。 例:設(shè)計(jì)一個(gè)程序,將如下圖所示中的PORT5讀到的一個(gè)數(shù)值,將輸入內(nèi)容做轉(zhuǎn)換,然后輸出到PORT6的7段顯示器上。 上圖中開關(guān)關(guān)閉,I/O引腳可以得到一個(gè)低電位,若是開關(guān)開啟則I/O引腳可以得到一個(gè)高電位。 圖 5.2 數(shù)碼管八段說明 7段顯示器的接線圖如上,我們要編一個(gè)表做為讀入內(nèi)容以及輸出內(nèi)容的對映。 7段顯示器各腳位電位狀態(tài) | PORT6輸出 | PORT5輸入 | H | G | F | E | D | C | B | A | 16進(jìn)位數(shù)值 | 10進(jìn)位數(shù)值 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0X3F | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0X06 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0X5B | 2 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0X4F | 3 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0X66 | 4 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0X6D | 5 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0X7D | 6 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0X07 | 7 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0X7F | 8 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0X6F | 9 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 0X77 | 10 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0X7C | 11 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0X58 | 12 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0X5E | 13 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0X79 | 14 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0X71 | 15 |
程序清單如下: PC == 0X02 ;定義。 PORT5 == 5 PORT6 == 6 ORG 0X10 ;設(shè)定程序起始位址。 IOW PORT6 ;設(shè)定PORT6為Output口。 MOV A, @0XFF IOW PORT5 ;設(shè)定PORT5為Input口。 JMP START ;跳轉(zhuǎn)到主程序中。 TABLE:;輸入及輸出對映表。 ADD PC, A RETL @0X3F RETL @0X06 RETL @0X5B RETL @0X4F RETL @0X66 RETL @0X6D RETL @0X7D RETL @0X07 RETL @0X7F RETL @0X6F RETL @0X77 RETL @0X7C RETL @0X58 RETL @0X5E RETL @0X79 RETL @0X71 START: MOV A, PORT5 AND A, @0X0F CALL TABLE MOV PORT6, A JMP START 在EM78X56系列的IC中有三種中斷信號,分別是: TCC溢位中斷。 PORT6 Change 中斷。 外部信號中斷。 在說明中斷使用方式之前,用戶要了解中斷寄存器,及與中斷息息相關(guān)的控制寄存器( Control Register),另外在芯片中預(yù)除器( Prescalar )的使用方法,用戶也需要住意。 中斷信號顯示寄存器0X0F各位安排如下: | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0 | 中斷信號 | - | - | - | - | - | 外部中斷標(biāo)志 | PORT6 Change | TCC 溢位標(biāo)志。 |
寄存器0X0F使用到的有BIT0 ~ BIT2。BIT0在TCC計(jì)時(shí)器計(jì)數(shù)溢位時(shí)就會被設(shè)定,用戶可以根據(jù)0X0F的BIT0被設(shè)定而判定TCC計(jì)數(shù)溢位。跟TCC配合的還有另一個(gè)寄存器---控制寄存器(Control Register,簡稱CONT)?刂萍拇嫫0X0F各位安排如下: | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0 | 控制信號 | - | INT | TS | TE | PAB | PSR2 | PSR1 | PSR0 |
各位的代表意義如下: □ PSR2 ~ PSR0:TCC/WDT 預(yù)除器設(shè)定。 PSR2 | PSR1 | PSR0 | TCC 比例 | WDT 比例 | 0 | 0 | 0 | 1:2 | 1:1 | 0 | 0 | 1 | 1:4 | 1:2 | 0 | 1 | 0 | 1:8 | 1:4 | 0 | 1 | 1 | 1:16 | 1:8 | 1 | 0 | 0 | 1:32 | 1:16 | 1 | 0 | 1 | 1:64 | 1:32 | 1 | 1 | 0 | 1:128 | 1:64 | 1 | 1 | 1 | 1:256 | 1:128 |
FIGURE3.5 PS0 ~ PS2的設(shè)定值與預(yù)除器和TCC及WDT的比例關(guān)係。 □ Bit3預(yù)除器配置: 0:TCC 1:WDT □ Bit4 TCC遞增時(shí)機(jī): 0:外部信號,觸發(fā)邊沿為正沿觸發(fā)。 1:外部信號,觸發(fā)邊沿為負(fù)沿觸發(fā)。 □ Bit5 TCC信號來源: 0:內(nèi)部指令周期觸發(fā)。 1:外部引腳(第三腳)觸發(fā)。 □ Bit6 INT使能標(biāo)志: 0:禁止所有中斷產(chǎn)生。 1:使能中斷信號。 □ Bit7 無使用。 三種中斷產(chǎn)生都有其先前的設(shè)定值,接下來會以示例說明。 l 例:寫一個(gè)程序,將寄存器0X20當(dāng)做計(jì)數(shù)器,每當(dāng)TCC中斷產(chǎn)生,就自動(dòng)加1。 MOV A, @0X0 ;設(shè)定 A = 0。 IOW 0X0E ;關(guān)閉Watch Dog。 ORG 6 ;設(shè)定接下來的程序位址。 CLR 0X20 ;清除寄存器0X20。 JMP TCC_PRO ;跳轉(zhuǎn)到TCC_PRO。 INT_PRO: DISI ;關(guān)閉各項(xiàng)中斷功能。 CLR 0X0F ;清除中斷寄存器。 INC 0X20 ;計(jì)數(shù)器加1。 RETI ;返回主程序,並使能中斷。 TCC_PRO: CLR 0X0F ;清除中斷寄存器。 MOV A, @0X01 ;設(shè)定 A = 1。 IOW 0X0F ;使能TCC溢位中斷產(chǎn)生。 MOV A, 0X40 ;設(shè)定 A = 0X40。 CONTW ;將A的值寫入控制寄存器。 ENI ;使能中斷。 TCC_WAIT: NOP ;等待TCC計(jì)數(shù)器計(jì)數(shù)溢位。 NOP ;等待TCC計(jì)數(shù)器計(jì)數(shù)溢位。 JMP TCC_WAIT ;等待TCC計(jì)數(shù)器計(jì)數(shù)溢位。 TCC中斷產(chǎn)生有幾個(gè)設(shè)計(jì)的重點(diǎn): 1. 關(guān)閉看門狗計(jì)時(shí)器(Watch Dog Timer)。 2. 設(shè)定控制寄存器(包括預(yù)除器、TCC信號來源、觸發(fā)時(shí)機(jī)…)。 3. 使能中斷(下ENI指令)。 4. 使能TCC中斷(設(shè)定中斷控制寄存器的bit0為1)。 5. 中斷服務(wù)位址為0X08。 6. 進(jìn)入中斷服務(wù)程序首先要將中斷禁止,否則會產(chǎn)生重復(fù)中斷。 7. 中斷寄存器0X0F,在進(jìn)入中斷服務(wù)程序時(shí)可以提供用戶判斷為何種中斷,判斷完成之后用戶必須自行清除。 8. 由中斷服務(wù)程序返回主程序應(yīng)使用指令RETI。 l 例:寫一個(gè)程序,將寄存器0X20當(dāng)做計(jì)數(shù)器,每當(dāng)PORT6 Change中斷產(chǎn)生,就自動(dòng)加1。 PORT6 == 6 ;定義。 DISI ;中斷禁止。 ORG 6 ;設(shè)定下一個(gè)位址為0X06。 CLR 0X20 ;清除計(jì)數(shù)寄存器。 JMP PORT6_CH ;跳轉(zhuǎn)到主程序。 DISI INT_PRO: ;0X08為中斷服務(wù)程序起始。 NOP CLR 0X0F ;清除中斷標(biāo)志寄存器。 INC 0X20 ;計(jì)數(shù)器遞增。 MOV PORT6, PORT6 ;將PORT6的值存入正反器。 RETI ;回主程序。 PORT6_CH: CLR 0X0F ;清除中斷標(biāo)志寄存器。 MOV A, @0XFF ;設(shè)定 A = 0XFF。 IOW PORT6 ;將PORT6設(shè)成輸入口。 MOV PORT6, PORT6 ;將PORT6的值存入正反器。 ENI ;使能中斷。 MOV A, @0X02 ;設(shè)定 A = 0X02。 IOW 0X0F ;使能PORT6 Change中 WAIT_INT: WDTC ;清除Watch Dog Timer。 NOP ;等待PORT6 Change。 NOP ;等待PORT6 Change。 JMP WAIT_INT ;循環(huán)。 使用PORT6 Change中斷有下列幾個(gè)步驟。 1. 關(guān)閉看門狗計(jì)時(shí)器(Watch Dog Timer),若看門狗計(jì)時(shí)器未關(guān)閉,用戶要定時(shí)下WDTC的指令。 2. 清除中斷寄存器。 3. 設(shè)定PORT6為輸出口。 4. 將PORT6的值存入觸發(fā)器中(這很重要)。 5. 使能中斷(下ENI的指令)。 6. 使能PORT6 Change中斷(設(shè)定中斷控制寄存器的bit1為1)。 7. 中斷服務(wù)程序的啟始位址在0X08。 8. 進(jìn)入中斷服務(wù)程序首先要將中斷禁止,否則會產(chǎn)生嵌套中斷。 9. 中斷寄存器0X0F,在進(jìn)入中斷服務(wù)程序時(shí)可以提供用戶判斷為何種中斷,判斷完成之后用戶必須自行清除。 10. 由中斷服務(wù)程序返回主程序應(yīng)使用指令RETI。 l 例:寫一個(gè)程序,將寄存器0X20當(dāng)做計(jì)數(shù)器,每當(dāng)外部中斷產(chǎn)生,就自動(dòng)加1。 所謂的外部中斷就是利用IC外部引腳,針對單片機(jī)外部的信號做為信號源來產(chǎn)生中斷。EM78系列的外部中斷引腳是第4腳,是和PORT6位0合用,所以再使用前要先設(shè)定PORT6 , BIT0是要單純用做I/O引腳,或是中斷輸入引腳。 ORG 6 ;設(shè)定啟始位址為0X06。 CLR 0X20 ;清除計(jì)數(shù)器。 JMP EXT_PRO ;跳轉(zhuǎn)到主程序。 INT_EXT: DISI ;中斷禁止。 CLR 0X0F ;清除中斷標(biāo)志。 INC 0X20 ;遞增計(jì)數(shù)寄存器。 RETI ;返回主程序。 EXT_PRO: CLR 0X0F ;清除中斷標(biāo)志。 MOV A, @0X04 ;A = 0X04。 IOW 0X0F ;使能外部中斷信號產(chǎn)生。 MOV A, @0X40 ;A = 0X40。 IOW 0X0E ;設(shè)定PORT6, BIT0為中斷輸入腳 ENI ;返回主程序。 EXT_WAIT: NOP ;等待外部中斷輸入。 NOP ;等待外部中斷輸入。 JMP EX_WAIT ;循環(huán)。 外部中斷顯然比較容易了解。所需注意的項(xiàng)目有: 1. 禁止中斷。 2. 設(shè)定中斷服務(wù)程序的地址在0X08。 3. 清除中斷標(biāo)志寄存器。 4. 使能外部中斷信號產(chǎn)生(設(shè)定中斷控制寄存器為0X04)。 5. 將PORT6, BIT0設(shè)定成外部中斷引腳(設(shè)定控制寄存器0X0E, BIT6為1)。 6. 使能中斷信號(ENI)。 7. 用戶在進(jìn)入中斷服務(wù)程序(0X08)時(shí),首先要記得禁止中斷(DISI)。 8. 可以由中斷標(biāo)志寄存器判斷中段的信號為何產(chǎn)生,判斷完之后應(yīng)自行清除中斷標(biāo)志。 9. 返回主程序時(shí)用指令RETI。 以上三支中斷程序的寫法都是利用無窮循環(huán),所以用戶想要看到結(jié)果只有結(jié)束程序,然后查看計(jì)數(shù)寄存器(0X20)的計(jì)數(shù)狀況。 在許多程序設(shè)計(jì)的場合,我們時(shí)常會利用到時(shí)間延遲子程序,接下來就介紹一個(gè)可以控制延遲時(shí)間的延遲子程序。 開下面是利用發(fā)工具E8-ICE來演示的一個(gè)精確的控制延遲時(shí)間的程序,選擇使用石英振蕩器,可以精確的算準(zhǔn)延遲時(shí)間,時(shí)間可以到nanosecond(十億分之一秒),很神奇。 LP_CNT0 == 0X20 ;定義。 LP_CNT1 == 0X21 MOV A, @2 ;A = 2。 MOV LP_CNT0, A ;設(shè)定延遲寄存器0(LP_CNT0)=2 CALL P0_DLY ;呼叫時(shí)間延遲子程序。 P0_DLY: NOP ;調(diào)節(jié)延遲時(shí)間。 MOV A, @200 ;設(shè)定 A = 200。 MOV LP_CNT1, A ;設(shè)定寄存器LP_CNT1 = 200。 P0_LP: NOP ;調(diào)節(jié)延遲時(shí)間。 NOP ;調(diào)節(jié)延遲時(shí)間。 NOP ;調(diào)節(jié)延遲時(shí)間。 DJZ LP_CNT1 ;遞減LP_CNT1,為0就跳過下一行 JMP P0_LP ;循環(huán)。 DJZ LP_CNT0 ;遞減LP_CNT0,為0就跳過下一行 JMP P0_DLY ;循環(huán)。 RET ;返回主程序。 假設(shè)用戶所使用的開發(fā)工具是E8-ICE,而且所采用的振蕩器為石英振蕩(4M Hz),並選擇指令執(zhí)行周期為1 Cycle, 2 Clock。這時(shí)每執(zhí)行一個(gè)指令的時(shí)間為0.5 uS. 用戶可以看出在程序中用了兩個(gè)寄存器來計(jì)數(shù)(LP_CNT0、LPCNT1),另外也使用了兩個(gè)循環(huán)(P0_DLY、P0_LP),其中在P0_LP中有5個(gè)指令,所以在P0_LP這個(gè)循環(huán)中,執(zhí)行了有1000個(gè)指令。 5X 200= 1000 P0_LP循環(huán)總共執(zhí)行指令數(shù)目。 5 + 1000 = 1005 P0_DLY循環(huán)總共執(zhí)行指令數(shù)目。 1005 X 2 = 2010 2010 + 1 + 1 = 2012 延遲程序總共執(zhí)行指令數(shù)目 在整個(gè)P0_DLY循環(huán)中就有2012個(gè)指令,每個(gè)指令的執(zhí)行時(shí)間為0.5 us。 2012 (instructions) x 0.5 (us/instruction) = 1.006 ms 所以用戶可以精確的計(jì)算出延遲的時(shí)間,用戶可以在LP_CNT0設(shè)定不同的值,如此可以有各種不同的延遲時(shí)間。 l 例:設(shè)計(jì)一個(gè)延遲時(shí)間為2ms的程序。 只要在上述程序中在呼叫P0_DEL延遲子程序之前,將LP_CNT0設(shè)成4就可以了。 MOV A, @4 MOV LP_CNT0, A CALL P0_DLY 其余不變。 1005 X 4 = 4020。 4020 + 1 + 1 = 4022。 4022 (instructions) X 0.5 (us) = 2.011 ms PORT5輸出動(dòng)作的控制,而且外部接有一推動(dòng)STEP MOTOR的電路。寫一程序驅(qū)動(dòng)STEP MOTOR。 在寫程序之前,先介紹STEP MOTOR的動(dòng)作原理。 圖5.3 PORT5步進(jìn)馬達(dá)控制圖。 P50 0 0 1 1 P51 1 1 0 0 P52 1 0 0 1 P53 0 1 1 0 圖5.4 PORT5步進(jìn)馬達(dá)控制時(shí)序圖。 圖5.3中可以看出,PORT5接到STEP MOTOR的對應(yīng)引腳,圖5.4可以看出PORT5應(yīng)該送出的信號。圖5.3中P50和P51的輸出必須反相,P52和P53的輸出必須反相,而P50和P52必須有相位差,假設(shè)P50和P52的相位差為90度,于是導(dǎo)出圖5.4 的時(shí)序圖。 圖5.4的時(shí)序圖中,可以看出有四個(gè)相位會一直循環(huán),分別是: | Phase 0 | Phase 1 | Phase 2 | Phase 3 | P50 | 0 | 0 | 1 | 1 | P51 | 1 | 1 | 0 | 0 | P52 | 1 | 0 | 0 | 1 | P53 | 0 | 1 | 1 | 0 | Value | 0x06 | 0x0A | 0x09 | 0x05 |
上表中有四個(gè)基本相位數(shù)值。所以只要不停的送出這四個(gè)相位,STEP MOTOR就會不停的旋轉(zhuǎn),送出的速度快,STEP MOTOR的轉(zhuǎn)速就快,但是要在STEP MOTOR的旋轉(zhuǎn)極限之內(nèi)。 PORT5 == 5 ; 定義 ; 程序開始 MOV A, @0X0 ;將A設(shè)成0X0。 IOW PORT5 ;設(shè)定PORT5為輸出口。 AGAIN: MOV A, @0X06 ;設(shè)定A的值為0X06。 MOV PORT5, A ;將A的值輸出到PORT5。 MOV A, @0X0A ;設(shè)定A的值為0X0A。 MOV PORT5, A MOV A, @0X09 ;設(shè)定A = 0X09。 MOV PORT5, A MOV A, @0X05 ;設(shè)定A = 0X05。 MOV PORT5, A ;設(shè)定PORT5 = 5。 JMP AGAIN ;循環(huán)。 PORT6輸出動(dòng)作的控制,而且外部接有一推動(dòng)8個(gè)七段顯示器的電路。編寫一程序在8個(gè)七段顯示器上輪流顯示1,2,3,4,5,6,7,8。 下圖為控制電路的方塊圖。  由PORT6單獨(dú)控制8個(gè)七段顯示器,利用時(shí)間分割(time slice)的顯示方式,就可以同時(shí)讓多個(gè)七段顯示器同時(shí)顯示。上圖可以看出,若是要讓第一個(gè)七段顯示器顯示一個(gè)0的值,在PORT6輸出的內(nèi)容值為0X00,前四個(gè)位控制要顯示的七段顯示器,后四個(gè)位控制顯示的數(shù)字。所以要選第0個(gè)七段顯示器,前四個(gè)位要為0;若要顯示的值為0,后四個(gè)位的值也是為0。 PORT6 == 6 ;定義PORT6 MOV A, @0 ;將A設(shè)成0。 IOW PORT6 ;設(shè)定PORT6為OUTPUT口 AGAIN: MOV A, @0X01 ;將A設(shè)成0X01 MOV PORT6, A ;輸出內(nèi)容到PORT6。 MOV A, @0X12 ;將A設(shè)成0X12。 MOV PORT6, A ;輸出內(nèi)容到PORT6。 MOV A, @0X23 MOV PORT6, A ;輸出內(nèi)容到PORT6。 MOV A, @0X34 MOV PORT6, A ;輸出內(nèi)容到PORT6。 MOV A, @0X45 MOV PORT6, A ;輸出內(nèi)容到PORT6。 MOV A, @0X56 MOV PORT6, A ;輸出內(nèi)容到PORT6。 MOV A, @0X67 MOV PORT6, A ;輸出內(nèi)容到PORT6。 MOV A, @0X78 MOV PORT6, A ;輸出內(nèi)容到PORT6。 JMP AGAIN PORT6的輸出接有一個(gè)數(shù)模轉(zhuǎn)換器(D/A convert)。寫一程序產(chǎn)生一個(gè)鋸此波。 本例的D/A Convert所采用的方式為R – 2R的方式,所使用的電阻為20K的同一品牌的排阻。因PORT6有8個(gè)位,所以在0V-VCC一共有256個(gè)階層。 PORT6 == 6;定義。 MOV A, @0 ;將A設(shè)成0。 IOW PORT6 ;將PORT6設(shè)成OUTPUT口。 MOV PORT6, A ;PORT6輸出內(nèi)容為0。 AGAIN: INC PORT6 ;PORT6的值依序遞增1。 JMP AGAIN |