一步步点亮LED之汇编点亮LED

GPJ0CON端口一共有8个端口,分别记住:GPJ0_0~GPJ0_7;相关寄存器为GPJ0CON、GPJ0DAT

GPJ0CON寄存器中设置8个引脚的工作模式(32/8=4,每个引脚分到4位,譬如GPJ0_0位bit0~bit3,我们就给=它写入0001得到输出模式)

1、需要控制的引脚:GPJ0_3、GPJ0_4、GPJ0_5低电平亮,高电平灭。

2、GPJ0CON(0xE0200240):控制模式      

  GPJ0DAT(0xE0200244):控制引脚数据

注意:由于IO与内存统一编址,所以不能直接往寄存器写入值,我们应该用指针的方式访问对应的地址间接写入。

将led灯全部点亮

/*
*文件名:led.S
*作者:***
*描述:这是我们一步步点亮led灯的第一个led程序
*
*/

_start:
    //第一步:把0x11111111写入0xE0200240(GPJOCON)位置
    ldr r0, =0x11111111        //从后面的=号可以看出来是伪指令,因为需要编译器来判
    ldr r1, =0xE0200240        //定是合法立即数还是非法立即数,一般都是ldr伪指令
    str r0, [r1]            //把r0中的数写入r1为地址的内存中去

    //第二步:把0x0写入0xE0200244(GPJ0DAT)
    ldr r0, =0x0
    ldr r1, =0xE0200244
    str r0, [r1]            //把0写入r1(0xE0200244)中

b .
//写了一个死循环。逐行运行裸机程序直到断电

编译后得到led.bin烧录到裸机中,就可以点亮led。

下面开始改进上述代码

1、增加可读性

由于上述代码可读性较差,过度依赖注释,下面需要改进代码,虽然可能增加代码复杂度,但是可读性增强

(1)运用宏定义,把对应的内存地址和GPIO名字绑定

(2)运用位操作,只亮中间一个灯(位操作便于直观看出哪位改动了)

#define GPJ0C0N 0xE0200240
#define GPJ0DAT 0xE0200244
.global _start
_start:
    //第一步:把0x11111111写入0xE0200240(GPJOCON)位置
    ldr r0, =0x11111111        //从后面的=号可以看出来是伪指令,因为需要编译器来判
    ldr r1, =GPJ0C0N         //定是合法立即数还是非法立即数,一般都是ldr伪指令
    str r0, [r1]            //把r0中的数写入r1为地址的内存中去

    //第二步:把0x0写入0xE0200244(GPJ0DAT)
    ldr r0, =(0x0)|(1<<3)|(0<<4)|(1<<5)  
    ldr r1, =GPJ0DAT
    str r0, [r1]            //把0写入r1(0xE0200244)中
    
b .                            //写了一个死循环。逐行运行裸机程序直到断电

2、led流水灯效果

(1)加入延时代码

(2)加入循环

#define GPJ0C0N 0xE0200240
#define GPJ0DAT 0xE0200244
.global _start
_start:
    //第一步:把0x11111111写入0xE0200240(GPJOCON)位置
    ldr r0, =0x11111111        //从后面的=号可以看出来是伪指令,因为需要编译器来判
    ldr r1, =GPJ0C0N         //定是合法立即数还是非法立即数,一般都是ldr伪指令
    str r0, [r1]            //把r0中的数写入r1为地址的内存中去
flash:
    //第二步:闪烁效果
    //点亮第一个灯,延时
    ldr r0, =(0<<3)|(1<<4)|(1<<5)
    ldr r1, =GPJ0DAT
    str r0, [r1]            //把0写入r1(0xE0200244)中
    bl delay
    //熄灭,延时
    ldr r0, =(1<<3)|(1<<4)|(1<<5)
    ldr r1, =GPJ0DAT
    str r0, [r1]            //把0写入r1(0xE0200244)中
    bl delay
    
    //点亮第二个灯,延时
    ldr r0, =(1<<3)|(0<<4)|(1<<5)
    ldr r1, =GPJ0DAT
    str r0, [r1]            //把0写入r1(0xE0200244)中
    bl delay
    //熄灭,延时
    ldr r0, =(1<<3)|(1<<4)|(1<<5)
    ldr r1, =GPJ0DAT
    str r0, [r1]            //把0写入r1(0xE0200244)中
    bl delay
    
    //点亮第三个灯,延时
    ldr r0, =(1<<3)|(1<<4)|(0<<5)
    ldr r1, =GPJ0DAT
    str r0, [r1]            //把0写入r1(0xE0200244)中
    bl delay
    //熄灭,延时
    ldr r0, =(1<<3)|(1<<4)|(1<<5)
    ldr r1, =GPJ0DAT
    str r0, [r1]            //把0写入r1(0xE0200244)中
    bl delay
    b flash
    
b .                        //写了一个死循环。逐行运行裸机程序直到断电(由于上一行有循环,这行根本不会执行,也可以删掉)


delay: ldr r2, =900000 ldr r3, =0x0 delay_loop: sub r2, r2, #1 cmp r2, r3 //cmp会影响Z标志位,如果r2=r3则Z等于1,下一句eq就会成立 bne delay_loop mov pc, lr
原文地址:https://www.cnblogs.com/jxjl/p/6958656.html