先导知识
汇编语言:
;加载寄存器
ldr r0,=0x40021018 ;这是内存地址
ldr r1,[r0] ; r1 = *r0 将r0的值赋值给r1
orr r1, r1, #0x10 ;将第4位置1(从0开始的哦)
bic r1, r1, #0xf ;将低4位清0
str r1, [r0] ;将r1的值写入r0这个地址 *r1 = r0
blx lr ;函数返回 return
;CBNZ
mov r0, #0
cbnz r1, KEY2_press ;当r1不等于0的时候跳转到KEY2_press
nop ;r1==0 跳到这儿
KEY2_press
nop
eor r1, r1,#0x800 ;异或操作 即可让灯翻转
mov r1, #3
mov r2, #5
and r3, r1, r2 ;r3 = r1 & r2 结果是5
如何在C代码中调用汇编呢?
main.c
//导入汇编的函数
extern void led_init(void);
int main(){
led_init(); //这是汇编函数
return 0;
}
asm.s
;这句话一定不要顶格写
AREA My_Function,CODE,READONLY
;要被C调用的函数 都需要声明EXPORT
EXPORT led_init
;对应的汇编函数
led_init
mov r0, #0xff
blx lr
C语言又是如何向汇编代码传参的呢?
r0-r3会接收C语言的参数,超过四个参数的自己想办法
如何找寄存器?
我以前写过,这里不写了
汇编实现按键点灯
main.c
#include "gd32c10x.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "gd32c10x_eval.h"
void led_spark(void)
{
static __IO uint32_t timingdelaylocal = 0U;
if(timingdelaylocal){
if(timingdelaylocal < 500U){
//gd_eval_led_on(LED2);
}else{
//gd_eval_led_off(LED2);
}
timingdelaylocal--;
}else{
timingdelaylocal = 1000U;
}
}
/**********上面代码不重要,下面才是重点********************/
extern void led_init(void);
extern void led_on(int led_num);
extern void led_off(int led_num);
extern void key_init(void);
extern void key1_scan(void); //这是4个按键都会检测
/*led灯的枚举定义*/
typedef enum
{
led1 = 0,
led2 = 1,
led3 = 2,
led0 = 3
}LED;
int main(void)
{
//所有灯的初始化
led_init();
//关闭灯
led_off(led1);
led_off(led2);
led_off(led3);
led_off(led0);
//按键初始化
key_init();
while(1){
key1_scan();
}
}
led_asm.s
AREA My_Function,CODE,READONLY
;要被C调用的函数 都需要声明EXPORT
EXPORT led_init
EXPORT led_on
EXPORT led_off
EXPORT key_init
EXPORT key1_scan
led_init
;时钟使能
ldr r0,=0x40021018
ldr r1, [r0]
orr r1, r1, #0x10 ;C口时钟
orr r1, r1, #0x1 ;AFIO端口时钟
orr r1, r1, #0x4 ;A口端口时钟
str r1, [r0]
;LED0 pA15需要关闭JTAG 打开SWJ使能
ldr r2,=0x40010004
ldr r3, [r2]
orr r3, r3, #0x1
bic r3, r3, #0x7000000
orr r3, r3, #0x2000000
str r3, [r2]
;led1的初始化
;GPIOC控制寄存器 0x40011004
;推挽输出 10MHZ 8~11为清0 再变成0x1
;GPIOC_CON &= ~(0xf<<8); //清0 [8:11]
;GPIOC_CON |= (0x1<<8); //清0后把最后一位置1
;推挽输出 10MHZ
ldr r2,=0x40011004
ldr r3, [r2] ;r3 = *r2
;LED1
bic r3, r3, #0xf00
orr r3, r3, #0x100
;LED2
bic r3, r3, #0xf000
orr r3, r3, #0x1000
;LED3
bic r3, r3, #0xf0000
orr r3, r3, #0x10000
str r3, [r2] ; *r2 = r3
;LED0初始化 推挽输出 10MHZ
ldr r2,=0x40010804
ldr r3, [r2]
bic r3, r3, #0xf0000000
orr r3, r3, #0x10000000
str r3, [r2]
;让LD0亮起来,其他灯初始化后就会亮,这个不会
ldr r2,=0x4001080C
ldr r3, [r2]
bic r3, r3, #0x8000
str r3, [r2]
blx lr
led_on
cmp r0, #0
beq LED1_on
cmp r0, #1
beq LED2_on
cmp r0, #2
beq LED3_on
cmp r0, #3
beq LED0_on
led_off
cmp r0, #0
beq LED1_off
cmp r0, #1
beq LED2_off
cmp r0, #2
beq LED3_off
cmp r0, #3
beq LED0_off
;led灯熄灭的跳转
LED0_off
ldr r2,=0x4001080C
ldr r1, [r2]
orr r1, r1, #0x8000
str r1, [r2]
blx lr
LED1_off
ldr r2,=0x4001100c
ldr r1, [r2]
orr r1, r1,#0x400
str r1, [r2]
blx lr
LED2_off
ldr r2,=0x4001100c
ldr r1, [r2]
orr r1, r1,#0x800
str r1, [r2]
blx lr
LED3_off
ldr r2,=0x4001100c
ldr r1, [r2]
orr r1, r1,#0x1000
str r1, [r2]
blx lr
;led灯亮的跳转
LED0_on
ldr r2,=0x4001100c
ldr r1, [r2]
ldr r2,=0x4001080C
ldr r1, [r2]
bic r1, r1, #0x8000
str r1, [r2]
blx lr
LED1_on
ldr r2,=0x4001100c
ldr r1, [r2]
bic r1, r1,#0x400
str r1, [r2]
blx lr
LED2_on
ldr r2,=0x4001100c
ldr r1, [r2]
bic r1, r1,#0x800
str r1, [r2]
blx lr
LED3_on
ldr r2,=0x4001100c
ldr r1, [r2]
bic r1, r1,#0x1000
str r1, [r2]
blx lr
;按键初始化
key_init
ldr r0,=0x40021018
ldr r1, [r0]
orr r1, r1, #0x8 ;B口端口时钟
str r1, [r0]
;KEY1 KEY2 KEY3 KEY4的配置 悬浮输入
ldr r0,=0x40010C04
ldr r1,[r0]
bic r1, r1, #0xf0000
orr r1, r1, #0x40000
bic r1, r1, #0xf00000
orr r1, r1, #0x400000
bic r1, r1, #0xf000000
orr r1, r1, #0x4000000
bic r1, r1, #0xf0000000
orr r1, r1, #0x40000000
str r1, [r0]
blx lr
;按键检测
key1_scan
ldr r0,=0x40010C08
ldr r1,[r0]
and r2, r1, #0x1000
cbnz r2, KEY2_scan ;结果非0跳转KEY2_scan
ldr r2,=0x4001100c
ldr r1, [r2]
eor r1, r1,#0x400 ;r1的第10位置
str r1, [r2]
blx lr
KEY2_scan
ldr r0,=0x40010C08
ldr r1,[r0]
and r2, r1, #0x2000
cbnz r2, KEY3_scan
ldr r2,=0x4001100c
ldr r1, [r2]
eor r1, r1,#0x800
str r1, [r2]
blx lr
KEY3_scan
ldr r0,=0x40010C08
ldr r1,[r0]
and r2, r1, #0x4000
cbnz r2, KEY4_scan
ldr r2,=0x4001100c
ldr r1, [r2]
eor r1, r1,#0x1000
str r1, [r2]
blx lr
KEY4_scan
ldr r0,=0x40010C08
ldr r1,[r0]
and r2, r1, #0x8000
cbnz r2, KEY_end
ldr r2,=0x4001100c
ldr r1, [r2]
ldr r2,=0x4001080C
ldr r1, [r2]
eor r1, r1, #0x8000
str r1, [r2]
blx lr
KEY_end
blx lr
总结
汇编代码if else有点挑战,还需要对各种寄存器比较熟悉,比如pc,lr这些。
如何去找寄存器这些都要对硬件有一定了解才行。
灯已电亮,按键也能按下进行电平翻转,用到异或操作。
汇编代码的清0和置1、异或等操作非常方便。
汇编代码全程都是在操作寄存器哦。