【韦东山旧1期学习笔记】11.S3C2440 中断实验(二)按键IRQ实验

按键IRQ实验

硬件介绍

在这里插入图片描述
这四个按键和将要控制的LED灯对应的电路原理图如下所示:
在这里插入图片描述
由上图可知,当按键没有按下时,EINT0、EINT2、EINT11和EIN19都处于高电平;当按键按下时,这四个引脚都处于低电平。我们使用S2按键触发IRQ中断来控制LED1,使用S3按键触发IRQ中断来控制LED2,使用S4按键触发IRQ中断来控制LED4。
对于S5按键,我们让其触发FIQ中断来控制三盏灯同时点亮或熄灭。
都让它们按下点亮LED灯,松开熄灭LED灯。

所以IRQ实验涉及S2、S3、S4三个按键和LED1、LED2、LED4三个灯。其对应的SoC GPIO管脚如下图所示:
在这里插入图片描述
在这里插入图片描述
我们可以看到,LED1对应的GPIO是GPF4,LED2对应的GPIO是GPF5,LED4对应的GPIO是GPF6。
按键S2对应的GPIO是GPF0,S3对应的GPIO是GPF2,S4对应的GPIO是GPG3。
在这里插入图片描述
在这里插入图片描述

LED灯操作代码

首先我们先进行LED灯操作的代码编写。我们先将GPF4、GPF5、GPF6初始化为输出引脚,并使其输出高电平,这样三盏LED灯均熄灭。之后编写点亮和熄灭函数,方便后续调用。具体代码如下所示:
led.c

#include "s3c2440_soc.h"
#include "led.h"

void leds_init(void) {
	//清除[13:8]比特位
	GPFCON &= (~(0x3F << 8));	
	//[13:12][11:10][9:8]分别设置为0b01
	//使得GPF4、GPF5、GPF6管脚处于输出状态
	GPFCON |= (0x15 << 8);
	//设置上拉电阻,使其默认处于高电平
	//GPFUP |= (0x7 << 4);
	//使其输出高电平,熄灭LED灯
	GPFDAT |= (0x7 << 4);
}

void led_on(int ledNum) {
	int offset = 0;
	switch(ledNum){
		case LED1:
			offset = 4;
			break;
		case LED2:
			offset = 5;
			break;
		case LED4:
			offset = 6;
			break;
		default:
			return;
	}	
	if(offset == 0) {
		return;
	}
	GPFDAT &= (~(1 << offset));
}

void led_off(int ledNum) {
	int offset = 0;
	switch(ledNum){
		case LED1:
			offset = 4;
			break;
		case LED2:
			offset = 5;
			break;
		case LED4:
			offset = 6;
			break;
		default:
			return;
	}	
	if(offset == 0) {
		return;
	}
	GPFDAT |= (1 << offset);
}

led.h

#ifndef __LED_H__
#define __LED_H__

#define LED1 1
#define LED2 2
#define LED4 4

void leds_init(void); 
void led_on(int ledNum); 
void led_off(int ledNum); 

#endif

按键初始化代码

void keys_init_irq(void) {
	//按键S2对应的GPIO是GPF0
	//S3对应的GPIO是GPF2
	//S4对应的GPIO是GPG3
	//初始化GPF0 GPF2为中断功能,对应EINT2 EINT0
	GPFCON &= (~(0x33));
	GPFCON |= (0x2 << 4) | (0x2 << 0);
	//初始化GPG3为中断功能,对应EINT11
	GPGCON &= (~(0x3 << 6));
	GPGCON |= (0x2 << 6);
	//设置GPIO中断触发方式为双边沿触发
	EXTINT0 |= (0x7 | (0x7 << 8));
	EXTINT1 |= (0x7 << 12);
	//打开GPIO中断屏蔽开关
	//对于EINT0~EINT3来说,GPIO控制器这里是始终没有屏蔽中断的。
	//我们只需打开EINT11中断屏蔽即可。
	EINTMASK &= (~(0x1 << 11));
	//打开中断控制器对应的中断开关
	INTMSK &= (~((1 << 0) | (1 << 2) | (1 << 5)));
}

从中可以看出,这里涉及到的中断为EINT0、EINT2和EINT11。

GPIO 中断触发方式

下面开始设置中断触发方式。我们使用的是EINT0、EINT2和EINT11。为了检测按键按下和松开,我们采用双边沿触发。

EXTINT0 |= (0x7 | (0x7 << 8));
EXTINT1 |= (0x7 << 12);

在这里插入图片描述
在这里插入图片描述

GPIO中断屏蔽寄存器

在这里插入图片描述
从上图我们可以看到,对于EINT0~EINT3来说,GPIO控制器这里是始终没有屏蔽中断的。
我们只需打开EINT11中断屏蔽即可。

EINTMASK &= (~(0x1 << 11));

中断控制器设置

在这里插入图片描述
通过S3C2440用户手册可以查到它的中断源表如上图所示。可以看到,EINT0、EINT2和EINT11都属于without sub-register中断源。所以我们不用设置SUBMSK寄存器。
下面来设置INTMSK寄存器,如下图所示:
在这里插入图片描述
我们需要打开EINT0、EINT2和EINT8_23中断开关。
INTMSK &= (~((1 << 0) | (1 << 2) | (1 << 5)));
优先级我们使用默认的优先级即可。

中断处理函数

在中断处理函数中,我们根据硬件中断号去读取相应引脚的电平状态,以判断是按下还是松开按键,之后决定打开还是熄灭LED灯。处理完毕后,从源头开始清理中断标识。
我们查看GPIO控制器中的外部中断PENDING寄存器 EINTPEND可以看到,如果是EINT11中断发生,那么我们首先需要清除这里的置位。注意,这里也是写1清零,写0不变。
在这里插入图片描述

void irqExpHandler(void) {
	//现在处于SVC模式
	//我们先获取硬件中断号
	unsigned int interruptNum = INTOFFSET;
	printf("IRQ Interrupt Number: %d\n\r", interruptNum);
	//按键 按下后为低电平
	unsigned int isKeyUp = 0;
	int ledNum = -1;
	switch(interruptNum){
		case 0:
			//EINT0中断 s2按键
			isKeyUp = (GPFDAT & 0x1);
			ledNum = LED1;
			
		break;
		case 2:
			//EINT2 s3按键
			isKeyUp = (GPFDAT & (0x1 << 2));
			ledNum = LED2;
		break;
		case 5:
			//EINT8_23 s4按键
			isKeyUp = (GPGDAT & (0x1 << 3));
			ledNum = LED4;
		break;

		default:
		break;
	}
	if(ledNum > 0) {
		if(isKeyUp) {
			//熄灭LED1
			led_off(ledNum);
			printf("Key is Up.LED%d is turn off.\n\r", ledNum);
		}else {
			led_on(ledNum);
			printf("Key is Down.LED%d is turn on.\n\r", ledNum);
		}
	}
	
	//处理完毕,从源头开始清理中断标志
	//注意是写1清零
	if(interruptNum == 5) {
		EINTPEND |= (0x1 << 11);
	}
	SRCPND |= (0x1 << interruptNum);
	INTPND |= (0x1 << interruptNum);
	printf("IRQ Interrupt is Handled\n\r");
}

main函数

主函数中只做一件事,就是无限死循环打印字符变量gCh,之后自增一继续打印。

char gCh = 'A';
int main(void) {
	leds_init();
	keys_init_irq();
	printf("%s\n\r", "IRQ Test.");
	dump_norFlash(80);
	
	while(1) {
		printf("%c(0x%02x) ", gCh, gCh);
		gCh++;
		wait(888888);
	}
	return 0;
}

实验效果动态图

在这里插入图片描述

发布了25 篇原创文章 · 获赞 2 · 访问量 1065

猜你喜欢

转载自blog.csdn.net/BakerTheGreat/article/details/104525450