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口寄存器。

你可能感兴趣的:(ARM)