ARM裸机——FS2410按键控制LED(中断方式)

一、开发环境

1、硬件平台:FS2410

2、主机:Ubuntu 10.10

二、相关硬件原理图(按键与LED)

                 

按键的接线资源:

KSCAN0 -> GPE11、  KSCAN1 -> GPG6、  KSCAN2 -> GPE13、  KSCAN3 -> GPG2

EINT0  -> GPF0、  EINT2  -> GPF2、  EINT11 -> GPG3、  EINT19 -> GPG11

三、程序设计相关原理

       某个中断的产生表示,与它所对应的矩阵行的4个按键中,至少有一个按键被按住了。因此可以通过查看产生了哪个中断,来确定在矩阵的哪一行中发生了按键操作(按住或释放)。例如,如果产生了外部2号线中断(EINT2变为低电平),则表示K7、K8、K9和K15中至少有一个按键被按住了。这时候4个EINT端口应该通过GPIO配置寄存器被设置为外部中断端口,而且4个KSCAN端口的输出必须为低电平。

      在确定按键操作所在行的位置之后,我们还得查看按键操作所在列的位置。此时要使用KSCAN端口组,同时将4个EINT端口配置为通用输入端口(而不是中断端口)。在4个KSCAN端口中,轮流将其中某一个端口的输出置为低电平,其他3个端口的输出置为高电平。这样逐列进行扫描,直到按键所在列的KSCAN端口输出为低电平,此时按键操作所在行的EINT管脚的输入端口的值会变成低电平。例如,在确认产生了外部2号中断之后,进行逐列扫描。若发现在KSCAN1为低电平时(其他端口输出均为高电平),GPF2(EINT2管脚的输入端口)变为低电平,则可以断定按键K8被按住了。

四、相关寄存器的配置信息见《ARM裸机——FS2410按键控制LED灯(查询方式)》

五、详细代码:

start.S:(启动代码)

.extern main
.text
.global _start

_start:
    b   Reset

HandleUndef:
    b   HandleUndef 
 
HandleSWI:
    b   HandleSWI

HandlePrefetchAbort:
    b   HandlePrefetchAbort

HandleDataAbort:
    b   HandleDataAbort

HandleNotUsed:
    b   HandleNotUsed

    b   HandleIRQ

HandleFIQ:
    b   HandleFIQ

Reset:                  

    mov r1, #0x53000000
    mov r2, #0x0
    str r2, [r1]
    
    msr cpsr_c, #0xd2    
    ldr sp, =1024 * 3  

    msr cpsr_c, #0xdf       
    ldr sp, =1024 * 4     

    bl  init_gpio   

	msr cpsr_c, #0x5f       
    
    ldr lr, =halt_loop    

    bl main

halt_loop:
    b   halt_loop
	
HandleIRQ:
 
	sub lr, lr, #4                  
    stmfd   sp!,    { r0-r12,lr }   
	
    bl light_on                     
    
	ldmfd   sp!,    { r0-r12,pc }^  


key.c:

#define SRCPND    (*(volatile unsigned long *) 0x4a000000)
#define INTMOD    (*(volatile unsigned long *) 0x4a000004)
#define INTMSK   (*(volatile unsigned long *) 0x4a000008)
#define INTPND    (*(volatile unsigned long *) 0x4a000010)
#define EXTINT2   (*(volatile unsigned long *) 0x56000090)
#define EINTMASK  (*(volatile unsigned long *) 0x560000a4)
#define EINTPEND  (*(volatile unsigned long *) 0x560000a8)
#define GPECON    (*(volatile unsigned long *) 0x56000040)
#define GPEDAT    (*(volatile unsigned long *) 0x56000044)
#define GPFCON    (*(volatile unsigned long *) 0x56000050)
#define GPFDAT    (*(volatile unsigned long *) 0x56000054)
#define GPGCON    (*(volatile unsigned long *) 0x56000060)

#define GPE11_out (1 << 22)
#define GPF4_out  (1 << 8)
#define GPF5_out  (1 << 10)
#define GPF6_out  (1 << 12)
#define GPF7_out  (1 << 14)
#define GPG11_int (2 << 22)

void init_gpio(void)     //初始化GPIO
{
	GPFCON = GPF4_out | GPF5_out | GPF6_out | GPF7_out;      //设置GPF4-GPF7为输出 
	GPFDAT |= 0xf0;      //将4个LED熄灭
	
	GPECON = GPE11_out;     //GPE11设置为输出(KSCAN0)
	GPEDAT &= ~(1 << 11);   //设置GPE11输出0

	GPGCON = GPG11_int;     //GPG11设置为中断方式(EINT19)
	EXTINT2 |= (1 << 13);   //设置为下降沿触发

	EINTMASK &= ~(1 << 19);     //使能EINT19
	INTMSK &= ~(1 << 5);      //使能中断

}

void light_on(void)    //设置灯亮
{
	if((EINTPEND & (1 << 19)) && (SRCPND & (1 << 5)))      //判断EINT19是否产生
	{  
		GPFDAT &= ~(1 << 4);       //点亮LED12
		
		EINTPEND |= (1 << 19);    //清除中断,注意清除中断的顺序
		SRCPND = SRCPND;
		INTPND = INTPND;  
	}
}

void wait(long long num)     //延迟函数
{
	for(; num > 0; num--);
}

int main(void)     //设置LED9闪烁
{
	while(1)   
	{
		GPFDAT &= ~(1 << 7);  
		wait(200000);
		GPFDAT |= 0xf0;
		wait(200000);
	}
	
	return 0;
}

Makefile :

key.bin: start.S key.c
	arm-none-linux-gnueabi-gcc -c start.S -o start.o
	arm-none-linux-gnueabi-gcc -c key.c -o key.o
	arm-none-linux-gnueabi-ld -Ttext 0x00000000 start.o key.o -o key
	arm-none-linux-gnueabi-objcopy -O binary -S key key.bin

clean:
	rm -f *.o key.bin key


在开发板的uboot上输入:

tftp 0 key.bin

go 0


实验现象:

LED9一直闪烁,按下按键后LED12灯亮

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值