版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第5章匯編語言程序設(shè)計
5.1STVD開發(fā)環(huán)境與STM8匯編語言程序結(jié)構(gòu)5.2STM8匯編程序結(jié)構(gòu)5.3程序基本結(jié)構(gòu)5.4并行多任務(wù)程序結(jié)構(gòu)及實現(xiàn)5.5程序仿真與調(diào)試 5.1STVD開發(fā)環(huán)境與STM8匯編語言程序結(jié)構(gòu)5.1.1STVD開發(fā)環(huán)境中創(chuàng)建工作站文件工作站文件的創(chuàng)建過程如下:
(1)執(zhí)行“File”菜單下的“NewWorkspace…”,選擇“createworkspaceandproject”,創(chuàng)建新的ST工作站文件(擴(kuò)展名為?.STW)。
(2)在圖5-1所示的“Workspace”文本框內(nèi)指定工作站文件的存放目錄路徑;在“Workspacefilename”文本框內(nèi)輸入工作站文件名(不用擴(kuò)展名)。圖5-1創(chuàng)建工作站文件
(3)在圖5-2所示的“Projectfilename”文本框內(nèi)輸入“項目文件名”;根據(jù)選定的開發(fā)語言(ST匯編還是某特定的C語言),在“Toolchain”文本框內(nèi)選定相應(yīng)的連接程序,如“STAssemblerLinker”。
(4)在“MCU”窗口內(nèi)選擇相應(yīng)的MCU型號,如STM8S208MB等,單擊“OK”按鈕后,就可以觀察到如圖5-3所示的文件夾。5.1.2STVD自動創(chuàng)建項目文件內(nèi)容利用STVD創(chuàng)建STM8S匯編項目文件時,在“SourceFiles”文件夾下自動生成了mapping.asm源文件(段定義匯編文件)、main.asm文件(用戶應(yīng)用程序主模塊框架匯編文件);在“IncludeFiles”包含文件夾內(nèi)自動生成了mapping.inc文件(段定義匯編文件中涉及的符號常量定義說明文件)。其中,mapping.asm、mapping.inc的內(nèi)容簡單明了,容易理解。下面主要分析main.asm文件組成和關(guān)鍵指令功能。
stm8/ ;?[注1]指定CPU類型匯編格式的偽指令,不能缺省且頂格書寫
#include"mapping.inc" ;?[注2]包含文件說明偽指令,凡指令、偽指令行至少退一個以上字符位
segment'rom' ;在rom段內(nèi)存放指令碼main.l ;?[注3]主程序開始標(biāo)號,凡標(biāo)號一律頂格書寫
;?initializeSP
ldwX,#stack_end ;?[注4]初始化堆棧指針SPldwSP,X#ifdefRAM0 ;?[注5]RAM存儲區(qū)00H~FFH單元清0;?clearRAM0ram0_start.bEQU$ram0_segment_startram0_end.bEQU$ram0_segment_endldwX,#ram0_startclear_ram0.l
clr(X) incwX cpwX,#ram0_end
jruleclear_ram0 #endif #ifdefRAM1 ;?[注6]RAM存儲區(qū)0100H及以上單元清0 ;?clearRAM1ram1_start.wEQU$ram1_segment_startram1_end.wEQU$ram1_segment_end ldwX,#ram1_startclear_ram1.l clr(X) incwX cpwX,#ram1_end jruleclear_ram1
#endif ;
clearstack ;?[注7]堆棧區(qū)單元清0stack_start.wEQU$stack_segment_startstack_end.wEQU$stack_segment_end ldwX,#stack_startclear_stack.l clr(X) incwX cpwX,#stack_end jruleclear_stackinfinite_loop.l ;虛擬的主程序
jrainfinite_loop interruptNonHandledInterrupt ;?[注8]中斷服務(wù)程序定義偽指令NonHandledInterrupt.l iret;中斷入口地址表
segment'vectit' dc.l{$82000000+main} ;?reset[注9]中斷入口地址表
dc.l{$82000000+NonHandledInterrupt} ;?trap dc.l{$82000000+NonHandledInterrupt} ;?irq0 dc.l{$82000000+NonHandledInterrupt} ;?irq1 dc.l{$82000000+NonHandledInterrupt} ;?irq2 dc.l{$82000000+NonHandledInterrupt} ;?irq3 dc.l{$82000000+NonHandledInterrupt} ;?irq4 dc.l{$82000000+NonHandledInterrupt} ;?irq5 dc.l{$82000000+NonHandledInterrupt} ;?irq6 dc.l{$82000000+NonHandledInterrupt} ;?irq7 dc.l{$82000000+NonHandledInterrupt} ;?irq8
dc.l{$82000000+NonHandledInterrupt} ;?irq9dc.l{$82000000+NonHandledInterrupt} ;?irq10dc.l{$82000000+NonHandledInterrupt} ;?irq11dc.l{$82000000+NonHandledInterrupt} ;?irq12dc.l{$82000000+NonHandledInterrupt} ;?irq13dc.l{$82000000+NonHandledInterrupt} ;?irq14dc.l{$82000000+NonHandledInterrupt} ;?irq15dc.l{$82000000+NonHandledInterrupt} ;?irq16dc.l{$82000000+NonHandledInterrupt} ;?irq17dc.l{$82000000+NonHandledInterrupt} ;?irq18dc.l{$82000000+NonHandledInterrupt} ;?irq19dc.l{$82000000+NonHandledInterrupt} ;?irq20dc.l{$82000000+NonHandledInterrupt} ;?irq21dc.l{$82000000+NonHandledInterrupt} ;?irq22dc.l{$82000000+NonHandledInterrupt} ;?irq23dc.l{$82000000+NonHandledInterrupt} ;?irq24dc.l{$82000000+NonHandledInterrupt} ;?irq25dc.l{$82000000+NonHandledInterrupt} ;?irq26dc.l{$82000000+NonHandledInterrupt} ;?irq27dc.l{$82000000+NonHandledInterrupt} ;?irq28dc.l{$82000000+NonHandledInterrupt} ;?irq29end ;匯編程序結(jié)束偽指令,不能缺省
[注1]在ST匯編中,匯編程序源文件開始處必須用“st7/(或ST7/)”或“stm8(或STM8/)”偽指令指定隨后的指令、偽指令按哪一種類MCU芯片指令格式進(jìn)行匯編,不可缺省且必須頂格書寫。
[注2]由于自動創(chuàng)建的段定義文件使用了符號常量作為段起始地址、終了地址,因此STVD自動創(chuàng)建了mapping.inc文件。該文件對段定義中涉及的符號常量進(jìn)行了定義,插入了#includemapping.inc偽指令。
[注3]在ROM段中開始定義了一個main.l標(biāo)號,標(biāo)號必須頂格書寫。這樣,只要在中斷入口地址表中用“dc.l{$82000000+main}”偽指令填充復(fù)位中斷向量存儲單元,就可以保證將復(fù)位中斷邏輯指向復(fù)位后要執(zhí)行的第一條指令所在存儲單元的地址,如[注9]所示。在STM8S中,復(fù)位后將從復(fù)位中斷邏輯指示的地址單元(可以是ROM、EEPROM,甚至是RAM)取出并執(zhí)行第一條指令。第一條指令在ROM存儲區(qū)中的存放位置并沒有限制,將第一條指令所在存儲單元的地址填入復(fù)位中斷入口地址表中。
[注4]復(fù)位后初始化堆棧指針。盡管復(fù)位后堆棧指針SP也指向RAM的最后一個單元,但復(fù)位后,用指令初始化有關(guān)寄存器是一個良好的習(xí)慣,避免了用缺省值造成的不確定性。
[注5]~[注7]分別清除了RAM存儲區(qū)、堆棧區(qū)。如果復(fù)位后沒有保留RAM單元信息的必要,則復(fù)位后對RAM單元進(jìn)行集中清0非常必要。
[注8]在ST匯編中,必須通過“interrupt”偽指令定義相應(yīng)中斷服務(wù)程序入口地址標(biāo)號,然后在中斷入口地址表中填入對應(yīng)的中斷服務(wù)程序入口地址標(biāo)號。
[注9]中斷入口地址表。例如,PortA外部中斷EXTI0的中斷號為IRQ03,因此PortA口外中斷服務(wù)程序結(jié)構(gòu)如下:
InterruptEXTI0
EXTI0.L ;外中斷EXTI0服務(wù)程序指令系列
IRET然后將中斷向量表內(nèi)的IRQ03改為
dc.l{$82000000+NonHandledInterrupt} ;
irq2,未定義中斷入口地址表依然保留
dc.l{$82000000+EXTI0}
;?irq3,即PortA口外中斷入口地址表
dc.l{$82000000+NonHandledInterrupt} ;?irq4可見在STM8S中,中斷服務(wù)程序入口地址不固定,只需將對應(yīng)中斷號服務(wù)程序第一條指令所在存儲單元地址,實際上是把82000000H與中斷服務(wù)程序第一條指令前標(biāo)號相加,填入對應(yīng)中斷向量表內(nèi)。5.1.3完善STVD自動創(chuàng)建的項目文件內(nèi)容由STVD創(chuàng)建的項目匯編文件尚不十分完善,沒有把相應(yīng)型號MCU的外設(shè)寄存器定義文件加入到“SourceFiles”(源文件夾)中,在用戶程序中尚不能直接引用外設(shè)寄存器名,如“LDPA_DDR,A”等;也沒有定義外設(shè)控制寄存器與外設(shè)狀態(tài)寄存器中的位,如“FLASH_IAPSR”的DUL位。為此須按下列步驟完善STVD創(chuàng)建的項目文件。
1.加入相應(yīng)MCU的外設(shè)寄存器定義匯編文件(.asm)及其外部標(biāo)號說明文件(.inc)將光標(biāo)移到“SourceFiles”源程序文件夾上,單擊右鍵,選擇“AddFilestoForlder…”將ST_toolset\asm\include文件夾中對應(yīng)型號芯片的外設(shè)寄存器定義匯編文件,如STM8S208MB.asm,加入到源程序文件中。將光標(biāo)移到“IncludeFiles”包含文件夾上,單擊右鍵,選擇“AddFilestoForlder…”將ST_toolset\asm\include文件夾中對應(yīng)芯片的外設(shè)端口寄存器標(biāo)號說明文件,如STM8S208MB.inc,加入到該文件夾中。
2.在main.asm文件中插入相應(yīng)MCU的.inc文件在main.asm文件中插入#include
"×××××××.inc",其中×××××××代表芯片型號,即上一步添加的包含文件名,以便能在應(yīng)用程序模塊中直接引用外設(shè)寄存器名,如PA_DDR、PA_CR1、FLASH_IAPSR等。到此基本完成了匯編環(huán)境的創(chuàng)建過程,可以在main.asm文件內(nèi)插入用戶指令系列,并進(jìn)行編譯、模擬仿真、聯(lián)機(jī)調(diào)試等操作。
3.在main.asm文件頭插入通用變量定義偽指令為便于模塊化應(yīng)用程序的編寫、調(diào)試,可將00H~3FH之間的RAM存儲單元劃分為四個區(qū),其中,00H~0FH作為主程序通用變量區(qū),10H~1FH作為優(yōu)先級為1的中斷服務(wù)程序的變量區(qū),20H~2FH作為優(yōu)先級為2的中斷服務(wù)程序的變量區(qū),30H~3FH作為優(yōu)先級為3的中斷服務(wù)程序的變量區(qū);分別用R00~R3F變量名對這64字節(jié)RAM單元進(jìn)行命名,具體如下: segment'ram0' BYTES ;?ram0段內(nèi)標(biāo)號為字節(jié)標(biāo)號。如果不用BYTES偽指令或后綴.B指定為字
;節(jié)標(biāo)號,將默認(rèn)為字標(biāo)號,采用16位地址格式;?00H~0FH單元定義為字節(jié)變量,供主程序使用.R00ds.b1 ;最好定義為公共變量,即用前綴“.”進(jìn)行聲明.R01ds.b1.R0Fds.b1;?10H~1FH單元定義為字節(jié)變量,供優(yōu)先級1中斷服務(wù)程序使用.R10ds.b1.R11ds.b1.R1Fds.b1;?20H~2FH單元定義為字節(jié)變量,供優(yōu)先級2中斷服務(wù)程序使用.R20ds.b1.R21ds.b1.R2Fds.b1;?30H~3FH單元定義為字節(jié)變量,供優(yōu)先級3中斷服務(wù)程序使用.R30ds.b1.R31ds.b1.R3Fds.b1
segment'ram1'WORDS ;?ram1段后定義的標(biāo)號為字標(biāo)號。當(dāng)在ram0段中,把變量標(biāo)號定義為bytes時,
;該語句不能少在模塊化程序結(jié)構(gòu)中,最好將R00~R3F公共變量定義偽指令放在一個特定的源文件中,如User_register.asm,同時創(chuàng)建相應(yīng)外部變量說明文件,如User_register.inc。然后分別添加到“SourceFiles”、“IncludeFiles”文件夾內(nèi),供不同的模塊引用。這兩個文件的內(nèi)容如下:
;?User_register.asm文件內(nèi)容:stm8/
;用戶定義公共變量
segment'ram0'
;?00H~0FH單元定義為字節(jié)變量(供主程序使用)
.R00.Bds.b1
.R01.Bds.b1
.R02.Bds.b1;省略R03~R0F變量定義偽指令行;?10H~1FH單元定義為字節(jié)變量,供優(yōu)先級為1中斷服務(wù)程序使用.R10.Bds.b1.R11.Bds.b1.R12.Bds.b1;省略R13~R1F變量定義偽指令行;?20H~2FH單元定義為字節(jié)變量,供優(yōu)先級為2中斷服務(wù)程序使用.R20.Bds.b1.R21.Bds.b1.R22.Bds.b1;省略R23~R2F變量定義偽指令行;?30H~3FH單元定義為字節(jié)變量,供優(yōu)先級為3中斷服務(wù)程序使用.R30.Bds.b1.R31.Bds.b1.R32.Bds.b1;省略R33~R3F變量定義偽指令行BYTESend;?User_register.inc文件內(nèi)容:;用戶定義公共變量屬性說明;?00H~0FH單元定義為字節(jié)變量,供主程序使用
EXTERNR00.B ;用戶定義的變量
EXTERNR01.B ;用戶定義的變量
EXTERNR02.B ;用戶定義的變量;省略R03~R0F變量定義屬性說明偽指令行
EXTERNR10.B ;用戶定義的變量
EXTERNR11.B ;用戶定義的變量
EXTERNR12.B ;用戶定義的變量
;省略R13~R1F變量定義屬性說明偽指令行
EXTERNR20.B ;用戶定義的變量
EXTERNR21.B ;用戶定義的變量
EXTERNR22.B ;用戶定義的變量;省略R23~R2F變量定義屬性說明偽指令行
EXTERNR30.B ;用戶定義的變量
EXTERNR31.B ;用戶定義的變量
EXTERNR32.B ;用戶定義的變量;省略R33~R3F變量定義屬性說明偽指令行在具體應(yīng)用程序中,可根據(jù)需要靈活裁剪,如某應(yīng)用系統(tǒng)的中斷源只有兩個優(yōu)先級,則無須保留30H~3FH單元作為中斷優(yōu)先級3的通用變量區(qū)。需要注意的是:非屏蔽中斷TRAP、頂級中斷TLI(PD7引腳外中斷)可中斷優(yōu)先級為3的可屏蔽中斷,這兩類中斷服務(wù)程序不宜共用R30~R3F變量,否則可能出現(xiàn)資源沖突現(xiàn)象。
4.更換匯編語言數(shù)制表示方式如果程序員熟悉Intel格式匯編語言數(shù)制表示方式,則可按下列步驟改造STVD自動創(chuàng)建的main.asm文件:
(1)在虛擬主程序段前插入“Intel”偽指令。
(2)在segment'vectit'(中斷向量段)前插入“Motorola”偽指令;在segment'vectit'(中斷向量段)后插入“Intel”偽指令。當(dāng)然也可以將堆棧段內(nèi)中斷入口地址表常數(shù)中全部的“$82000000”修改為“82000000H”,但遠(yuǎn)不如直接插入“Motorola”、“Intel”等偽指令方便。
5.創(chuàng)建外設(shè)寄存器位定義說明文件(.inc)創(chuàng)建外設(shè)寄存器位定義說明文件不是必需的,只是為了增加源程序的可讀性。未用?#Define偽指令定義外設(shè)寄存器位前,ST匯編語言源程序中的位操作指令只能采用“寄存器名,#位編號”形式作為位操作數(shù)。例如:
BTJTFLASH_IAPSR,#3,EEPROM_Write_Next1 ;DUL(EEPROM寫保護(hù)標(biāo)志位)為1,則跳轉(zhuǎn)該指令如果不加注釋,則指令的可讀性很差,需要查閱用戶指南才能確定FLASH_IAPSR[3]位是DUL標(biāo)志。此外,當(dāng)程序中多處出現(xiàn)“FLASH_IAPSR,#3”時,容易出錯。例如,將“#3”誤寫成“#2”,則編譯時不給出任何提示信息。為此最好創(chuàng)建一個通用的外設(shè)寄存器位定義說明文件(periph_bit_define.INC),以便在程序中用“寄存器名_位名”形式作為位操作數(shù),以提高源程序的可讀性。該文件格式如下:;------FLASH_IAPSR寄存器位定義------; 位名稱 所在位編號 讀寫特性說明#defineFLASH_IAPSR_HVOFF FLASH_IAPSR,#6 ;r#defineFLASH_IAPSR_DUL FLASH_IAPSR,#3 ;rc_w0#defineFLASH_IAPSR_EOP FLASH_IAPSR,#2 ;rc_r#defineFLASH_IAPSR_PUL FLASH_IAPSR,#1 ;rc_w0#defineFLASH_IAPSR_WR_PG_DIS FLASH_IAPSR,#0 ;rc_r將periph_bit_define.inc文件添加到IncludeFiles文件夾內(nèi),并在應(yīng)用程序文件頭部分插入?#include“periph_bit_define.inc”?偽指令,如圖5-4所示。圖5-4插入并引用外設(shè)寄存器位定義名為防止編譯時聯(lián)接程序找不到指定的文件,一個簡單的辦法是將User_register.asm、User_register.inc、periph_bit_define.inc,甚至相應(yīng)型號MCU外設(shè)寄存器定義文件,如STM8S207R8.asm、STM8S207R8.inc等,復(fù)制到指定工作站目錄下,然后再分類逐一添加到SourceFiles、IncludeFiles文件夾內(nèi)。這樣,在匯編語言源程序中就可以直接使用位定義名代替“寄存器名,#位編號”形式位操作數(shù),原因是“BTJTFLASH_IAPSR_DUL,EEPROM_Write_Next1”與“BTJTFLASH_IAPSR,#3,EEPROM_Write_Next1”等效。顯然,用寄存器位定義名后提高了源程序的可讀性,且只要保證位定義文件中寄存器名、位編號正確,就不會出錯。5.1.4在項目文件中添加其他文件
STVD開發(fā)環(huán)境支持多模塊匯編。因此,可創(chuàng)建多個源程序,并將它添加到“SourceFiles”文件夾內(nèi),匯編后將根據(jù)模塊內(nèi)段定義特征連接成一個完整的應(yīng)用程序。在項目內(nèi)添加程序源文件時,需要注意以下幾點(diǎn):
(1)任意一個匯編源程序文件的第一條指令必須是“ST7/(或st7/)”或“STM8/(或stm8/)”偽指令;最后一條指令一般為“END(或end)”偽指令,且每一指令行必須帶有“回車符”。
(2)對于變量定義偽指令,必須通過“Segment”指定變量存放在哪一段內(nèi);對于代碼,也必須通過“Segment”指定存放匯編后代碼存放在哪一段內(nèi)。
(3)在多模塊結(jié)構(gòu)程序中,模塊內(nèi)的公共變量、標(biāo)號必須指定為Public類型,或用前綴“.”定義,否則匯編時將視為局部變量、標(biāo)號,僅在本模塊內(nèi)有效。模塊內(nèi)引用來自其他模塊定義的變量、標(biāo)號時必須用“EXTERN”偽指令說明。
(4)在main.asm主程序中無須加入“#include匯編源程序名.asm”指令。對于包含文件(.inc),則必須通過“#include文件名.inc”語句聲明。
(5)模塊順序決定了連接后的定位順序。在STVD中,“SourceFiles”匯編程序源文件順序依次為
Mapping.asm ;段定義源文件應(yīng)排在最前面
STM8S208MB.asm ;外設(shè)寄存器定義源程序文件,具體文件名與MCU型號有關(guān)
Main.asm ;用戶主程序或其他模塊程序5.2STM8匯編程序結(jié)構(gòu)5.2.1子程序與中斷服務(wù)程序在主模塊內(nèi)
采用子程序與中斷服務(wù)程序在主模塊內(nèi)的結(jié)構(gòu)時,工作站文件夾中除了相應(yīng)型號芯片的頭文件外,幾乎沒有其他模塊文件,形成了單一主模塊程序結(jié)構(gòu),如圖5-5所示。該結(jié)構(gòu)中所有的子程序、中斷服務(wù)程序均位于主應(yīng)用程序main.asm模塊內(nèi),變量、子程序入口地址標(biāo)號、中斷服務(wù)入口地址等屬于局部標(biāo)號與局部變量,無須指定標(biāo)號類型,也無須用EXTERN偽指令聲明其來源,但其缺點(diǎn)是程序結(jié)構(gòu)不夠清晰,查找某一個子程序時效率較低。
圖5-5單一主模塊程序結(jié)構(gòu)在這種結(jié)構(gòu)程序中,主應(yīng)用程序main.asm模塊大致包含了如下內(nèi)容:
;按st7還是stm8代碼格式匯編源程序
stm8/ ;代碼格式偽指令
;程序頭(由#define、equ、cequ定義的符號常量、標(biāo)號)#defineVAR1$50
;主程序引用的外部標(biāo)號(變量)說明區(qū)(EXTERN)
segment'rom' ;指定了代碼存放在哪一段中
mani.l ;主程序開始標(biāo)號
;初始化I/O引腳的輸入/輸出方式,并用#define指令對I/O引腳重定義
;初始化堆棧指針
;?RAM0段存儲單元清0
;?RAM1段存儲單元清0
;堆棧段存儲單元清0
;初始化主時鐘及CPU時鐘頻率
;硬件初始化(設(shè)置外設(shè)部件工作方式)
;復(fù)位中斷優(yōu)先級(開中斷);主程序?qū)嶓w指令系列;子程序;中斷服務(wù)程序;常數(shù)表(由dc.b、dc.w、dc.l定義的常數(shù)表);中斷向量表由于STVD開發(fā)環(huán)境不支持過程匯編,位于同一個匯編文件內(nèi)不同子程序中的標(biāo)號必須唯一。因此,在STVD開發(fā)環(huán)境中最好取長標(biāo)號,可按“模塊名_模塊內(nèi)標(biāo)號”形式給標(biāo)號取名。例如,在“EEPROM_Write.L”模塊中可用“EEPROM_Write_Lab1”、“EEPROM_Write_Next1”、“EEPROM_Write_Last1”、“EEPROM_Write_Loop1”等作為該模塊的標(biāo)號。盡管在理論上,子程序與中斷服務(wù)程序可存放在FlashROM存儲區(qū)中的任意位置,但在STVD開發(fā)環(huán)境中,中斷服務(wù)程序必須位于子程序后,否則在仿真調(diào)試時,調(diào)試速度會很慢,單步執(zhí)行一條指令(包括子程序調(diào)用指令)所需的時間可能很長,甚至不能接受。5.2.2子程序與中斷服務(wù)程序在各自模塊內(nèi)把子程序,尤其指令較多的子程序、中斷服務(wù)程序安排在各自模塊內(nèi),形成多模塊結(jié)構(gòu)程序,如圖5-6所示。這種程序結(jié)構(gòu)清晰,除了指定為“Public”的公共變量、標(biāo)號外,均屬于局部變量、局部標(biāo)號,這意味著不同模塊內(nèi)的局部標(biāo)號可重復(fù)使用。這有利于程序的維護(hù),以及多人協(xié)作完成同一項目控制程序的設(shè)計。圖5-6多模塊程序結(jié)構(gòu)為便于程序的維護(hù)和升級,在程序中應(yīng)盡量避免直接使用存儲單元地址。因此良好的程序習(xí)慣如下:
(1)對于常數(shù),可在程序頭中用#define、EQU偽指令定義。例如:
#definePlus_width50H或
Plus_widthEQU50H
(2)對于RAM、EEPROM中的存儲單元,最好用ds.b、ds.w、ds.l偽指令定義,使變量對應(yīng)的存儲單元地址處于浮動狀態(tài),變量實際地址待編譯后才能確定。例如:
Segment'ram0'
ds.bTRK11
ds.bTRK21
(3)位于FlashROM中的常數(shù)表,用dc.B、dc.W、dc.L偽指令定義。5.2.3子程序結(jié)構(gòu)所謂子程序就是供其他程序模塊通過CALL或CALLF指令調(diào)用的指令系列。當(dāng)子程序中存在改寫CPU內(nèi)某一寄存器(包括索引寄存器X、Y,累加器A,條件碼寄存器CC)時,如果返回后需要用到調(diào)用前該寄存器的值,則必須將其壓入堆棧保護(hù),這容易理解。但容易忽略的是寄存器CC中的標(biāo)志位,由于STM8內(nèi)核CPU許多指令均影響標(biāo)志位狀態(tài),因此返回后還需使用調(diào)用前的標(biāo)志位狀態(tài),為防止錯誤,在子程序中一律將CC寄存器壓入堆棧將是一個良好的習(xí)慣。其實,在模塊化程序設(shè)計中,把子程序中改寫的CPU寄存器一律壓入堆棧也是一個良好策略,這是因為STM8內(nèi)核MCU堆棧深度較大,如果子程序嵌套層數(shù)不太多,則遇到堆棧溢出的可能性很小。在STM8系統(tǒng)中,子程序入口地址標(biāo)號可以是Word類型,即16位地址形式,對應(yīng)的返回指令為RET;也可以是Long類型,即24位地址形式,對應(yīng)的返回指令為RETF。采用L類型地址標(biāo)號還是W類型地址標(biāo)號,與子程序存放的位置有關(guān)。
(1)當(dāng)子程序位于00段內(nèi)時,可定義為W類型,也可以定義為L類型。當(dāng)定義為W類型時,調(diào)用(CALL指令)與返回(RET指令)代碼短、執(zhí)行速度快,子程序中所有標(biāo)號均定義為W類型。為方便程序維護(hù),最好在地址標(biāo)號后加“:”(冒號)。這樣當(dāng)需要將該子程序放到01段以上時,只要將“:”(冒號)用“.L”替換;將JP絕對跳轉(zhuǎn)指令中的操作碼助記符“JP”用“JPF”替換;將返回指令RET用“RETF”替換即可。因此,00段內(nèi)入口地址為W類型的子程序結(jié)構(gòu)如下:
Sub_xxx: ;子程序入口地址標(biāo)號Sub_xxx定義為W(Word)類型
PUSHWX ;保護(hù)索引寄存器X(子程序用到寄存器X) PUSHWY ;保護(hù)索引寄存器Y(子程序用到寄存器Y) PUSHCC ;保護(hù)寄存器CC PUSHA ;保護(hù)累加器A ;子程序?qū)嶓w
JPSub_xxx_NEXT1 ;子程序?qū)嶓wSub_xxx_NEXT1: ;子程序內(nèi)的地址標(biāo)號定義為W類型
POPA POPCC POPWY POPWX RET ;子程序返回指令
RET ;子程序返回冗余指令數(shù)目為1~4條,參閱第11章這種結(jié)構(gòu)子程序,只能在00段內(nèi)通過CALL指令調(diào)用。為此可將00段內(nèi)子程序入口地址定義為L類型,以便在任何位置都可以通過CALLF指令調(diào)用。因此,00段內(nèi)推薦的子程序結(jié)構(gòu)如下:
Sub_xxx.L ;子程序入口地址標(biāo)號Sub_xxx定義為L(Long)類型
PUSHWX ;保護(hù)索引寄存器X(子程序用到寄存器X)
PUSHWY ;保護(hù)索引寄存器Y(子程序用到寄存器Y) PUSHCC ;保護(hù)寄存器CC PUSHA ;保護(hù)累加器A ;子程序?qū)嶓w
JPSub_xxx_NEXT1 ;為減少指令碼長度、提高運(yùn)行速度,仍采用JP絕對跳轉(zhuǎn)指令
;子程序?qū)嶓wSub_xxx_NEXT1: ;子程序內(nèi)的地址標(biāo)號定義為W類型
POPA POPCC POPWY POPWX RETF ;子程序返回指令
RETF ;子程序返回冗余指令
(2)當(dāng)子程序位于01段以上時,入口地址標(biāo)號必須定義為L類型,同時,子程序內(nèi)所有地址標(biāo)號均定義為L類型,如下所示:
Sub_xxx.L ;子程序入口地址標(biāo)號Sub_xxx定義為L(Lord)類型
PUSHWX ;保護(hù)索引寄存器X(子程序用到寄存器X) PUSHWY ;保護(hù)索引寄存器Y(子程序用到寄存器Y) ;子程序?qū)嶓w
JPFSub_xxx_NEXT1 ;采用遠(yuǎn)跳轉(zhuǎn)指令JPF ;子程序?qū)嶓wSub_xxx_NEXT1.L ;子程序內(nèi)所有地址標(biāo)號必須定義為L類型
POPWY POPWX RETF ;子程序返回指令
RETF ;子程序返回冗余指令值得注意的是:中斷服務(wù)程序入口地址標(biāo)號一定為L類型,原因是STM8內(nèi)核CPU響應(yīng)中斷請求時,將入口地址標(biāo)號對應(yīng)的三個字節(jié)壓入堆棧;在中斷服務(wù)程序中,無須將CPU內(nèi)核寄存器壓入堆棧,這是因為STM8內(nèi)核CPU響應(yīng)中斷請求時已自動將CPU內(nèi)各寄存器壓入堆棧。5.3程序基本結(jié)構(gòu)5.3.1順序結(jié)構(gòu)所謂順序程序結(jié)構(gòu),是指程序段中沒有轉(zhuǎn)移指令,執(zhí)行時CPU逐條執(zhí)行。例5-1查表程序。假設(shè)共陽LED數(shù)碼管數(shù)碼0~F的筆段碼存放在以LED_Data為標(biāo)號的存儲單元中,如下所示:
LED_Data:
;
0,
1,2,
3,4,
5,
6,7,
8,9,
A,B,
C,D,
E,
F
dc.B
0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H,088H,083H,0C6H,0A1H,086H,08EH顯示數(shù)據(jù)在累加器A中,試編寫一個程序段將顯示數(shù)據(jù)對應(yīng)的筆段碼取出。
參考程序段如下:
CLRWX ;寄存器X清0 LDXL,A ;顯示數(shù)碼送寄存器XL ADDWX,#LED_Data ;加上數(shù)據(jù)首地址LDA,(X) ;取出對應(yīng)的筆段碼或
CLRWX ;寄存器X清0 LDXL,A ;顯示數(shù)碼送寄存器XL LDA,(LED_Data,X) ;以“基址?+?變址尋址”方式取出對應(yīng)的筆段碼例5-2
將存放在R01單元中壓縮形式的BCD碼轉(zhuǎn)換為二進(jìn)制數(shù)。參考程序如下:
;功能:把存放在R01單元中壓縮形式的BCD碼轉(zhuǎn)換為二進(jìn)制數(shù)
;算法:
;入口參數(shù):待轉(zhuǎn)換的BCD碼存放在R01單元中
;出口參數(shù):結(jié)果回送R01單元,假定R01物理地址在RAM存儲區(qū)中
;使用資源:寄存器A、X及R01單元S_BCD_BI.W ;單字節(jié)BCD碼轉(zhuǎn)二進(jìn)制
LDA,R01 ;取BCD碼
ANDA,#0F0H ;保留高4位(十位) SWAPA LDXL,A LDA,#10 MULX,A ;?X←XL?×?A,十位乘10,最大為90,高8位XH為0 LDA,R01 ;取BCD碼
ANDA,#0FH ;保留BCD碼個位
LDR01,A ;回送R01暫存
LDA,XL ADDA,R01 LDR01,A RET例5-3把存放在R02、R03單元中壓縮形式的BCD碼轉(zhuǎn)換為二進(jìn)制數(shù),結(jié)果回送到R02、R03單元中。參考程序如下:
;功能:把存放在R02、R03單元中壓縮形式的BCD碼轉(zhuǎn)換為二進(jìn)制數(shù)
;算法:a3?×?103?+?a2?×?102?+?a1?×?10?+?a0?=?(a3?×?10?+?a2)?×?100?+?(a1?×?10?+?a0)
;入口參數(shù):待轉(zhuǎn)換的BCD碼存放在寄存器R02、R03單元中
;出口參數(shù):結(jié)果回送R02、R03單元,假定兩單元相鄰,可按字節(jié)訪問,也可以按字訪問
;使用資源:寄存器A、X以及R01單元D_BCD_BI.W MOVR01,R03 ;十位、個位送R01 CALLS_BCD_BI ;調(diào)用單字節(jié)BCD碼轉(zhuǎn)二進(jìn)制子程序,計算a1?×?10?+?a0 MOVR03,R01 ;結(jié)果暫時存放在R03中
MOVR01,R02 ;千位、百位送R01 CALLS_BCD_BI ;調(diào)用單字節(jié)BCD碼轉(zhuǎn)二進(jìn)制子程序,計算a3?×?10?+?a2 LDA,R01 LDXL,A ;結(jié)果送寄存器XL中
LDA,#100 MULX,A ;?(a3?×?10?+?a2)?×?100,結(jié)果在寄存器X中
CLRR02 ;清除R02單元
ADDWX,R02 ;按字相加
LDWR02,X ;結(jié)果回送R02、R03單元
RET例5-4將存放在R01單元中的二進(jìn)制數(shù)轉(zhuǎn)換為壓縮形式的BCD碼,結(jié)果存放在R02(百位)、R03(十位及個位)單元。參考程序如下:
;算法:待轉(zhuǎn)換的二進(jìn)制數(shù)除以100,所得的商是百位,余數(shù)再除以10所得的商是十位,余數(shù)為個位
;入口參數(shù):待轉(zhuǎn)換的二進(jìn)制存放在R01單元中
;出口參數(shù):百位存放在R02單元中,十位及個位存放在R03單元中
;使用資源:寄存器A、X及R02、R03單元
S_BI_BCD: ;單字節(jié)二進(jìn)制轉(zhuǎn)化為壓縮形式的BCD碼
CLRWX LDA,R01 LDXL,A LDA,#100 DIVX,A ;商(百位碼)在XL中,余數(shù)在A中
EXGA,XL ;商與余數(shù)交換
LDR02,A ;保存百位碼
LDA,#10 DIVX,A ;商(十位碼)在XL中,余數(shù)(個位碼)在A中
LDR03,A ;個位碼先放R03LDA,XL ;取十位碼SWAPA ;十位碼轉(zhuǎn)移到高4位ORA,R03 ;合并壓縮形式的BCD碼LDR03,ARET5.3.2循環(huán)結(jié)構(gòu)循環(huán)程序結(jié)構(gòu)由初始化、循環(huán)體、包含條件跳轉(zhuǎn)指令的循環(huán)控制等三部分組成。例5-5
將ram0段(即00H~FFH)存儲單元清0。由于需要清除256個單元,因此,不能再用例5-1~例5-4所示的順序程序結(jié)構(gòu),否則程序會很長,須用循環(huán)結(jié)構(gòu)程序?qū)崿F(xiàn)。參考程序如下:;初始化LDWX,#ram0_start ;初始化索引寄存器X ;循環(huán)體Ram0_CLR_LOOP: CLR(X) ;把寄存器X內(nèi)容對應(yīng)單元清0 INCWX ;?X加1,指向下一個存儲單元
;循環(huán)控制指令CPWX,#ram0_end ;與ram0段的終了地址比較JRULERam0_CLR_LOOP ;當(dāng)X不大于終了地址時,跳轉(zhuǎn)到標(biāo)號為LOOP處繼續(xù)執(zhí)行5.3.3分支程序結(jié)構(gòu)分支程序也是一種常見的程序結(jié)構(gòu),常需要根據(jù)運(yùn)算結(jié)果、某一個輸入引腳的狀態(tài),決定是否執(zhí)行相應(yīng)的操作。根據(jù)分支多少,可將分支程序結(jié)構(gòu)分為簡單分支(即兩分支)結(jié)構(gòu)和多路分支結(jié)構(gòu)。
1.簡單分支簡單分支常用條件轉(zhuǎn)移指令實現(xiàn),例如位測試轉(zhuǎn)移指令,如下所示:
BTJTR00,#3,NEXT1
NEXT1:
2.多路分支在STM8指令系統(tǒng)中,00段內(nèi)的多路分支可用無條件跳轉(zhuǎn)指令JP(TAB_ADR,X)實現(xiàn),為菜單、并行多任務(wù)程序結(jié)構(gòu)中任務(wù)與作業(yè)切換操作等提供了方便。由于變址寄存器X為16位,因此可以實現(xiàn)超過256分支的散轉(zhuǎn)。例5-6
編寫一段程序完成32位除以16位的運(yùn)算。假設(shè)32位被除數(shù)存放在R04、R05、R06、R07單元中,16位除數(shù)存放在R00、R01單元中。
STM8內(nèi)核CPU沒有32位除以16位運(yùn)算指令,只能通過類似多項式除法完成。根據(jù)運(yùn)算規(guī)則可知商為32位,余數(shù)為16位,因此需要把除數(shù)擴(kuò)展為16?+?32?=?48位,然后通過移位相減獲得對應(yīng)位的商。參考程序如下:
DIV3216: ;?32位除以16位運(yùn)算子程序(沒有檢查除數(shù)為0)
;?32bit/16bit運(yùn)算程序
;入口參數(shù):32位被除數(shù)存放在R04~R07單元中,高位放在低地址
; :16位除數(shù)存放在R00~R01單元中,高位放在低地址
;出口參數(shù):32位商放在R04、R05、R06、R07單元中
; :余數(shù)放在R02、R03寄存器中
;算法:通過移位相減類似多項式除法實現(xiàn),先將被除數(shù)擴(kuò)展為32?+?16位,即48位
;執(zhí)行時間約為584個機(jī)器周期;使用資源:X,ACLRR02CLRR03 ;擴(kuò)展被除數(shù)為(32?+?16)位LDA,#32 ;定義移位相減次數(shù)DIV3216_LOOP1: SLLR07 ;左邏輯移位(C←b7,b7←b6,b0←0)RLCR06RLCR05RLCR04RLCR03RLCR02BCCMR07,#0 ;?C移到R07的b0位LDWX,R02 ;取擴(kuò)展被除數(shù)最高位SUBWX,R00JRNCDIV3216_NEXT1;
C
=
1,即有借位BTJFR07,#0,DIV3216_NEXT2 ;商已為0,無須再設(shè)置;移出位為1,說明也夠減DIV3216_NEXT1:;夠減,用差替換被減數(shù)BSETR07,#0 ;?b0位置1,用差替換被減數(shù)LDWR02,XDIV3216_NEXT2:DECAJRNEDIV3216_LOOP1RET可見,實現(xiàn)32位除以16位運(yùn)算程序段指令代碼不長,執(zhí)行時間大約為584個機(jī)器周期。用多項式除法運(yùn)算規(guī)則實現(xiàn)除法運(yùn)算時,一般情況下需要擴(kuò)展被除數(shù),但在特殊情況下,也可以不用擴(kuò)展被除數(shù)。例如,當(dāng)除數(shù)不小于8000H,即除數(shù)最高位b15為1,可不用擴(kuò)展被除數(shù),而是直接用被除數(shù)高位減除數(shù),完成時間將極大地縮短,僅需300個機(jī)器周期,如例5-7所示。例5-7已知32位被除數(shù)存放在R04~R07單元中,不小于8000H的16位除數(shù)存放在R00~R01單元中,編寫出相應(yīng)的除法計算指令系列。參考程序如下:
DIV3216A: ;特殊的32位除以16位運(yùn)算子程序
;?32?bit?/?16?bit運(yùn)算程序
;入口參數(shù):32位被除數(shù)存放在R04~R07中,高位放在低地址
;不小于8000H的16位除數(shù)存放在R00~R01中,高位放在低地址
;出口參數(shù):32位商放在R05(只有b0,即商的b16位有效)、R06、R07中;余數(shù)放在寄存器X中;算法:通過移位相減實現(xiàn),由于除數(shù)不小于8000H,因此無須擴(kuò)展被除數(shù)為48位;執(zhí)行時間為300個機(jī)器周期;使用資源:寄存器X,ALDA,#16BRESR02,#0 ;開始時移出位為0LOOP1:LDWX,R04 ;取被除數(shù)最高位SUBWX,R00 ;減除數(shù)JRNCNEXT1;有借位BTJTR02,#0,NEXT1;有借位,且移出位為0,不夠減,應(yīng)保留原來的被減數(shù) RCF ;商為0 JRTNEXT2NEXT1: LDWR04,X ;用差替換被除數(shù)高16位
SCF ;商為1NEXT2: RLCR07 ;移位
RLCR06 RLCR05 RLCR04 BCCMR02,#0 ;?C送R02的b0位
DECA ;循環(huán)次數(shù)減1 JRNELOOP1 ;最后一次減
LDWX,R04 ;取被除數(shù)最高位
SUBWX,R00 JRNCNEXT3
BTJTR02,#0,NEXT3 ;有借位,且移出位為0,說明不夠減,保留原來的差
LDWX,R04 RCF ;商為0 JRTNEXT4NEXT3: ;最后一次移位,形成商
SCF ;商為1NEXT4:
CLRR05 ;清除商的最高位
RLCR07 ;把最后運(yùn)算結(jié)果移到商字節(jié)
RLCR06 RLCR05 RET在單片機(jī)應(yīng)用系統(tǒng)中,有時用查表方式代替分支程序結(jié)構(gòu)可能更簡單,不僅代碼短、運(yùn)行速度快,程序維護(hù)、修改也非常方便,如例5-8所示。例5-8在某工程設(shè)計中,3個觸發(fā)器Q2、Q1、Q0狀態(tài)及其6個輸出量y5~y0變化規(guī)律如表5-1所示,表中未列出的狀態(tài)均屬無效態(tài)。表5-1轉(zhuǎn)換表如果采用條件跳轉(zhuǎn)指令的分支程序結(jié)構(gòu)完成狀態(tài)判別及計算輸出量y5~y0的值將很復(fù)雜,而采用查表方式完成就非常簡單。根據(jù)表5-1狀態(tài)轉(zhuǎn)換對應(yīng)的輸出量,不難得出二維數(shù)表,即b5~b0對應(yīng)y5~y0,b6未使用規(guī)定為0,b7為“1”時表示無效態(tài),如下所示:Y5_Y0_TAB:;列編號為新狀態(tài)(n+1),行編號為當(dāng)前狀態(tài)(n);01234567 dc.b01H,10H,02H,05H,05H,01H,06H,80H ;當(dāng)前狀態(tài)(0) dc.b80H,00H,20H,80H,25H,21H,24H,80H ;當(dāng)前狀態(tài)(1) dc.b80H,10H,00H,80H,05H,01H,04H,80H ;當(dāng)前狀態(tài)(2) dc.b09H,80H,80H,01H,80H,80H,80H,80H ;當(dāng)前狀態(tài)(3) dc.b80H,10H,0AH,80H,00H,08H,02H,80H ;當(dāng)前狀態(tài)(4) dc.b80H,10H,02H,80H,04H,00H,06H,80H ;當(dāng)前狀態(tài)(5) dc.b80H,10H,08H,80H,01H,09H,00H,80H ;當(dāng)前狀態(tài)(6) dc.b80H,80H,80H,80H,80H,80H,80H,80H ;當(dāng)前狀態(tài)(7)參考程序段如下:LDA,stu_Q2_0 ;取Q2~Q0當(dāng)前狀態(tài)ANDA,#07HSLLASLLASLLA ;每個舊狀態(tài)對應(yīng)8個新狀態(tài),因此要乘以8ADDA,R00 ;假設(shè)新狀態(tài)存放在R00單元中CLRWXLDXL,A ;舊—新狀態(tài)編號存放在寄存器X中LDA,(Y5_Y0_TAB,X) ;查表獲得舊—新狀態(tài)對應(yīng)的輸出量CPA,#80HJRNENEXT1;遇到非法狀態(tài),可根據(jù)需要強(qiáng)制系統(tǒng)復(fù)位或不處理dc.b05Hdc.b05Hdc.b05Hdc.b05Hdc.b05H ;本例強(qiáng)制執(zhí)行非法指令使系統(tǒng)復(fù)位NEXT1:MOVstu_Q2_0,R00 ;更新狀態(tài)變量stu_Q2_0LDR00,A ;把輸出量送R00單元,以便通過位測試判別BTJFR00,#0,NEXT21;?R00的b0位即y0為1
;執(zhí)行y0為1的指令系列NEXT21:BTJFR00,#1,NEXT22;
R00的b1位即y1為1 ;執(zhí)行y1為1的指令系列NEXT22: ;省略5.4并行多任務(wù)程序結(jié)構(gòu)及實現(xiàn)5.4.1串行多任務(wù)程序結(jié)構(gòu)與并行多任務(wù)程序結(jié)構(gòu)在串行多任務(wù)程序結(jié)構(gòu)中,按預(yù)先設(shè)定的順序執(zhí)行各任務(wù)(即模塊),任何時候只執(zhí)行其中的一個任務(wù),如圖5-7所示。
串行多任務(wù)程序結(jié)構(gòu)簡單、清晰,編寫、調(diào)試比較容易,是單片機(jī)應(yīng)用系統(tǒng)中最常用的程序結(jié)構(gòu)之一。但在串行多任務(wù)程序結(jié)構(gòu)中,只能通過查詢(如果滿足條件,則通過CALL及CALLF指令)和中斷方式執(zhí)行某些需要實時處理的事件,不適應(yīng)于具有多個需要實時處理事件的應(yīng)用系統(tǒng)。例如,在無線防盜報警器中,某防區(qū)報警時,第一要通過電話線將報警信息以DTMF方式發(fā)送到接警中心,或以語音方式通知用戶;第二要監(jiān)控其他防區(qū)有無被觸發(fā),即無線接收、解碼不能停頓;第三要監(jiān)視電話線狀態(tài),如忙音、回鈴音、被叫方提機(jī)、斷線等;第四是控制內(nèi)置警笛的音量及音調(diào)。為此,在單片機(jī)應(yīng)用系統(tǒng)中,有時需要用“實時(或稱為并行)多任務(wù)”程序結(jié)構(gòu)。由于單片機(jī)系統(tǒng)內(nèi)嵌RAM存儲器容量小,如STM8系列芯片的只有幾KB,沒有更多空間存放任務(wù)切換時需要保護(hù)的數(shù)據(jù)——斷點(diǎn)(即PC指針)、現(xiàn)場(CPU內(nèi)寄存器,如累加器A、通用寄存器、標(biāo)志寄存器等)和中間結(jié)果,因此決定了單片機(jī)應(yīng)用系統(tǒng)并行多任務(wù)程序結(jié)構(gòu)與一般微機(jī)、小型機(jī)并行多任務(wù)操作系統(tǒng)程序結(jié)構(gòu)有所不同。圖5-7串行多任務(wù)程序結(jié)構(gòu)5.4.2并行多任務(wù)程序結(jié)構(gòu)并行多任務(wù)程序結(jié)構(gòu)如圖5-8所示。圖5-8并行多任務(wù)程序結(jié)構(gòu)把需要實時處理的多個任務(wù)排成一個隊列,通過隊列指針(也稱為任務(wù)號),借助散轉(zhuǎn)指令,如STM8的“JP(TAB_ADR,X)”指令(或條件轉(zhuǎn)移指令)實現(xiàn)任務(wù)間的切換。每個任務(wù)執(zhí)行時間長短不同,需將每一個任務(wù)細(xì)分為若干作業(yè)(或稱為子過程),不同任務(wù)的作業(yè)量不盡相同,即作業(yè)量與任務(wù)本身的復(fù)雜程度有關(guān)。例如,在圖5-8中的A任務(wù),就分成A0、A1、A2、…、An,即n個作業(yè)。為此還需給每一個任務(wù)設(shè)置一個作業(yè)指針(或稱為作業(yè)號),切換到某一個任務(wù)后,執(zhí)行其中的哪一個作業(yè)由任務(wù)內(nèi)的作業(yè)指針確定。在并行多任務(wù)程序結(jié)構(gòu)中,各任務(wù)地位相同,每個任務(wù)內(nèi)的作業(yè)地位也相同。并行多任務(wù)程序結(jié)構(gòu)模塊清晰,能方便地增減其中任一個模塊。任務(wù)調(diào)度也很靈活,可根據(jù)當(dāng)前作業(yè)的執(zhí)行結(jié)果選擇下一步將要執(zhí)行的任務(wù)號,非常適合于需要實時處理的多任務(wù)控制系統(tǒng),實用價值較高。在單片機(jī)并行多任務(wù)程序結(jié)構(gòu)設(shè)計中,需要考慮的問題及注意事項如下:
(1)作業(yè)劃分原則。為減少任務(wù)、作業(yè)切換時需要保護(hù)的數(shù)據(jù)量,任務(wù)內(nèi)的每一個作業(yè)必須是一個完整的子過程。對于執(zhí)行時間較長的任務(wù),通過設(shè)置若干標(biāo)志后,細(xì)分為多個作業(yè),使每個作業(yè)執(zhí)行時間不超出系統(tǒng)基本定時器的溢出時間。按上述原則劃分作業(yè)后,在作業(yè)處理過程中,除中斷外不被其他任務(wù)所中斷,作業(yè)執(zhí)行結(jié)束后,只需將處理結(jié)果保存到相應(yīng)的RAM存儲單元中,對于初始化處理類作業(yè)根本無須保存結(jié)果;無須保護(hù)現(xiàn)場,即CPU各寄存器的值,如STM8的寄存器CC、A、X、Y等。
(2)任務(wù)切換方式。在微機(jī)、小型機(jī)實時多任務(wù)操作系統(tǒng)中,一般按設(shè)定順序執(zhí)行各任務(wù),即每一個作業(yè)執(zhí)行結(jié)束后任務(wù)指針加1,當(dāng)執(zhí)行到最后一個任務(wù)時將指針切換到第一個任務(wù)。在單片機(jī)控制系統(tǒng)中,一般不宜采用“定時時間到切換”規(guī)則,如果系統(tǒng)中沒有需要精確定時的事件,根本不需要定時器。原因是單片機(jī)系統(tǒng)時鐘頻率低,CPU響應(yīng)速度慢,內(nèi)嵌RAM容量有限,沒有更多空間存放任務(wù)切換時需要保存的大量數(shù)據(jù)。另外,在單片機(jī)應(yīng)用系統(tǒng)中,控制對象屬性、控制對象所要執(zhí)行的操作又非常明確,完全可根據(jù)當(dāng)前作業(yè)的執(zhí)行結(jié)果和系統(tǒng)的當(dāng)前狀態(tài),直接切換到某個任務(wù),以提高系統(tǒng)的實時性。這與十字路口交通燈切換時間最好由當(dāng)前的車流量決定問題類似。例如,在報警器設(shè)計中,報警器上傳接警中心信息可分為三大類:布防、撤防及報警信息(包括旁路信息及系統(tǒng)狀態(tài)信息)。為減輕用戶話費(fèi)負(fù)擔(dān),這三類信息須分別撥打不同的電話號碼。對于布防、撤防信息來說,一般只需了解該信息來自哪一個用戶及其時間,完全可借助“來電顯示”功能感知信息來源與發(fā)生的時間(用FSK來電信息幀內(nèi)嵌時間或接警中心內(nèi)部時鐘),無須提機(jī)。對于布防、撤防以外的信息,如報警、旁路信息等,還需要進(jìn)一步了解是哪個防區(qū)報警、旁路,什么樣的警情等,需要提機(jī)接收報警器上傳的全部信息。為此,在撥號前除了先根據(jù)緩沖區(qū)內(nèi)信息類型確定撥打的電話號碼外,在撥號過程中還必須根據(jù)緩沖區(qū)內(nèi)出現(xiàn)的新信息,決定是繼續(xù)撥號,還是掛機(jī)后撥打另一個號碼。為進(jìn)一步提高系統(tǒng)的即時處理能力,除了在每個作業(yè)執(zhí)行結(jié)束后根據(jù)當(dāng)前作業(yè)的執(zhí)行結(jié)果、系統(tǒng)當(dāng)前狀態(tài)設(shè)置任務(wù)號外,還可在中斷服務(wù)程序中重新設(shè)置任務(wù)號。
(3)通過中斷方式響應(yīng)需要實時處理的事件。在作業(yè)處理過程中,只能通過中斷方式(包括定時器溢出中斷、外部中斷等)響應(yīng)需要實時處理的事件。為避免中斷服務(wù)程序執(zhí)行時間過長,降低系統(tǒng)對同級中斷請求響應(yīng)的實時性,需要在中斷服務(wù)程序中引入事件驅(qū)動方式:響應(yīng)某一個中斷請求后,僅設(shè)置事件發(fā)生標(biāo)志或進(jìn)行簡單處理后就退出,而事件執(zhí)行由事件處理程序完成,也就是說把中斷響應(yīng)與事件處理過程分離,以提高系統(tǒng)的實時響應(yīng)速度。例如,DTMF解碼芯片8870解碼有效DV信號接STM8SMCU的外中斷PD口的某一個引腳,則PD口中斷服務(wù)程序如下:InterruptPD_Interrupt_procPD_Interrupt_proc.L BSETPA_ODR,#6 ;解碼輸出允許OE接PA6引腳
LDA,PI_IDR ;解碼輸出引腳D3~D0分別接MCU的PI3~PI0 ANDA,#0FH ;屏蔽與解碼輸入無關(guān)位
ORA,#80H ;將DTMF輸入寄存器b7位置1,作為解碼輸入有效標(biāo)志
LDDTMF_IN,A ;輸入數(shù)據(jù)放入DTMF_IN變量后就退出,至于輸入什么數(shù)據(jù)
;由解碼輸入處理程序判別和處理
BRESPA_ODR,#6 ;將8870解碼輸出置為高阻態(tài)
IRET系統(tǒng)中由主定時器控制的各定時時間必須呈整數(shù)倍關(guān)系,主定時器的溢出時間就是最小的定時時間。對于需要精確定時的事件,可放在系統(tǒng)主定時器中斷服務(wù)程序中計時,定時時間到,相應(yīng)標(biāo)志位置1,處理程序檢查相應(yīng)標(biāo)志來確定是否需要處理相應(yīng)事件。例如,當(dāng)主定時器溢出時間為10ms,而鍵盤定時掃描間隔為20ms時,那么,主定時器中斷服務(wù)程序內(nèi)與鍵盤掃描定時有關(guān)的指令為
DECKEY_TIMEJRNEEXIT_K_T
;鍵盤掃描定時器減1,不為0跳轉(zhuǎn)BSETR_S_KEY,#0
;置位鍵盤掃描執(zhí)行標(biāo)志R_S_KEY[0]MOVKEY_TIME,#2
;重置鍵盤掃描定時時間EXIT_K_T:
(4)子程序調(diào)用原則。各任務(wù)內(nèi)任意一個作業(yè)均可調(diào)用同一個子程序,但不允許中斷服務(wù)程序調(diào)用,以免產(chǎn)生混亂。主定時器中斷服務(wù)程序應(yīng)盡量短小,當(dāng)遇到處理時間較長的事件時,可通過設(shè)置執(zhí)行標(biāo)志后返回,在主程序任務(wù)調(diào)度處理過程中執(zhí)行。下面是具有4個任務(wù)的“實時多任務(wù)”程序結(jié)構(gòu):Segment'ram0'BytesTASKPds.b1 ;任務(wù)指針TASK0P ds.b1 ;任務(wù)0作業(yè)指針;TASK0P_TIMEds.b1 ;任務(wù)0執(zhí)行控制時間。對于有時間限制的任務(wù),可設(shè)置
;任務(wù)執(zhí)行時間TASK1Pds.b1 ;任務(wù)1作業(yè)指針;TASK1P_TIMEds.b1 ;任務(wù)1執(zhí)行控制時間TASK2P ds.b1 ;任務(wù)2作業(yè)指針;TASK2P_TIMEds.b1 ;任務(wù)2執(zhí)行控制時間TASK3P ds.b1 ;任務(wù)3作業(yè)指針;TASK3P_TIMEds.b1 ;任務(wù)3執(zhí)行控制時間WordsSegment'rom'main.L;初始化部分MOVTASKP,#0 ;從任務(wù)0開始執(zhí)行MOVTASK0P,#0 ;任務(wù)0從作業(yè)0開始MOVTASK1P,#0 ;任務(wù)1從作業(yè)0開始
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 礦產(chǎn)勘查地球物理異常分析與解釋考核試卷
- 電池制造與冰雪項目考核試卷
- 特色美術(shù)社團(tuán)課程設(shè)計
- 森林公園生態(tài)旅游產(chǎn)品差異化設(shè)計考核試卷
- 生態(tài)保護(hù)與工業(yè)綠色轉(zhuǎn)型考核試卷
- 電磁離合器與制動器考核試卷
- 玻璃儀器在醫(yī)療設(shè)備制造中的應(yīng)用考核試卷
- 電子樂器新型傳感器技術(shù)研究考核試卷
- 電池在生命體征監(jiān)測系統(tǒng)中的重要性考核試卷
- 白桃種植技術(shù)解析考核試卷
- 糧油食材配送投標(biāo)方案(大米食用油食材配送服務(wù)投標(biāo)方案)(技術(shù)方案)
- 2024年自然資源部直屬企事業(yè)單位公開招聘考試筆試易考易錯模擬試題(共500題)試卷后附參考答案
- 2024變電站集中監(jiān)控系統(tǒng)第8部分:遠(yuǎn)程智能巡視
- 2024-2030年中國無糖壓縮餅干行業(yè)市場現(xiàn)狀供需分析及投資評估規(guī)劃分析研究報告
- 北京大學(xué)圖書館招考聘用高頻考題難、易錯點(diǎn)模擬試題(共500題)附帶答案詳解
- 壓力箱涵施工組織設(shè)計
- 安全管理三級體系
- 2024年商用密碼應(yīng)用安全性評估從業(yè)人員考核試題庫-下(判斷題)
- 快樂讀書吧《愛的教育》復(fù)習(xí)小結(jié)(知識點(diǎn))-統(tǒng)編版語文六年級上冊
- 2024年人教版初一生物(上冊)期末考卷及答案(各版本)
- 2024至2030年中國無糖壓縮餅干行業(yè)市場全景監(jiān)測及投資策略研究報告
評論
0/150
提交評論