ARM 裸機程序學習 02 - 按響BEEP


第二個示例程序:按響BEEP

這次的程序主要練習ARM的GPIO口的輸入功能,並以此來按響BEEP。

比較嚴密的說法應該是:按了按鍵,然后CPU得知,然后CPU再輸出相應的內容。

所以過程很簡單,程序不斷地讀取GPIO口的值,當發現有不同輸入的時候,做出相應的反應。

 

硬件環境:

w3c2440,GPF0,2,3,4接4個按鍵。並且接上拉電阻。  //我一直在想,GPF口本身自帶上拉電阻,如果不接上拉電阻應該也行。

當某一個鍵按下的時候,對應的GPF口數據位輸入0。沒有按下的時候,依靠上拉電阻輸入1。

BEEP接三極管的集電極,GPB0口接基極,發射極接地  //簡單得說,就是三極管當做開關,GPB0輸出1就接通BEEP。電子方面有謬誤還請指出來。

 

匯編代碼:

 

 1     AREA BEEPSAMPLE,CODE,READONLY
 2     ENTRY
 3     
 4     LDR R1, =0x56000058        ;GPFUP_addr
 5     MOV R2, #0x000000FF        ;GPFUP_value=disable
 6     STR R2, [R1]
 7     
 8     LDR R1, =0x56000018        ;GPBUP_addr
 9     LDR R2, =0x00000FFF        ;GPBUP_value=disable
10     STR R2, [R1]
11     
12     LDR R1, =0x56000050        ;GPFCON_addr
13     LDR R2, =0x0000FC0C        ;GPFCON(0,2,3,4)_value=input
14     STR R2, [R1]
15     
16     LDR R2, =0x56000014        ;GPBDAT_addr
17     
18     LDR R3, =0x56000010        ;GPBCON_addr
19     LDR R4, =0x00FFFFFD        ;GPBCON(0)_value=output
20     STR R4, [R3]
21     
22 START
23     LDR R5, =0x56000054        ;GPFDAT_addr
24     LDR R6, [R5]         ;read GPFDAT
25     ORR R6, R6, #0xE2
26     
27     CMP R6, #0xFF
28     BEQ BEEPDOWN
29     
30 BEEPUP
31     LDR R7, =0xFFF
32     STR R7, [R2]            ;set GPBDAT(0), output=1
33     B START
34     
35 BEEPDOWN
36     LDR R6, =0xFFE
37     STR R6, [R2]            ;set GPBDAT(1), output=0
38     B START
39     
40     END

注解及筆記:

04~10:禁止GPF,GPB的上拉電阻

12~20:配置GPF口,功能設置為輸入。而GPB口則設置為輸出

23~24:讀取GPF口的值。

  在這里,23行的LDR是一條偽指令,而24的LDR才是真正的ARM指令而非偽指令。

  23行:把內存GPF的內存地址存入R5(偽指令:把一個“常量”存到寄存器)

  24行:從內存地址 0x56000054 (保存在R5中的地址)處讀取數據,存入R6(ARM指令:從內存傳輸數據到寄存器)

25:將讀取到的值(保存在R6)和(1110 0010)做或運算。

  這樣做的目的是簡化操作,把GPF0,2,3,4以外的數據位都設置為1,方便比較。

27:CMP比較指令。比較兩個數,並設置相關CPSR(程序狀態寄存器)的相關標志位。

  標志位相對復雜,現階段暫且不深究。

  簡單得說,通過CMP比較並設置相關標志位后,指令可以通過條件碼選擇執行:

  EQ:當(剛才的比較)相等時執行;  NE:當不相等時執行。

28:BEQ,就是 B (跳轉指令)+ EQ(條件碼:相等時執行)。

  連起來就是當相等時執行跳轉。

30~33:打開BEEP。

  方法很簡單,就是向GPB0輸出1而已。

  輸出結束后跳回檢測GPF輸入值的代碼段(START)

35~38:關閉BEEP。

  向GPB0輸出0。

 

注意點:

1:GPF口是一個0位口,所以讀到的數據也就是8位二進制,所以CMP對比的時候和0xFF對比即可。

2:匯編和高級編程語言不同,不能像C一樣直接對某個IO口寄存器賦值(比如:GPB=0xFFF)

  必須要分三步:載入IO口寄存器地址,載入需要輸出的數據,通過LDR將數據送入IO口寄存器。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM