zoukankan      html  css  js  c++  java
  • 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口寄存器。

    /*
     * Yiling Zhou
     * Shanghai, China
     * -.-- .. .-.. .. -. --. / --.. .... --- ..-
     * ... .... .- -. --. .... .- .. --..-- / -.-. .... .. -. .-
     */
    
  • 相关阅读:
    django目录
    django之form表单验证
    django操作数据库之查询F,Q操作 和 seach搜索功能
    django的序列化
    三目运算
    【转】做有生命力的接口测试
    【转】浅谈反应测试
    【转】jmeter 进行java request测试
    【转】探索式测试:基本概念
    【转】 测试职业思考:如何成为一名优秀的软件测试工程师
  • 原文地址:https://www.cnblogs.com/pastgift/p/2465873.html
Copyright © 2011-2022 走看看