版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、STM8與匯編語言(1)不知是心血來潮,還是其它因素,突然又想起玩匯編語言了。這幾年也沒少跟單片機打交道,包括51系列,430系列,ARM系列,但都是用C語言來開發(fā)。不過由于使用C語言,實際上對這些CPU的了解還是不夠深刻,當(dāng)然除了51之外,因為那是我多年前曾經(jīng)用匯編開發(fā)過的芯片。盡管當(dāng)今C語言已經(jīng)在嵌入式產(chǎn)品的開發(fā)過程中成為主流,但我個人依然認(rèn)為,要想真正了解CPU的特點,還得用匯編語言。不知道這種觀點是對還是錯,也許是因為自己從硬件做起,寫過機器碼,用匯編語言做過優(yōu)化,因此對匯編語音有一種特殊的偏愛。51系列的芯片用多了,感覺有時寫起程序來不太方便,因此總想尋找一些其它的8位單片機玩玩,正
2、好手頭有一個ST的三合一開發(fā)板,那是09年參加ST研討會上買的,一直躺在那里,與其躺在那里,不如拿出來玩玩。這幾年,ST在國內(nèi)推廣STM32,力度不小,不過我一直沒有用過,只是初步地看看資料。原因在于在32位單片機方面,我一直在用Luminary公司的LM3S1138,感覺不錯,一直都很順利。09年ST舉辦的研討會上,ST除了介紹STM32外,也介紹了STM8,當(dāng)時聽了以后,覺得還行。尤其是會上的低功耗演示給我留下了很深刻的印象?;谶@些,我決定好好地玩一下STM8芯片,并將玩的結(jié)果拿出來與大家共享。STM8與匯編語言(2)第一次打開STM8的手冊時發(fā)現(xiàn),CPU中的寄存器只有6個,即A、X、Y
3、、SP、PC和CC。這幾個寄存器,看上去特象早年蘋果機使用的微處理器6502。在眼下都是多寄存器的RISC潮流下,不知ST推出的這種CPU架構(gòu)有什么意圖?這樣的芯片能否與Microchip或者Atmel的RISC結(jié)構(gòu)的MCU競爭呢?在此我無意做評論,我只想了解這顆芯片。通過仔細研究,我發(fā)現(xiàn)由于STM8采用了32位寬度的程序存儲器結(jié)構(gòu),使得大部分的指令都能在一個周期內(nèi)取出,并且采用了哈佛結(jié)構(gòu)和流水線,相當(dāng)多的指令也都是單周期完成的。這樣的話,雖然CPU是CISC架構(gòu)的,但也基本上達到了單周期指令的效果,就像手冊上說的,CPU的性能達到了20MISP24MHZ。就這一點來說,我個人感覺STM8還真
4、不錯。舉個例子來說,如果我們要完成內(nèi)存中的2個8位無符號數(shù)相加,結(jié)果還保存到內(nèi)存中,用C語言描述成:unsigned char a,b,c;c = a + b;這一段程序,用STM8匯編可以寫成如下代碼:LD A, $1000 ADD A, $1001 LD $1002, A這里假設(shè)a,b,c這3個變量分別存儲在內(nèi)存中,地址為1000,1001和1002。從STM8的手冊上可以查到,這3條指令都是單周期的,完成一個加法,只需要3個時鐘周期,可見STM8的CPU執(zhí)行速度還是相當(dāng)快的。在這種傳統(tǒng)的所謂CISC架構(gòu)中,我特別關(guān)心累加器A與內(nèi)存的訪問速度,因為如果累加器與內(nèi)存的訪問速度是單周期的話,實
5、際上我們就可以將內(nèi)存當(dāng)寄存器來看,這樣寫程序時就相當(dāng)于擁有了一個大的寄存器陣列,或者說我們也就沒必要再去考慮變量在內(nèi)存中還是在寄存器中。也正是因為這一點,我對STM8越來越感興趣了。STM8與匯編語言(3)STM8的開發(fā)環(huán)境用起來還是不錯的,可以到ST的網(wǎng)站上下載安裝程序ST_Toolset.exe。利用該環(huán)境可以開發(fā)用匯編語言寫的程序,而且與ST的三合一開發(fā)板配合起來,確實非常方便。不過如果要想用C語言來開發(fā),稍微有點麻煩,得去別的公司下載C的編譯器(CXSTM8_16K.exe),而且下載完以后,還得去注冊,等待許可文件。實際上,我也按照ST介紹的方法做了,但始終都沒有收到許可文件,也許本
6、人實在愚笨。但不管怎么說,我覺得ST這一點做得相當(dāng)不好,實在有點摳門。既然是免費的,為什么不一起打包提供給客戶,這么麻煩,多耽誤客戶使用,得少賣多少STM8的芯片。言歸正傳,還回到正題。用匯編語言開發(fā)程序,最簡單的就是利用ST開發(fā)環(huán)境中提供的匯編程序框架自動生成功能。打開開發(fā)環(huán)境后,在File菜單中選擇New Workspace,點擊Create workspace and project圖標(biāo),然后就可以建立項目,在工具鏈中選ST Assembler Linker,最后選擇MCU的型號,點擊OK,就完成了一個項目的建立。這個環(huán)境與微軟的VC6開發(fā)環(huán)境很象,點開項目文件中的Source File
7、s,能看到系統(tǒng)自動生成好了一個匯編語言的框架,我們編寫程序只要在這框架基礎(chǔ)上就可以了。其實不用編寫任何一條指令,這個框架程序是能夠編譯通過,并下載運行的。自動生成的項目中包含3個重要的文件:mapping.inc,mapping.asm和main.asm。mapping.inc文件中定義的是一些常量,mapping.asm文件中定義的是一些內(nèi)存的分配,主要的匯編代碼都在main.asm。下面是main.asm中的匯編代碼及注釋。stm8/#include "mapping.inc"segment 'rom' 下面是定義一個標(biāo)號,ST匯編的寫法,有點不習(xí)慣;
8、這里的main標(biāo)號是復(fù)位后的第一條指令,與后面的中斷向量表中; 的名字是對應(yīng)的main.l ; initialize SPldw X,#stack_endldw SP,X ; 設(shè)置堆棧指針 #ifdef RAM0; 如果定義了RAM0,則要匯編以下代碼 ; clear RAM0ram0_start.b EQU $ram0_segment_startram0_end.b EQU $ram0_segment_endldw X,#ram0_start ;寄存器X指向要清除的內(nèi)存起始地址 clear_ram0.l ;這是一個標(biāo)號定義,用于后面的跳轉(zhuǎn)指令clr (X) ;對應(yīng)的內(nèi)存單元清0 incw X
9、 ;寄存器X+1,指向下一個單元 cpw X,#ram0_end ;比較寄存器X是否等于內(nèi)存的最后一個地址 jrule clear_ram0 ;若不等于,則循環(huán) #endif#ifdef RAM1; 如果定義了RAM1,則要匯編以下代碼,代碼含義與上面完全一樣 ; clear RAM1ram1_start.w EQU $ram1_segment_startram1_end.w EQU $ram1_segment_endldw X,#ram1_startclear_ram1.lclr (X)incw Xcpw X,#ram1_endjrule clear_ram1#endif; clear st
10、ack; 將堆棧區(qū)的內(nèi)存單元清0,代碼含義與上面完全一樣 stack_start.w EQU $stack_segment_startstack_end.w EQU $stack_segment_endldw X,#stack_startclear_stack.lclr (X)incw Xcpw X,#stack_endjrule clear_stackinfinite_loop.l ; 定義一個標(biāo)號;由于是一個框架,初始化內(nèi)存后,進入一個死循環(huán)jra infinite_loop ;下面代碼寫的是一段中斷服務(wù)程序,不過也是空的interrupt NonHandledInterruptNonHa
11、ndledInterrupt.l; 當(dāng)進入中斷服務(wù)程序后,無其它動作,直接返回 iret ; 下面這張表很重要,定義了STM8所有的硬件中斷對應(yīng)的中斷; 服務(wù)程序的入口地址 segment 'vectit'dc.l $82000000+main; resetdc.l $82000000+NonHandledInterrupt; trapdc.l $82000000+NonHandledInterrupt; irq0dc.l $82000000+NonHandledInterrupt; irq1dc.l $82000000+NonHandledInterrupt; irq2dc.
12、l $82000000+NonHandledInterrupt; irq3dc.l $82000000+NonHandledInterrupt; irq4dc.l $82000000+NonHandledInterrupt; irq5dc.l $82000000+NonHandledInterrupt; irq6dc.l $82000000+NonHandledInterrupt; irq7dc.l $82000000+NonHandledInterrupt; irq8dc.l $82000000+NonHandledInterrupt; irq9dc.l $82000000+NonHandl
13、edInterrupt; 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;
14、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 $82
15、000000+NonHandledInterrupt; irq25dc.l $82000000+NonHandledInterrupt; irq26dc.l $82000000+NonHandledInterrupt; irq27dc.l $82000000+NonHandledInterrupt; irq28dc.l $82000000+NonHandledInterrupt; irq29end把這個項目Build后,點擊Debug中的Start Debugging就可以將程序下載到ST的三合一板上了,然后點擊Run,程序就運行起來了,不過由于框架程序是一個空程序,初始化內(nèi)存后就進入死循環(huán)了
16、,因此什么效果也看不見。因此我們必須在框架程序的基礎(chǔ)上,編寫自己的程序。后面的程序例子都是在這個框架程序的基礎(chǔ)上編寫的。 STM8與匯編語言(4)今天要做的實驗是在ST的三合一開發(fā)板上,用匯編語言寫一個程序,驅(qū)動板上的LED指示燈閃爍。開發(fā)板上的LED1接在STM8的PD3上,因此要將PD3設(shè)置成輸出模式,為了提高高電平時的輸出電流,要將其設(shè)置成推挽輸出方式。這主要通過設(shè)置對應(yīng)的DDR/CR1/CR2寄存器實現(xiàn)。還是利用ST的開發(fā)工具,先生成一個匯編程序的框架,然后修改其中的main.asm,修改后的代碼如下。編譯通過后,下載到開發(fā)板,運行程序,可以看到LED1在閃爍,且閃爍的頻率為5HZ。s
17、tm8/ #include "mapping.inc" 下面定義端口D的寄存器地址PD_ODR EQU $500f PD_IDR EQU $5010PD_DDR EQU $5011 PD_CR1 EQU $5012PD_CR2 EQU $5013; 定義堆棧空間的起始位置和結(jié)束位置stack_start.w EQU $stack_segment_startstack_end.w EQU $stack_segment_end; 下面開始定義一個段,該段位于ROM中 segment 'rom' ; 定義復(fù)位后的第一條指令的標(biāo)號(即入口地址)main.l ; 首先
18、要初始化堆棧指針LDW X,#stack_end LDW SP,X LD A,#08LD PD_DDR,A ; 將PD3設(shè)置成輸出 LD A,#08 LD PD_CR1,A ; 將PD3設(shè)置成推挽輸出 LD A,#00 LD PD_CR2,A ;MAIN_LOOP.L LD A,#08 ; LD PD_ODR,A ; 將PD3的輸出設(shè)置成1 LD A,#100 CALL DELAY_MS ; 延時100MS LD A,#00 ; LD PD_ODR,A ; 將PD3的輸出設(shè)置成1 LD A,#100 CALL DELAY_MS ; 延時100MS JRA MAIN_LOOP ; ; 函數(shù)功能:
19、延時; 輸入?yún)?shù):寄存器A 要延時的毫秒數(shù),這里假設(shè)CPU的主頻為2MHZ; 輸出參數(shù):無; 返 回 值:無; 備 注:無DELAY_MS.L PUSH A ; 將入口參數(shù)保存到堆棧中 LD A,#250 ; 寄存器A<-250,作為下面的循環(huán)數(shù) DELAY_MS_1.L NOP ; 用空操作指令進行延時4T NOP NOP NOP NOP DEC A ; 寄存器A<-A-1,本條指令執(zhí)行之間為1T JRNE DELAY_MS_1 ; 若不等于0,則循環(huán), ; 本條指令執(zhí)行時間為2T(跳時)或1T(不跳時) POP A ; 從堆棧中恢復(fù)入口參數(shù) DEC A ; 將要延時的MS數(shù)1
20、JRNE DELAY_MS ; 若不等于0,則循環(huán)RET ; 函數(shù)返回 interrupt NonHandledInterruptNonHandledInterrupt.l iret; 下面定義中斷向量表 segment 'vectit' dc.l $82000000+main ; reset dc.l $82000000+NonHandledInterrupt ; trap dc.l $82000000+NonHandledInterrupt ; irq0 dc.l $82000000+NonHandledInterrupt ; irq1 dc.l $82000000+Non
21、HandledInterrupt ; 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+NonHandle
22、dInterrupt ; irq9 dc.l $82000000+NonHandledInterrupt ; irq10 dc.l $82000000+NonHandledInterrupt ; irq11 dc.l $82000000+NonHandledInterrupt ; irq12 dc.l $82000000+NonHandledInterrupt ; irq13 dc.l $82000000+NonHandledInterrupt ; irq14 dc.l $82000000+NonHandledInterrupt ; irq15 dc.l $82000000+NonHandle
23、dInterrupt ; irq16 dc.l $82000000+NonHandledInterrupt ; irq17 dc.l $82000000+NonHandledInterrupt ; irq18 dc.l $82000000+NonHandledInterrupt ; irq19 dc.l $82000000+NonHandledInterrupt ; irq20 dc.l $82000000+NonHandledInterrupt ; irq21 dc.l $82000000+NonHandledInterrupt ; irq22 dc.l $82000000+NonHandl
24、edInterrupt ; irq23 dc.l $82000000+NonHandledInterrupt ; irq24 dc.l $82000000+NonHandledInterrupt ; irq25 dc.l $82000000+NonHandledInterrupt ; irq26 dc.l $82000000+NonHandledInterrupt ; irq27 dc.l $82000000+NonHandledInterrupt ; irq28 dc.l $82000000+NonHandledInterrupt ; irq29endSTM8與匯編語言(5)上一次的實驗程序
25、,完成了LED指示燈的驅(qū)動,用到了GPIO的輸出方式,這一次要用GPIO的輸入方式,進行按鍵的輸入。下面的代碼是讀入按鍵值,如果按鍵按下,則點亮LED,否則熄滅LED。利用ST的開發(fā)工具,生成一個匯編程序的框架,然后修改其中的main.asm,修改后的代碼如下。編譯通過后,下載到開發(fā)板,運行程序,可以看到當(dāng)按下按鍵時,LED1點亮,當(dāng)抬起按鍵時,LED1熄滅。stm8/#include "mapping.inc" 涉及到的硬件資源; LED1定義在PD3; KEY1定義在PD7; 下面定義端口D的寄存器地址PD_ODR EQU $500f PD_IDR EQU $5010P
26、D_DDR EQU $5011 PD_CR1 EQU $5012PD_CR2 EQU $5013; 定義堆棧空間的起始位置和結(jié)束位置stack_start.w EQU $stack_segment_startstack_end.w EQU $stack_segment_end segment 'rom' ; 下面開始定義一個段,該段位于ROM中main.l ; 定義復(fù)位后的第一條指令的標(biāo)號(即入口地址); 首先要初始化堆棧指針 LDW X,#stack_end LDW SP,X; 下面初始化IO端口; PD3設(shè)置成推挽輸出; PD7設(shè)置成懸浮輸入LD A,#08LD PD_DD
27、R,A ; 將PD3設(shè)置成輸出,PD7設(shè)置成輸入LD A,#08LD PD_CR1,A ; 將PD3設(shè)置成推挽輸出LD A,#00LD PD_CR2,A ;MAIN_LOOP.L LD A,PD_IDR ; 讀入端口D的引腳輸入寄存器AND A,#$80 ; 測試最高位是否為1JRNE MAIN_LOOP_1 ; 若最高位為1,則跳轉(zhuǎn) LD A,#$08 ; 否則說明按鍵按下,PD3<-1,點亮LED1LD PD_ODR,A ; JRA MAIN_LOOPMAIN_LOOP_1.LLD A,#$00 ; 若按鍵沒按下,PD3<-0,熄滅LED1 LD PD_ODR,A ; JRA
28、MAIN_LOOP ; interrupt NonHandledInterruptNonHandledInterrupt.liret; 下面定義中斷向量表segment 'vectit'dc.l $82000000+main; resetdc.l $82000000+NonHandledInterrupt; trapdc.l $82000000+NonHandledInterrupt; irq0 dc.l $82000000+NonHandledInterrupt; irq1 dc.l $82000000+NonHandledInterrupt; irq2 dc.l $8200
29、0000+NonHandledInterrupt; irq3 dc.l $82000000+NonHandledInterrupt; irq4dc.l $82000000+NonHandledInterrupt; irq5 dc.l $82000000+NonHandledInterrupt; irq6 dc.l $82000000+NonHandledInterrupt; irq7 dc.l $82000000+NonHandledInterrupt; irq8 dc.l $82000000+NonHandledInterrupt; irq9 dc.l $82000000+NonHandle
30、dInterrupt; irq10 dc.l $82000000+NonHandledInterrupt; irq11 dc.l $82000000+NonHandledInterrupt; irq12 dc.l $82000000+NonHandledInterrupt; irq13 dc.l $82000000+NonHandledInterrupt; irq14 dc.l $82000000+NonHandledInterrupt; irq15 dc.l $82000000+NonHandledInterrupt; irq16 dc.l $82000000+NonHandledInter
31、rupt; irq17 dc.l $82000000+NonHandledInterrupt; irq18 dc.l $82000000+NonHandledInterrupt; irq19 dc.l $82000000+NonHandledInterrupt; irq20 dc.l $82000000+NonHandledInterrupt; irq21 dc.l $82000000+NonHandledInterrupt; irq22 dc.l $82000000+NonHandledInterrupt; irq23 dc.l $82000000+NonHandledInterrupt;
32、irq24 dc.l $82000000+NonHandledInterrupt; irq25 dc.l $82000000+NonHandledInterrupt; irq26 dc.l $82000000+NonHandledInterrupt; irq27 dc.l $82000000+NonHandledInterrupt; irq28dc.l $82000000+NonHandledInterrupt; irq29endSTM8與匯編語言(6)8位定時器應(yīng)用之一STM8單片機中的外設(shè)資源是比較豐富的,定時器有8位的也有16位的,下面的實驗程序,就是利用8位定時器4來進行延時,然后驅(qū)動
33、LED閃爍。同樣還是利用ST的開發(fā)工具,生成一個匯編程序的框架,然后修改其中的main.asm,修改后的代碼如下。編譯通過后,下載到開發(fā)板,運行程序,可以看到LED在閃爍,或者用示波器可以在LED引腳上看到方波。在這里要特別提醒的是,從ST給的手冊上看,這個定時器中的計數(shù)器是一個加1計數(shù)器,但本人在實驗過程中感覺不太對,經(jīng)過反復(fù)的實驗,我認(rèn)為應(yīng)該是一個減1計數(shù)器(也許是我拿的手冊不對,或許是理解上有誤)。例如,當(dāng)給定時器中的自動裝載寄存器裝入255時,產(chǎn)生的方波頻率最小,就象下面代碼中計算的那樣,產(chǎn)生的方波頻率為30HZ左右。若初始化時給自動裝載寄存器裝入1,則產(chǎn)生的方波頻率最大,大約為3.9
34、K左右。也就是說實際的分頻數(shù)為ARR寄存器的值+1。stm8/#include "mapping.inc"#include "STM8S207S8.INC" 涉及到的硬件資源; 下面定義端口D的寄存器地址PD_ODR EQU $500f PD_IDR EQU $5010PD_DDR EQU $5011 PD_CR1 EQU $5012PD_CR2 EQU $5013; 定時器4的寄存器定義TIM4_CR1 EQU $5340TIM4_IER EQU $5341TIM4_SR EQU $5342TIM4_EGR EQU $5343TIM4_CNTR EQU
35、 $5344TIM4_PSCR EQU $5345TIM4_ARR EQU $5346; 定義堆??臻g的起始位置和結(jié)束位置stack_start.w EQU $stack_segment_startstack_end.w EQU $stack_segment_end segment 'rom' ; 下面開始定義一個段,該段位于ROM中main.l ; 定義復(fù)位后的第一條指令的標(biāo)號(即入口地址); 首先要初始化堆棧指針 LDW X,#stack_end LDW SP,X; 下面初始化IO端口; PD3設(shè)置成推挽輸出; PD7設(shè)置成懸浮輸入LD A,#08LD PD_DDR,A ;
36、 將PD3設(shè)置成輸出,PD7設(shè)置成輸入LD A,#08LD PD_CR1,A ; 將PD3設(shè)置成推挽輸出LD A,#00LD PD_CR2,A ; 下面初始化定時器4LD A,#$00LD TIM4_IER,A ; 禁止中斷LD A,#$01 LD TIM4_EGR,A ; 允許產(chǎn)生更新事件LD A,#$07LD TIM4_PSCR,A ; 計數(shù)器時鐘=主時鐘/128=2MHZ/128 ; 相當(dāng)于計數(shù)器周期為64uSLD A,#255LD TIM4_ARR,A ; 設(shè)定重裝載時的寄存器值,255是最大值LD A,#255LD TIM4_CNTR,A ; 設(shè)定計數(shù)器的初值 ; 定時周期=(ARR
37、+1)*64=16384uS ; 產(chǎn)生方波頻率=30.5HZLD A,#$01 ; b0 = 1,允許計數(shù)器工作; b1 = 0,允許更新LD TIM4_CR1,A ; 設(shè)置控制器,啟動定時器MAIN_LOOP.LLD A,TIM4_SR ; 讀入定時器4的狀態(tài)AND A,#01 ; 判斷是否產(chǎn)生更新標(biāo)志 JREQ MAIN_LOOP ; 若沒有,則等待 LD A,#0 ; 清除更新標(biāo)志 LD TIM4_SR,A LD A,PD_ODR ; 將LED驅(qū)動信號取反XOR A,#$08LD PD_ODR,A ; LED閃爍頻率=2MHZ/128/255/2=30.63JRA MAIN_LOOP ;
38、 無限循環(huán) interrupt NonHandledInterruptNonHandledInterrupt.liret; 下面定義中斷向量表 segment 'vectit' dc.l $82000000+main; reset dc.l $82000000+NonHandledInterrupt; trap dc.l $82000000+NonHandledInterrupt; irq0 dc.l $82000000+NonHandledInterrupt; irq1 dc.l $82000000+NonHandledInterrupt; irq2 dc.l $820000
39、00+NonHandledInterrupt; irq3 dc.l $82000000+NonHandledInterrupt; irq4dc.l $82000000+NonHandledInterrupt; irq5 dc.l $82000000+NonHandledInterrupt; irq6 dc.l $82000000+NonHandledInterrupt; irq7 dc.l $82000000+NonHandledInterrupt; irq8 dc.l $82000000+NonHandledInterrupt; irq9 dc.l $82000000+NonHandledI
40、nterrupt; irq10 dc.l $82000000+NonHandledInterrupt; irq11 dc.l $82000000+NonHandledInterrupt; irq12 dc.l $82000000+NonHandledInterrupt; irq13 dc.l $82000000+NonHandledInterrupt; irq14 dc.l $82000000+NonHandledInterrupt; irq15 dc.l $82000000+NonHandledInterrupt; irq16 dc.l $82000000+NonHandledInterru
41、pt; irq17 dc.l $82000000+NonHandledInterrupt; irq18 dc.l $82000000+NonHandledInterrupt; irq19 dc.l $82000000+NonHandledInterrupt; irq20 dc.l $82000000+NonHandledInterrupt; irq21 dc.l $82000000+NonHandledInterrupt; irq22 dc.l $82000000+NonHandledInterrupt; irq23 dc.l $82000000+NonHandledInterrupt; ir
42、q24 dc.l $82000000+NonHandledInterrupt; irq25 dc.l $82000000+NonHandledInterrupt; irq26 dc.l $82000000+NonHandledInterrupt; irq27 dc.l $82000000+NonHandledInterrupt; irq28dc.l $82000000+NonHandledInterrupt; irq29endSTM8與匯編語言(7)8位定時器應(yīng)用之二上次寫的是用STM8單片機中的8位定時器作為軟件延時,采用的是查詢方式。在實際系統(tǒng)中,定時器的應(yīng)用,更多的是采用中斷方式,下面的
43、代碼就給出8位定時器在中斷方式下的應(yīng)用。實驗程序首先初始化驅(qū)動LED的端口,然后初始化8位的定時器4,最后啟動中斷允許,要記住,一定要將中斷服務(wù)程序的入口地址填寫到中斷向量表中,并且要根據(jù)中斷向量號在正確的位置上填寫。同樣還是利用ST的開發(fā)工具,生成一個匯編程序的框架,然后修改其中的main.asm,修改后的代碼如下。編譯通過后,下載到開發(fā)板,運行程序,可以看到LED在閃爍,或者用示波器可以在LED引腳上看到方波。stm8/#include "mapping.inc"#include "STM8S207S8.INC" 涉及到的硬件資源; LED1定義在P
44、D3; 下面定義端口D的寄存器地址PD_ODR EQU $500f PD_IDR EQU $5010PD_DDR EQU $5011 PD_CR1 EQU $5012PD_CR2 EQU $5013; 定時器4的寄存器定義TIM4_CR1 EQU $5340TIM4_IER EQU $5341TIM4_SR EQU $5342TIM4_EGR EQU $5343TIM4_CNTR EQU $5344TIM4_PSCR EQU $5345TIM4_ARR EQU $5346; 定義堆??臻g的起始位置和結(jié)束位置stack_start.w EQU $stack_segment_startstack_
45、end.w EQU $stack_segment_endsegment 'rom' ; 下面開始定義一個段,該段位于ROM中main.l ; 定義復(fù)位后的第一條指令的標(biāo)號(即入口地址); 首先要初始化堆棧指針 LDW X,#stack_end LDW SP,X; 下面初始化IO端口; PD3設(shè)置成推挽輸出; PD7設(shè)置成懸浮輸入 LD A,#08 LD PD_DDR,A ; 將PD3設(shè)置成輸出,PD7設(shè)置成輸入 LD A,#08LD PD_CR1,A ; 將PD3設(shè)置成推挽輸出 LD A,#00LD PD_CR2,A ; 下面初始化定時器4LD A,#$01 LD TIM4_EGR,A ; 允許產(chǎn)生更新事件LD A,#$07LD TIM4_PSCR,A ; 計數(shù)器時鐘=主時鐘/128=2MHZ/128 ; 相當(dāng)于計數(shù)器周期為64uSLD A,#255LD TIM4_ARR,A ; 設(shè)定重裝載時的寄存器值,255是最大值LD A,#255LD TIM4_CNTR,A ; 設(shè)定計數(shù)器的初值 ; 定時周期=(255+1)*64=16384uSLD A,#$01 ; b0 = 1,允許計數(shù)器工作 ; b1 = 0,允許更新LD TI
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024-2030年中國地理書籍行業(yè)市場運營模式及未來發(fā)展動向預(yù)測報告
- 2024-2030年中國園林古建筑行業(yè)發(fā)展前景規(guī)劃研究報告
- 2024-2030年中國周界報警系統(tǒng)行業(yè)運營模式及發(fā)展戰(zhàn)略分析報告
- 2024-2030年中國衛(wèi)生潔凈器行業(yè)供需狀況發(fā)展戰(zhàn)略規(guī)劃分析報告
- 2024年生態(tài)保育合同范本
- 2024年環(huán)保裝修材料購買協(xié)議3篇
- 微專題構(gòu)建模型解讀新信息-2024高考化學(xué)一輪考點擊破
- 呂梁職業(yè)技術(shù)學(xué)院《體操類》2023-2024學(xué)年第一學(xué)期期末試卷
- 2024年樣品提供協(xié)議范本下載版B版
- 2024年某企業(yè)與保險公司關(guān)于企業(yè)財產(chǎn)保險合同
- 國家公務(wù)員考試(面試)試題及解答參考(2024年)
- 火電廠電氣值班員培訓(xùn)
- 導(dǎo)尿管相關(guān)尿路感染預(yù)防與控制技術(shù)指南-3
- 2024年人教版八年級數(shù)學(xué)上冊期末考試卷(附答案)
- 【浙江卷】浙江省2024學(xué)年第一學(xué)期杭州市2025屆高三年級教學(xué)質(zhì)量檢測(杭州一模)(11.4-11.6)歷史試卷答案
- 國開(浙江)2024年秋《中國建筑史(本)》形考作業(yè)1-4答案
- 北京工業(yè)大學(xué)《數(shù)學(xué)模型》2022-2023學(xué)年第一學(xué)期期末試卷
- 部編版語文五年級上冊《父愛之舟》說課
- 大學(xué)生思想道德與法治課件
- 《個人防守技術(shù):搶、斷球技術(shù)》教案
- 2024版成人術(shù)中非計劃低體溫預(yù)防與護理培訓(xùn)課件
評論
0/150
提交評論