ARM-Key按键实验
-
一、查看原理图
-
二、查看芯片手册
-
三、操作GPIO
-
四、编写代码
-
在exynos_4412.h中有这款芯片所有的寄存器地址,可以通过查找得到对应结构体
-
typedef struct { unsigned int CON; unsigned int DAT; unsigned int PUD; unsigned int DRV; }gpx1; #define GPX1 (*(volatile gpx1 *)0x11000C20)
-
-
#define GPX1 (*(volatile gpx1 *)0x11000C20)
-
//key.c #include "exynos_4412.h" #include "exynos_setup.h" extern void led_init(int num); extern void led_on(int num); extern void led_off(int num); //GPX1_1:GPX1的第1个引脚(每个引脚4位)K2 //按键K2初始化 void key2_init(void) { #if 0 GPX1.CON = GPX1.CON & ~(0xf << 4); //将GPX1CON寄存器[7,4]位清0 GPX1.CON = GPX1.CON | (0x0 << 4); //将GPX1CON寄存器[7,4]赋值0x0设置输入模式 #endif SET_GPIO_MODE(GPX1.CON, 1, 0x0); //等价于if和endif之间的语句 return ; } //读取按键K2状态 int read_key2(void) { return GPX1.DAT & (0x1 << 1); //将GPX1DAT寄存器[7,0]第1位的值返回(1:抬起高电平或0:按下低电平) } //延迟函数(单位:ms) void delay_ms(int ms) { int i = 0, j = 0; while(ms--) { for(i = 0; i < 5; i++) { for(j = 0; j < 514; j++) { ; } } } return ; } //key测试 void key_test(void) { /*按下按键灯点亮、松开按键灯熄灭 key2_init(); led_init(3); //初始化LED5 while (1) { if (read_key2() == 0) //按下按键LED5点亮 { led_on(3); } else //松开按键LED5熄灭 { led_off(3); } } */ //按下按键灯点亮,再次按下按键灯熄灭 key2_init(); led_init(0); //初始化LED2 int flag = 0; //设置用户按下次数的标志位,奇数次亮,偶数次灭 while (1) { //用户按下了K2按键 if(read_key2() == 0) { delay_ms(5); //等待5ms //用户按下还没有松开 if(read_key2() == 0) { if(flag == 0) //第基数次按下 { led_on(0); flag = 1; //更新标志位 } else //第偶数次按下 { led_off(0); flag = 0; //更新标志位 } while(read_key2() == 0) //用户一直按下没有松开 { ; } delay_ms(5); //等待5ms } } } return ; }
-
//led.c #define DAT_OFFSET 4 struct led_des{ int pin; //引脚 int addr; //寄存器起始地址 }; struct led_des leds[] = { {7,0x11000c40}, //0 LED2 {0,0x11000c20}, //1 LED3 {4,0x114001E0}, //2 LED4 {5,0x114001E0}, //3 LED5 }; void led_init(int num) { //设置为输出工作模式 int *p; //传入参数的合法性 if(num < 0 || num > 3){ return; } p = (int *)leds[num].addr; *p = *p & ~(0xf << (4 * leds[num].pin)); *p = *p | (0x1 << (4 * leds[num].pin)); return; } void led_on(int num) { //输出高电平 int *p; if(num < 0 || num > 3){ return; } p = (int *)(leds[num].addr + DAT_OFFSET); *p = *p | (1 << leds[num].pin); return; } void led_off(int num) { //输出低电平 int *p; if(num < 0 || num > 3){ return; } p = (int *)(leds[num].addr + DAT_OFFSET); *p = *p & ~(1 << leds[num].pin); return; } void delay_time(int time) { int i,j; for(i = 0;i < 100 * time;i ++){ for(j = 0;j < 5000;j ++){ } } } void water_flower_led(int n) { int i; for(i = 0;i < n;i ++){ led_init(i); } while(1){ for(i = 0;i < n;i ++){ led_on(i); delay_time(1); led_off(i); delay_time(1); } } }
-
//start.s .global _start _start: b reset ldr pc,_undefined_instruction @ B undefined_instruction ldr pc,_software_interrupt @ B software_interrupt ldr pc,_prefetch_abort @ B prefetch_abort ldr pc,_data_abort @ B data_abort ldr pc,_not_used @ B not_used ldr pc,_irq @ B irq ldr pc,_fiq @ B fiq @ 异常向量表 _undefined_instruction:.word _undefined_instruction @ 未定义异常 _software_interrupt:.word software_interrupt @ 软件中断异常 _prefetch_abort:.word _prefetch_abort @ 取指令中止异常 _data_abort:.word _data_abort @ 取数据中止异常 _not_used:.word _not_used @ 未使用异常 _irq:.word irq @ 一般中断异常 _fiq:.word _fiq @ 快速中断异常 reset: @告诉ARM核异常向量表所在的基地址 adr r0,_start @获得异常向量表所在的地址 mcr p15,0,r0,c12, c0, 0 @将异常向量表的基地址写入cp15协处理器的寄存器c12 ldr sp,=0x40008000 bl main stop: b stop software_interrupt: ldr sp,=0x40009000 stmfd sp!,{r0-r12,lr} ldr r0,[lr,#-4] mov r1,#0xff bic r0,r0,r1,lsl #24 ldmfd sp!,{r0-r12,pc}^ irq: ldr sp,=0x40010000 sub lr,lr,#4 stmfd sp!,{r0-r12,lr} ldmfd sp!,{r0-r12,pc}^
-
//Config.mk COBJECTS += driver/led.o COBJECTS += driver/key.o
-
//main.c extern void key_test(void); int main(void) { key_test(); return 0; }
-
//Makefile CROSS_COMPILE = arm-none-eabi- GCC = $(CROSS_COMPILE)gcc LOAD = $(CROSS_COMPILE)ld OBJECTCOPY = $(CROSS_COMPILE)objcopy ELF = key.elf BIN = key.bin CINCLUDES = -I ./Include LOADFLAGS += -static -L ./Lib -lc -lm -lnosys LOADFLAGS += -static -L ./Lib -lgcc include Config.mk # arm-none-eabi-ld -Ttext=0x40000000 start.o main.o led.o -o led.elf # arm-none-eabi-objcopy -O binary led.elf led.bin $(ELF):Start/start.o main.o $(COBJECTS) $(LOAD) -Ttext=0x40000000 $^ -o $@ $(LDFLAGS) $(OBJECTCOPY) -O binary $(ELF) $(BIN) # arm-none-eabi-gcc -c start.s -o start.o # arm-none-eabi-gcc -c led.c -o led.o # arm-none-eabi-gcc -c main.c -o main.o %.o:%.s $(GCC) -c $< -o $@ %.o:%.c $(GCC) -c $< -o $@ $(CINCLUDES)
-
-
-
五、编译代码
-
六、下载代码到开发板上