S3C2440 按键中断

发布者:数字狂舞最新更新时间:2021-10-14 来源: eefocus关键字:S3C2440  按键中断  寄存器 手机看文章 扫描二维码
随时随地手机看文章

中断也是一种异常,但中断较为复杂一点,除了一般异常的处理流程


保护现场

处理 (handle_irq_c )

判断中断源 [INTOFFSET]

跳到中断处理函数 (key_action)[EINTPEND]

清除中断 [SRCPND] [INTBEND]

恢复现场

当然还有寄存器设置函数 key_enit_init [EXTINTn] [EINTPEND]


更为甚者,我们可以来参考手册上的流程图

这里是引用

对于我们的按键中断来讲,都是without sub-register。


寄存器

使用什么外设,其实都是和寄存器打交道。那么,这次又和哪些寄存器打交道呢。


总中断寄存器

[INTMASK] Determine which interrupt source is masked.

The masked interrupt source will not be

serviced.(需要设置,在 register_irq 里设置)

[INTBEND] Indicate the interrupt request status.(需要清零, handle_irq_c )

[INTOFFSET] Indicate the IRQ interrupt request source(只读, handle_irq_c )

[SRCPND] Indicate the interrupt request status.(需要清零, handle_irq_c )

INTMSK 寄存器 中断屏蔽寄存器,置1是屏蔽中断源,置0是使能,默认是全部屏蔽,所以需要设置。


地址:0X4A000008

[0] : EINT0 = 0x0(S2 - EINT0)

[2] : EINT2 = 0x0(S3 ~ EINT2)

[5] : EINT8_23 = 0x0(S4 ~ EINT11,S5 ~ EINT19)

即 [0X4A000008] &= ((0<<0) | (0<<2) | (0<<5))

INTPND 寄存器 Indicate the interrupt request status.


地址: 0X4A000010

表明被请求了的寄存器

[0] : EINT0 (S2 - EINT0)

[2] : EINT2 (S3 ~ EINT2)

[5] : EINT8_23 (S4 ~ EINT11,S5 ~ EINT19)

INTOFFSET 寄存器 Indicate the IRQ interrupt request source


地址:0x4A000014

只读寄存器

0 : EINT0 (S2 - EINT0)

2 : EINT2 (S3 ~ EINT2)

5 : EINT8_23 (S4 ~ EINT11,S5 ~ EINT19)

SRCPND寄存器 Indicate the interrupt request status.

一共32位代表不同的中断,置0是关闭中断,置1是使能中断


地址: 0X4A000000

[0] : EINT0 = 0x1(S2 - EINT0)

[2] : EINT2 = 0x1(S3 ~ EINT2)

[5] : EINT8_23 = 0x1(S4 ~ EINT11,S5 ~ EINT19)

外部(按键)中断设置

[EXTINT0] / [EXTINT1] / [EXTINT2]

External interrupt control register 0 / 1 / 2(需要设置, key_enit_init )

[EINTMASK] External interrupt mask register (需要设置, key_enit_init )

[EINTPEND] External interrupt pending register(需要清零, key_action)

EXTINT0 寄存器 External interrupt control register 0


地址:0x56000088

[2:0] :EINT0 = 0x111(11x = Both edge triggered)

[10:8]:EINT2 = 0x111(11x = Both edge triggered)

EXTINT1 寄存器 External interrupt control register 1

地址:0x5600008c


[14:12] :EINT11 = 0x111(11x = Both edge triggered)

EXTINT2 寄存器 External interrupt control register 2

地址:0x56000090


[14:12] :EINT19 = 0x111(11x = Both edge triggered)

EINTMASK 寄存器 外部中断屏蔽寄存器,置1是屏蔽中断源,置0是使能,默认是全部屏蔽,所以需要设置。


地址:0x560000a4(External interrupt mask register )

[11] :EINT11 = 0x0

[19] :EINT19 = 0x0

EINTPEND 寄存器 判断哪个中断发生


地址:0x560000a8(External interrupt pending register)

逐一对应

中断流程

首先是按键中断的各种寄存器初始化,这个真少不了。


/* 初始化按键中断 */

void key_eint_init()


{

/* 初始化按键寄存器

* 设置GPFCON的GPF0/2、GPG3/11为中断引脚 

*  按键寄存器 

* C_S2 ~ 0  ~ GPF0 

* C_S3 ~ 4  ~ GPF2 

* C_S4 ~ 6  ~ GPG3 

* C_S5 ~ 22 ~ GPG11 

* D_S2 ~ 0  ~ GPF0 

* D_S3 ~ 2  ~ GPF2 

* D_S4 ~ 3  ~ GPG3 

* D_S5 ~ 11 ~ GPG11 

*/

GPFCON &= ~((3< GPGCON &= ~((3<

GPFCON |=  ((2< GPGCON |=  ((2<

/* EXTINT0 寄存器 External interrupt control register 0

- 地址:0x56000088

- [2:0]  :EINT0 = 0x111(11x = Both edge triggered)

- [10:8] :EINT2 = 0x111(11x = Both edge triggered)


* EXTINT1 寄存器 External interrupt control register 1

* 地址:0x5600008c

- [14:12] :EINT11 = 0x111(11x = Both edge triggered)


* EXTINT2 寄存器 External interrupt control register 2

* 地址:0x56000090

- [14:12] :EINT19 = 0x111(11x = Both edge triggered)

 

* EINTMASK 寄存器 I/O中断屏蔽寄存器,置1是屏蔽中断源,置0是使能,默认是全部屏蔽,所以需要设置。

- 地址:0x560000a4(External interrupt mask register ) 

- [11] :EINT11 = 0x0

- [19] :EINT19 = 0x0

*/

EXTINT0 |= ((7<<0) | (7<<8)); /* s2, s3*/

EXTINT1 |= ((7<<12)); /* s4 */

EXTINT2 |= ((7<<12)); /* s5 */


EINTMASK &= ~((1<<11) | (1<<19)); /* 使能外部中断,关闭屏蔽信号 */


register_irq(0, key_irq);

register_irq(2, key_irq);

register_irq(5, key_irq);

}


一按下按键,硬件处理,首先就会跳到向量组 vector 0x18,通过汇编跳到 do_irq, 在这里完成保护现场和恢复现场,处理异常跳到c函数 handle_irq_c 。


do_irq:

/* 重要!栈未设置,需要重新设置,指向一个不会被用到的地方 */

ldr sp, =0x33d00000


/* 保护现场 */

sub lr, lr, #4 //根据lr恢复规则,异常前的lr-4 = 异常后的lr

stmdb sp!, {r0-r12, lr} //目前位置 lr 里面有被打断前的下一条将要执行的指令,所以也要保存

/* 处理异常 */

bl handle_irq_c


/* 恢复现场 */

ldmia sp!, {r0-r12, pc}^ /* ^会把spsr的值恢复到cpsr里 */


来到函数 handle_irq_c,做三个动作,分别是分辨中断源和清除中断,处理中断通过 irq_array[bit](bit) 语句跳转,这个其实是函数指针,in this case,处理函数是 key_action,里面就可以处理按键按下后的事情,整个中断流程至此。


typedef void(*irq_func)(int);

irq_func irq_array[32];


void handle_irq_c()

{

/* 分辨中断源 */


/*INTOFFSET 寄存器** Indicate the IRQ interrupt request source

- 地址:0x4A000014

    只读寄存器

- 0 : EINT0 (S2 - EINT0)

  - 2 : EINT2 (S3 ~ EINT2)

  - 5 : EINT8_23 (S4 ~ EINT11,S5 ~ EINT19)

  */

int bit = INTOFFSET; //读出来是哪个中断



/* 处理中断 */

irq_array[bit](bit);


/* 清除中断 */

SRCPND = (1< INTPND = (1<}


还有一个问题没解决 irq_array[bit](bit) 怎么指向 key_irq ?


我们搞一个函数,注册中断函数 ,在里面顺便设置中断屏蔽


/* 注册中断的指针函数, 附加使能总中断

 * irq - 第几个处理函数,fp - 传入的中断处理函数

 */

void register_irq(int irq, irq_func fp)

{


irq_array[irq] = fp;


/* [INTMSK] 寄存器  中断屏蔽寄存器

* 置1是屏蔽中断源,置0是使能,默认是全部屏蔽,所以需要设置。

- 地址:0X4A000008

- [0] : EINT0 = 0x0(S2 - EINT0)

- [2] : EINT2 = 0x0(S3 ~ EINT2)

- [5] : EINT8_23 = 0x0(S4 ~ EINT11,S5 ~ EINT19)

-  即 [0X4A000008] &= ((0<<0) | (0<<2) | (0<<5))

*/

INTMSK &= ~(1<}


相关代码

中断初始化(总/外部中断)


/* 初始化中断控制器 */

void interrput_init()

{

/* SRCPND寄存器 Indicate the interrupt request status.

* 一共32位代表不同的中断,置0是关闭中断,置1是使能中断

- 地址: 0X4A000000

- [0] : EINT0 = 0x1(S2 - EINT0)

- [2] : EINT2 = 0x1(S3 ~ EINT2)

- [5] : EINT8_23 = 0x1(S4 ~ EINT11,S5 ~ EINT19)

 

* INTMSK 寄存器  中断屏蔽寄存器

* 置1是屏蔽中断源,置0是使能,默认是全部屏蔽,所以需要设置。

- 地址:0X4A000008

- [0] : EINT0 = 0x0(S2 - EINT0)

- [2] : EINT2 = 0x0(S3 ~ EINT2)

- [5] : EINT8_23 = 0x0(S4 ~ EINT11,S5 ~ EINT19)

-  即 [0X4A000008] &= ((0<<0) | (0<<2) | (0<<5))

*/


INTMSK &= ~((1<<0) | (1<<2) | (1<<5));

 

}


按键中断处理

/* 按键处理函数,包括按键处理

irq - 0 : EINT0 (S2 - EINT0)

irq - 2 : EINT2 (S3 ~ EINT2)

irq - 5 : EINT8_23 (S4 ~ EINT11,S5 ~ EINT19)


*/

int key_action(int irq)

{

unsigned int val = EINTPEND;



/* S2-GPF0 、 S3-GPF2 、 S4 - GPG3

* S2~GPF6、S3~GPF5、S4~GPF4

* 如果按键对应DAT寄存器是零,即按键按下,反之 

*/


/* S2控制LED3 */

if (irq == 0)

{

if (GPFDAT&(1< GPFDAT |=  (1< }

else{

GPFDAT &= ~(1< }

}

/* S3控制LED2 */

else if (irq == 2)

{

if (GPFDAT&(1< GPFDAT |=  (1< }

else{

GPFDAT &= ~(1< }

}


/* S4控制LED1 */

else if (irq == 5)

{

if (val & (1<<11))

{

if (GPGDAT&(1< GPFDAT |=  (1< }

else{

GPFDAT &= ~(1<

}

else if (val & (1<<19))

{


if (GPGDAT&(1< GPFDAT |=  ((1< }

else{

GPFDAT &= ~((1< }

}


}

EINTPEND = val; //清除外部中断

}


void handle_irq_c()

{

/* 分辨中断源 */



/*INTOFFSET 寄存器** Indicate the IRQ interrupt request source

- 地址:0x4A000014

    只读寄存器

- 0 : EINT0 (S2 - EINT0)

  - 2 : EINT2 (S3 ~ EINT2)

  - 5 : EINT8_23 (S4 ~ EINT11,S5 ~ EINT19)

  */

int bit = INTOFFSET; //读出来是哪个中断



/* 处理中断 */

if(bit == 0 || bit == 2 || bit == 5)

key_action(bit);


/* 清除中断 */

SRCPND = (1< INTPND = (1<}


汇编

_start:

b reset /* 0x30000000 */

// ldr pc, =do_und /* 0x30000004 */

ldr pc, und_addr

ldr pc, swi_addr

b halt /* vector 0x0c : prefetch aboot */

b halt /* vector 0x10 : data abort */

b halt /* vector 0x14 : reserved */

ldr pc, irq_addr /* vector 0x18 : irq */

b halt /* vector 0x1c : fiq */

……

do_irq:

/* 重要!栈未设置,需要重新设置,指向一个不会被用到的地方 */

ldr sp, =0x33d00000


/* 保护现场 */

sub lr, lr, #4 //根据lr恢复规则,异常前的lr-4 = 异常后的lr

stmdb sp!, {r0-r12, lr} //目前位置 lr 里面有被打断前的下一条将要执行的指令,所以也要保存

/* 处理异常 */

bl handle_irq_c


/* 恢复现场 */

ldmia sp!, {r0-r12, pc}^ /* ^会把spsr的值恢复到cpsr里 */

关键字:S3C2440  按键中断  寄存器 引用地址:S3C2440 按键中断

上一篇:S3C2440中的异常与中断
下一篇:S3C2440—6.串口的printf实现

推荐阅读最新更新时间:2024-11-11 14:49

S3C2440 UART串口驱动1
1.1 UART 串口 通用异步接收器和发送器(Universal Asynchronous Receiver and Transmitter) 简称UART。通常是嵌入式设备中默认都会配置的通信接口。这是因为,很多嵌入式设备没有显示屏,无法获得嵌入式设备实时数据信息,通过UART串口和超级终端相连,打印嵌入式设备输出信息。并且在对嵌入式系统进行跟踪和调试时,UART串口了是必要的通信手段。比如:网络路由器,交换机等都要通过串口来进行配置。UART串口还是许多硬件数据输出的主要接口,如GPS接收器就是通过UART串口输出GPS接收数据的。 1.1.1 异步通信和同步通信 图2-56同步信号与异步信号 同步通信
[单片机]
<font color='red'>S3C2440</font> UART串口驱动1
基于S3C2440和DM9000移植LWIP
终于开始我的第一篇笔记了。这回要做的事情,是以太网的移植。 使用mini2440已经有一段时间了。诸如裸机的LED,键盘开关等等等等也都试验过了,uCOS,WinCE也是浅尝了一下。如今想到了以太网。 由于mini2440的板上集成了一个DM9000的网卡,并且在CE系统里面成功的使用以太网与PC连接了。于是自然而然的想,能不能在uCOS下也实现以太网接口呢? 一上来什么都不懂,于是找一些资料,在这里要谢谢焦海波老师所著的嵌入式网络系统设计一书,移植过程中很多资料都来源于这本书。其次是mikenoodle的单片机驱动DM9000网卡一文,里面详细地讲述如何在2440裸机下驱动DM9000网卡。 首先明确我们需要做的事情是什么?为了
[单片机]
51单片机(十六)—— 定时器0和定时器1寄存器介绍及功能描
这篇文章,我们对51单片机的定时器0和定时器1的寄存器和功能进行介绍。 1 定时器/计数器工作方式寄存器TMOD 定时器/计数器工作方式寄存器在特殊功能寄存器中,字节地址为89H,不能位寻址,TMOD用来确定定时器T0和T1的工作方式及功能选择,单片机复位时,TMOD全部被清0,TMOD寄存器的定义如下。 定时器/计数器工作方式寄存器TMOD 这个寄存器的高4位用来设置定时器T1,低4位用来设置定时器T0。 GATE—门控制位。 GATE=0,定时器/计数器启动与停止仅受TCON寄存器中TRx位来控制。 GATE=1,定时器/计数器启动与停止由TCON寄存器中TRx位和外边中断引脚(INT0或INT1)上的
[单片机]
51单片机(十六)—— 定时器0和定时器1<font color='red'>寄存器</font>介绍及功能描
S3C2440 网卡驱动介绍以及制作虚拟网卡驱动(二十五)
1、描述 网卡的驱动其实很简单,它还是与硬件相关,主要是负责收发网络的数据包,它将上层协议传递下来的数据包以特定的媒介访问控制方式进行发送,并将接受到的数据包传递给上层协议。 网卡设备与字符设备和块设备不同,网络设备并不对应于/dev/目录下的文件,不过会存放在/sys/class/net目录下 2、Linux系统对网络设备驱动定义了4个层次,这4个层次有到下分为: 1)网络协议接口层: 实现统一的数据包收发的协议,该层主要负责调用dev_queue_xmit()函数发送数据,netif_rx()函数接收数据 2)网络设备接口层: 通过net_device结构体来描述一个具体的网络设备的信息,实现不同的
[单片机]
<font color='red'>S3C2440</font> 网卡驱动介绍以及制作虚拟网卡驱动(二十五)
STM32的GPIO的寄存器配置学习1
本篇文章主要是学习以M3内核的STM32的GPIO的寄存器的配置,为什么要学习寄存器,而不利用库函数呢?我只能说为了让学的知识更加牢固吧!当然,你可以直接去利用库函数,但是如果你能认真读完本篇博客,你会对知识豁然开朗!加油吧! STM32 的每个 IO 端口都有 7 个寄存器来控制。他们分别是:配置模式的 2 个 32 位的端口配置寄存器 CRL 和 CRH;2 个 32 位的数据寄存器 IDR 和 ODR;1 个 32 位的置位/复位寄存器BSRR;一个 16 位的复位寄存器 BRR;1 个 32 位的锁存寄存器 LCKR;这里我们仅介绍常用的几个寄存器,我们常用的 IO 端口寄存器只有 4 个:CRL、CRH、IDR、OD
[单片机]
STM32的GPIO的<font color='red'>寄存器</font>配置学习1
ATmega 16 单片机的WDT定时器的相关寄存器(七)
1.WDTCR 看门狗定时器控制寄存器 WDTOE WDE WDP2 WDP1 WDP0 位 Res:保留位 ATmega16保留位,读操作返回值为零。 位 4 WDTOE:看门狗修改使能 清零WDE时必须置位WDTOE,否则不能禁止看门狗。一旦置位,硬件将在紧接的4个时钟周期之后将其清零。 位 3 WDE:使能看门狗 WDE为 1 时,看门狗使能,否则看门狗将被禁止。只有在WDTOE为 1 时WDE才能清零。以下为关闭看门狗的步骤: (1).在同一个指令内对WDTOE和WDE写 1 ,即使WDE已经为 1 (2).在紧接的4个时钟周期之内对WDE写 0 位 WDP2,
[单片机]
S3C2440的UART详解
1、UART原理简介 在介绍2440的UART控制器之前,我们首先来了解一下UART的原理 UART:Universal Asynchronous Receiver/Transmitter(通用异步收发送器),用来传输串行数据,发送数据时,CPU将并行数据写入UART,UART按照一定格式在TxD线上串行发出;接收数据时,UART检测到RxD线上的信号,将串行收集放到缓冲区中,CPU即可读取UART获得的这些数据。 UART最精简的连线形式只有3根线,TXD用于发送,RXD用于接收,GND用于提供参考电平。UART之间以帧作为数据传输单位,帧由具有完整意义的若干位组成,它包含开始位、数据位、校验位和停止位。发送数据之前,互相通信
[单片机]
<font color='red'>S3C2440</font>的UART详解
s3c2440下vxworks的tffs文件系统调试
使用BCNG2440开发板,该板配置了AM29LV160DB的FLASH。 目标:实现vxworks下的tffs文件系统。 1、使用最新的bsp,构建一个新的工程,然后在vxworks配置选项中增加tffs的支持,以及tffs show的支持,重新编译内核,发现bsp目录下自动拷贝了一个新的systffs.c文件,然后报告编译错误, E:Tornado2.2targetconfigbcng2440sysTffs.c:116:69: #error sysTffs : Verify system mac ros and function before first use 不知道error宏是干什么用的,只好把这句话删掉。 哦,让第一次
[单片机]

推荐帖子

第一次发帖:用MSP430 LaunchPad做了个心率仪
在团购的群里看到有人给了一个用PIC单片机制作心率仪链接,做得很不错,是外国人做的!拿到MSP430LaunchPad本来是想做一块触摸板的,可是图不好画,后面又补发了触摸板,所以原来计划作罢。前段时间比较闲,看看有网友翻译了那篇用PIC单片机制作心率仪,就模仿做了一个。水平有限,请大家拍砖!在原来的基础上我做了一些该进,我的是四位数的,最高位是时间提示位-----------也就是提示被测的人已经按住多少时间按了。15秒一到,显示被测者的心率。显示部分我本来想用段码液晶的,可手头上
IC爬虫 微控制器 MCU
TI2017年发布超低相噪锁相环LMX2594
前几天老板让调试一下TI新发布不久的锁相环,先看看性能。性能是相当优越了,写了一个点频的程序测试了一下效果,输出12G的情况下,100M鉴相在10k可以达到102dbc/hz,基本上满足芯片手册上的指标,测试结果就不贴出来了,但这个效果一般的锁相环采用内插混频才能达到,可以说是相当厉害了。现在在调试扫频功能,但是这个锁相环功能感觉有些强大,有112个寄存器需要配置,扫频功能调试了几天还没有调试成功,如有调试的同道中人,一起讨论一下~此内容由EEWORLD论坛网友logitech66
logitech66 RF/无线
EMI噪声耦合的机理?
产生噪声的机理有如下几种:(1)阻抗不匹配和阻抗不连续;(2)共模阻抗不匹配引起差模信号;(3)容性耦合产生噪声电流;(4)感性耦合引起噪声电压;第一种阻抗不匹配和阻抗不连续会导致信号反射会导致信号的叠加、过冲、振铃;第二种共模阻抗不匹配导致差模信号,这个我想起的一个例子就是在同相加法器中,共模阻抗不匹配,但是怎么引起的差模信号?第三种第四种容性耦合和感性耦合,是指分开的两个导体之间存在电容,如果存在一个导体的电压相对另一个导体发生变化,就会产生所谓的位移电流,Ic=Cdu/dt,
乱世煮酒论天下 模拟电子
Viterbi核的调用
最近在搞Viterbi译码器,不知道哪位大佬有viterbi核的使用手册,另外我调用的时候出现好多Error(204009):Can'tgeneratenetlistoutputfilesbecausethelicenseforencryptedfileF:/QuartusII13.0/biyesheji/viterbi_IP/viterbi-library/auk_vit_hyb_bmp_atl_ent.vhdisnotavailable这类错误哪位能解释下
'Friday Altera SoC
在altium designer中能不能挖一个凹槽?
在altiumdesigner中能不能挖一个凹槽?比如2.0mm厚的板子,要求凹槽深度1.2mm,就是不透的槽,如何挖?在altiumdesigner中能不能挖一个凹槽?走过路过的,帮个忙!就是一个凹槽不透,这个在keepoutlayer层放上槽的外框,最好是不要90°直角,即直角处稍微有点圆弧图上明确表明此处半槽,深度1.2mm,并发板图的时候,要和制板厂沟通能做否qwqwqw2088发表于2014-8-618:26就是一个凹槽不透,这个在keepoutl
OldChief PCB设计
CMOS集成电路设计手册
CMOS集成电路设计手册CMOS集成电路设计手册赞一个非常好的电子书,英文原版,下载保存了,谢谢分享
liva2022 电路观察室
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved