ARM平台FS6818/s5p6818开发板实验6 —— 按键中断实验

按键中断实验:

实验内容:

通过简单事例说明s5p6818处理器的GIC中断处理的应用,设置key2按键连接的引脚为中断模式,当识别按键被按下时进入相应的中断处理函数

实验目的:

熟悉开发环境的使用

掌握s5p6818处理器的中断过程及编程。

实验平台:

FS_6818开发平台,Ubuntu,secureCRT。

实验6-按键中断实验

  1. 分析电路图

  1. 分析芯片手册

分析芯片手册的GPIO章节。

 

GPIOxOUTENB:GPIOx引脚输出使能寄存器

GPIOxDETMODE0/1:GPIOx引脚事件检查模式寄存器

               中断的触发方式:低电平,高电平,下降沿,上升沿

       GPIOxINTENB:GPIOx引脚中断使能寄存器

GPIOxDET:GPIOx引脚事件检测寄存器

GPIOxALTFN0/1:GPIOx引脚复用功能选择寄存器

GPIOxDETMODEEX:GPIOx引脚事件检查外部寄存器

GPIOxDETENB:GPIOx引脚检测使能寄存器

 

  1. GPIOB8引脚设置为GPIO功能   GPIOBALTFN0

  1. 设置GPIOB8引脚位输入功能    GPIOBOUTENB

3》 设置GPIOB8引脚的中断的触发方式(下降沿触发)

GPIOxDETMODE0/1 

GPIOxDETMODEEX

4》设置中断使能寄存器   GPIOxINTENB

5》事件检测寄存器:GPIOxDET

作用:中断挂起的标志位,当读GPIOx引脚对应的位为1,表示中断发生。

        在相应的位写1,可以清除中断挂起标志位,可以接收下一次中断。

 

6》使能GPIOx引脚检测使能寄存器  GPIOxDETENB

GIC章节分析:

1》GICD_CTRL:GICD全局使能寄存器

2》GICD_ISENABLER:中断设置使能寄存器

GIC支持16个SGI,16个PPI,128个SPI,总计160个中断信号。

而GICD_ISENABLERn寄存器中每一位管理着一个中断号,

一个寄存器最多管理32个中断号,所以需要5个这样的寄存器,

管理160个中断号。

我们需要找到86中断号对应着5个ISENABLERn寄存器中的

哪个寄存器,以及这个寄存器的哪1位。

GICD_ISENABLER2[22] = 0b1

86 / 32 = 2…22

3》GICD_IPRIORITYRn (n = 0 to 39)  中断信号优先级设置寄存器

而GICD_IPRIORITYRn寄存器中每8位管理着一个中断号,

一个寄存器最多管理4个中断号,所以需要40个这样的寄存器,

管理160个中断号。

我们需要找到86中断号对应着40个GICD_IPRIORITYRn寄存器中的哪个寄存器,

以及这个寄存器的哪8位。

GICD_IPRIORITYR21[23:16] = 86;

 

  1.  4 = 21…2

 

4GICD_ITARGETSRn中断目标分配寄存器

而GICD_ITARGETSRn寄存器中每8位管理着一个中断号,

一个寄存器最多管理4个中断号,所以需要40个这样的寄存器,

管理160个中断号。

我们需要找到86中断号对应着40个GICD_ITARGETSRn寄存器中的哪个寄存器,

以及这个寄存器的哪8位。

GICD_ITARGETSRn21[23:16] = 0x1;

86 / 4 = 21…2

5》GICD_ICPENDERn:中断挂起标志位清除寄存器

而GICD_ICPENDERn寄存器中每一位管理着一个中断号,

一个寄存器最多管理32个中断号,所以需要5个这样的寄存器,

管理160个中断号。

 

我们需要找到86中断号对应着5个GICD_ICPENDERn寄存器中的

哪个寄存器,以及这个寄存器的哪1位。

GICD_ICPENDER2[22] = 0b1

 

 

6》GICC_CTRL:GICC中断使能寄存器

7》GICC_PMR:中断优先级屏蔽寄存器

8》GICC_IAR:中断应答寄存器

9》GICC_EOIR:中断结束寄存器

  1. 编写代码

main.c


#include "led.h"
#include "pwm.h"
#include "delay.h"
#include "uart0.h"
#include "wdt.h"
#include "adc.h"
#include "key.h"
int main()
{
	hal_led_init();
	hal_uart_init();
	hal_gpio_init();
	hal_gic_init();
	Tri_String("KEY Interrupt Test\n");
	while(1)
	{
		// 按键中断到来,
		// 打断当前正在处理的程序
		// 进入中断处理程序
		// 需要了解:异常的处理过程。
	}
	return 0;
}

key.c


#include "key.h"
void hal_gpio_init(void)
{
	// 1. 设置GPIOB8引脚为GPIO功能 GPIOBALTFN0
	GPIOB.ALTFN0 &= (~(0x3 << 16));
	// 2. 设置GPIOB8引脚为输入功能 GPIOBOUTENB
	GPIOB.OUTENB &= (~(0x1 << 8));
	// 3. 设置GPIOB8引脚的中断触发方式:下降沿触发
	// 		GPIOBDETMODE0  GPIOBDETMODEEX
	GPIOB.DETMODE0 &= (~(0x3 << 16));
	GPIOB.DETMODE0 |= (0x2 << 16);
	GPIOB.DETMODEEX &= (~(0x1 << 8));
	// 4. 设置GPIOB8引脚中断使能寄存器  GPIOBINTENB 
	GPIOB.INTENB |= (0x1 << 8);
	// 5. 设置GPIOB8引脚的检测使能寄存器  GPIOBDETENB
	GPIOB.DETENB |= (0x1 << 8);

	// 1. 设置GPIOB16引脚为GPIO功能 GPIOBALTFN1
	GPIOB.ALTFN1 &= (~(0x3 << 0));
	GPIOB.ALTFN1 |= (0x2 << 0);
	// 2. 设置GPIOB16引脚为输入功能 GPIOBOUTENB
	GPIOB.OUTENB &= (~(0x1 << 16));
	// 3. 设置GPIOB16引脚的中断触发方式:下降沿触发
	// 		GPIOBDETMODE1  GPIOBDETMODEEX
	GPIOB.DETMODE1 &= (~(0x3 << 0));
	GPIOB.DETMODE1 |= (0x2 << 0);
	GPIOB.DETMODEEX &= (~(0x1 << 16));
	// 4. 设置GPIOB16引脚中断使能寄存器  GPIOBINTENB 
	GPIOB.INTENB |= (0x1 << 16);
	// 5. 设置GPIOB16引脚的检测使能寄存器  GPIOBDETENB
	GPIOB.DETENB |= (0x1 << 16);
}
void hal_gic_init(void)
{
	// GICD
	// 1. 设置GICD层86号对应的中断使能寄存器 GICD_ISENABLER2[22]
	GICD_ISENABLER.ISENABLER2 |= (0x1 << 22);
	// 2. 设置中断优先级寄存器 GICD_IPRIORITYR21[23:16]
	GICD_IPRIORITYR.IPRIORITYR21 &= (~(0xFF << 16));
	GICD_IPRIORITYR.IPRIORITYR21 |= (86 << 16);
	// 3. 设置中断目标分配寄存器 GICD_ITARGETSR21[23:16]
	GICD_ITARGETSR.ITARGETSR21 &= (~(0xFF << 16));
	GICD_ITARGETSR.ITARGETSR21 |= (0x1 << 16);
	// 4. 设置GICD层全局中断使能寄存器 GICD_CTRL[0]
	GICD_CTRL |= (0x1);

	// GICC
	// 5. 设置GICC层中断全局使能寄存器 GICC_CTRL[0]
	GICC_CTRL |= (0x1);
	// 6. 设置GICC层中断屏蔽寄存器  GICC_PMR[7:0]
	GICC_PMR |= (0xFF);
}

do_irq.c

// irq类型中断处理程序的入口
#include "s5p6818.h"
#include "delay.h"
void do_irq(void) 
{
	int irq_num;
	// 获取中断号 GICC_IAR[9:0]
	irq_num = GICC_IAR & 0x3FF;	
	switch(irq_num) {
	case 86:
		//86号中断处理程序
		printf("KEY Interrupt Number = %d\n",irq_num);
		if (GPIOB.DET & (0x1 << 8)) {
			// 按键按下
			while(!(GPIOB.PAD & (1 << 8))) {
				delay_ms(10);  // 去抖动
				// 松手检测  
				while(!(GPIOB.PAD & (1 << 8))); 
				printf("KEY VOL+\n");
			}
			// 清除GPIO层中断挂起标志位 GPIOBDET
			GPIOB.DET |= (0x1 << 8);

		} else if (GPIOB.DET & (0x1 << 16)) {
			while(!(GPIOB.PAD & (1 << 16))) {
				delay_ms(10);
				while(!(GPIOB.PAD & (1 << 16)));
				printf("KEY VOL-\n");
			}
			// 清除GPIO层中断挂起标志位 GPIOBDET
			GPIOB.DET |= (0x1 << 16);
		}
		// 清除GICD层中断挂起标志位 GICD_ICPENDER2[22]
		GICD_ICPENDER.ICPENDER2 |= (0x1 << 22);
		break;
	case 87:		
		//87号中断处理程序
		break;
		// ....
	}
	// 清除GICC层中断号  GICC_EOIR[9:0]
	GICC_EOIR = (GICC_EOIR & (~0x3FF)) | irq_num;
}

key.h

#ifndef __KEY_H__
#define __KEY_H__
#include "s5p6818.h"
void hal_gpio_init(void);
void hal_gic_init(void);

#endif //__KEY_H__

 

  1. 下载调试

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值