void _start(void)
{
// 灯设置成输出
GPIOEALTFN0 &= ~(3<<(13*2)); //function0--GPIOE13
GPIOEOUTENB |= (1<<13);//GPIOE13--OUTOPUT
// 按键设置成输入
GPIOAALTFN1 &= ~(3<<((28-16)*2)); //function0--GPIOA28
GPIOAOUTENB &= ~(1<<28);//GPIOA28--INPUT
while(1)
{
if(! (GPIOAPAD&(0x01<<28))) // 真就表示读到低电平,按下
{
delay(0x40000); //消抖
if(! (GPIOAPAD&(0x01<<28)))
GPIOEOUT &= ~(1<<13);//GPIOE13 output 0
}
else
GPIOEOUT |= (1<<13);//GPIOE13 output 1
}
}
void delay(int val)
{
volatile int i=val;
while(i--);
}
.global _start // 全局变量定义
_start:
LDR R0, =0XC001E020 // 将0XC001E020作为地址赋给R0
LDR R1, [R0] //将R0即地址0XC001E020的内容赋给R1
BIC R1, R1, #(3<<26) //R1=R1 & ~(3<<26),因为BIC自动取反
STR R1,[R0] //将R1存储到地址0xC001E020
LDR R0, =0xC001E004 // 设置成输出
LDR R1, [R0]
ORR R1, R1, #(1<<13);
STR R1,[R0];
_loop: // 循环
LDR R0 , =0xC001E000 // 设置输出值
LDR R1, [R0]
BIC R1 , R1,#0X2000 // (1<<13) 与操作,设置为0 灯亮
STR R1,[R0];
bl _delay // 执行延时函数
LDR R1, [R0]
ORR R1 , R1,#0X2000 // (1<<13) 或操作,设置为1 灯灭
STR R1,[R0];
bl _delay // 执行延时函数
b _loop // 继续循环
_delay:
MOV R4, #0x4000000
d_loop:
subs R4,R4,#1
cmp R4,#0
bne d_loop
mov pc , lr
1)文件的后缀是大写的S,小写的.s编译会不过的(编译环境ubuntu18.04 arm-linux-gcc)
2)mov PC ,LR ---- 相当于子函数调用返回return
3)代码块可以直接用 name: 表示
4)对于_start 函数入口,需要在文件头定义成全局变量
.global _start // 全局变量定义
5)LDR和MOV 的区别
LDR 是ARM指令集中的
.LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器;
若加载的常数未超出 MOV 或 MVN 的范围,则使用 MOV 或 MVN 指令代替该 LDR 伪指令
MOV 是 16位的;
数据传送指令.将 8 位立即数或寄存器(operand2)传送到目标寄存器(Rd)
6)BIC 和 AND 的区别
BIC 会把对应位先取反再相与
位清除指令.将寄存器Rn的值与operand2的值的反码按位作逻辑与操作,结果保存到 Rd 中.指令格式如下:
BIC{cond}{S}Rd,Rn,operand2
BIC R1,R1,#0x0F ;将 R1 的低 4 位清零,其它位不变
AND 直接和对应数相与
逻辑与操作指令.将 operand2 值与寄存器 Rn 的值按位作逻辑与操作,结果保存到Rd 中.指令格式如下:
AND{cond}{S} Rd,Rn,operand2
ANDS R0R0#x01 ;R0=R0&0x01取出最低位数据
7)STR 的作用
STR Rd,addressing 存储字数据 [addressing]←Rd,addressing 索引 STR{cond}
;STR 指令用于将寄存器中的数据保存到内存(存储器地址).
8)BL和B的区别
B 跳转指令.跳转到指定的地址执行程,不能返回,使用于循环操作
BL带链接的跳转指令.指令将下一条指令的地址拷贝到 R14(即 LR)链接寄存器中,然后跳转到指定地址运行程序.可以用mov PC , LR 返回到调用处