历史上的今天
返回首页

历史上的今天

今天是:2024年09月09日(星期一)

正在发生

2018年09月09日 | STM32 I/O 作为外部中断输入

2018-09-09 来源:eefocus

 I/O口作为外部中断。general  purpose input and output

STM32 的每个 IO口都可以作为中断输入,要把 IO口作为外部中断输入,
有以下几个步骤:
1) 初始化 IO 口为输入。
这一步设置你要作为外部中断输入的 IO 口的状态,可以设置为上拉/下拉输入,也可以设
置为浮空输入,但浮空的时候外部一定要带上拉,或者下拉电阻。否则可能导致中断不停的触
发。在干扰较大的地方,就算使用了上拉/下拉,也建议使用外部上拉/下拉电阻,这样可以一
定程度防止外部干扰带来的影响。
2) 开启 IO 口复用时钟,设置 IO 口与中断线的映射关系。
STM32 的 IO 口与中断线的对应关系需要配置外部中断配置寄存器 EXTICR,这样我们要
先开启复用时钟,然后配置 IO 口与中断线的对应关系。才能把外部中断与中断线连接起来。
3) 开启与该 IO 口相对的线上中断/事件,设置触发条件。
这一步,我们要配置中断产生的条件, STM32 可以配置成上升沿触发,下降沿触发,或者
任意电平变化触发,但是不能配置成高电平触发和低电平触发。这里根据自己的实际情况来配
置,同时要开启中断线上的中断。这里需要注意的是:如果使用外部中断,并设置该中断的 EMR
位的话,会引起软件仿真不能跳到中断,而硬件上是可以的。而不设置 EMR,软件仿真就可以
进入中断服务函数,并且硬件上也是可以的。建议不要配置 EMR 位。
4) 配置中断分组(NVIC),并使能中断。
这一步,我们就是配置中断的分组,以及使能,对 STM32 的中断来说,只有配置了 NVIC
的设置,并开启才能被执行,否则是不会执行到中断服务函数里面去的。关于 NVIC 的详细介
绍,请参考 5.2.6 节。
5) 编写中断服务函数。
这是中断设置的最后一步,中断服务函数,是必不可少的,如果在代码里面开启了中断,
但是没编写中断服务函数,就可能引起硬件错误,从而导致程序崩溃!所以在开启了某个中断

后,一定要记得为该中断编写服务函数。在中断服务函数里面编写你要执行的中断后的操作。

与 NVIC 相关的寄存器, MDK 为其定义了如下的结构体:
typedef struct
{
__IO uint32_t ISER[8]; //中断使能寄存器组 Interrupt Set-Enable Registers
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; //中断除能寄存器组
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; //中断挂起控制寄存器组
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; //中断解挂控制寄存器组
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; //中断激活标志位寄存器组
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; //中断优先级控制寄存器组
uint32_t RESERVED5[644];
__O uint32_t STIR; //软件触发中断寄存器组
} NVIC_Type; 

        ISER[8]: ISER 全称是: Interrupt Set-Enable Registers, 每1 bit 代表一个中断,总共有32×8=256个中断,你要使能某个中断,必须设置相应的 ISER 位为 1,使该中断被使能(这里仅仅是使能,还要配合中断分组、屏蔽、 IO 口映射等设置才算是一个完整的中断设置)。 

        ICER[8]:全称是: Interrupt Clear-Enable Registers, 该寄存器组与 ISER[8] 的作用恰好相反,是用来清除某个中断的使能的。 如果想清除一个中断,不是在对应bit写0,而应该在对应位置写1。写0是无效的。
        ISPR[8]:全称是: Interrupt Set-Pending Registers ,每个位对应的中断和 ISER 是一样的。通过置 1,可以将正在进行的中断挂起,而执行同级或更高级别的中断。写 0 是无效的。

        ICPR[8]:全称是: Interrupt Clear-Pending Registers ,通过设置 1,可以将挂起的中断取消挂起操作。写 0 无效。

        IABR[8]:全称是: Interrupt Active Bit Registers,是一个中断激活标志位寄存器组。对应位所代表的中断和 ISER 一样,如果为 1,则表示该位所对应的中断正在被执行。这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。 

        IP[240]:全称是: Interrupt Priority Registers, 是一个中断优先级控制的寄存器组。这个寄存器组相当重要! STM32 的中断分组与这个寄存器组密切相关。 IP 寄存器组由 240 个 8bit 的寄存器组成,每个可屏蔽中断占用 8bit,这样总共可以表示 240 个可屏蔽中断。 而 STM32 只用到了其中的 68 个。 IP[67]~IP[0]分别对应中断 67~0。 而每个可屏蔽中断占用的 8bit 并没有全部使用,而是 只用了高 4 位。这 4 位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要根据 SCB->AIRCR 中的中断分组设置来决定。抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。 

         STM32 的 5 个分组是通过设置 SCB->AIRCR 的 BIT[10:8]来实现的,而 SCB->AIRCR 的修改需要通过在高 16 位写入 0X05FA 这个密钥才能修改的,故在设置 AIRCR 之前,应该把密钥加入到要写入的内容的高 16 位,以保证能正常的写入 AIRCR。在修改 AIRCR 的时候,我们一般采用读->改->写的步骤,来实现不改变 AIRCR 原来的其他设置。

这里简单介绍一下 STM32 的中断分组: STM32 将中断分为 5 个组,组 0~4。该分组的设
置是由 SCB->AIRCR 寄存器的 bit10~8 来定义的。具体的分配关系如表 5.2.6.1 所示:

AIRCR[10: 8]bit[7: 4]分配情况分配结果
01110: 40 位抢占优先级, 4 位响应优先级
11101: 31 位抢占优先级, 3 位响应优先级
21012: 22 位抢占优先级, 2 位响应优先级
31003: 13 位抢占优先级, 1 位响应优先级
40114: 04 位抢占优先级, 0 位响应优先级


                                                                表 5.2.6.1 AIRCR 中断分组设置表 

   

//设置 NVIC
//NVIC_PreemptionPriority: 抢占优先级
//NVIC_SubPriority : 响应优先级
//NVIC_Channel : 中断编号
//NVIC_Group : 中断分组 0~4
//注意优先级不能超过设定的组的范围!否则会有意想不到的错误
//组划分:
//组 0: 0 位抢占优先级, 4 位响应优先级
//组 1: 1 位抢占优先级, 3 位响应优先级
//组 2: 2 位抢占优先级, 2 位响应优先级
//组 3: 3 位抢占优先级, 1 位响应优先级
//组 4: 4 位抢占优先级, 0 位响应优先级
//NVIC_SubPriority 和 NVIC_PreemptionPriority 的原则是, 数值越小, 越优先
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)
{
u32 temp;
MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
temp=NVIC_PreemptionPriority<<(4-NVIC_Group);
temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
temp&=0xf; //取低四位
NVIC->ISER[NVIC_Channel/32]|=(1<//使能中断位(要清除的话,相反操作就 OK)
NVIC->IP[NVIC_Channel]|=temp<<4;     //设置响应优先级和抢断优先级

 NVIC配置总结:

  1)  SCB->AIRCR 决定抢占优先级的位数,设置怎么解释IP(interrupt priority)分组。其实这个分组的设置在每个系统里面只要设置一次就够了,设置多次,则是以最后的那一次为准。整个系统的优先级分组格式都一样。

 2)   ISER 使能对应的中断管脚,

 3)设置优先级。
       IP[channel] 决定具体的抢占优先级和子优先级。

       IP和SCB->AIRCR 一起决定中断的优先级。

       IABR 自读,显示当前正在执行的中断时那个管脚的中断。

》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

以上是对NVIC的管理和配置,下面说明一下外不中断的配置。

》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

STM32F103 的 EXTI 控制器支持 19 个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。 STM32F103 的 19 个外部中断为:
    线 0~15:对应外部 IO 口的输入中断。
    线 16:连接到 PVD 输出。
    线 17:连接到 RTC 闹钟事件。
    线 18:连接到 USB 唤醒事件。
对于外部中断 EXTI 控制 MDK 定义了如下结构体:
typedef struct
{
__IO uint32_t IMR;  //interrupt mask register
__IO uint32_t EMR;  //event mask register 
__IO uint32_t RTSR;  //rising trigger selection register 
__IO uint32_t FTSR;  //falling trigger selection register 
__IO uint32_t SWIER;   //software interrupt event register  
__IO uint32_t PR;     //pending register 
} EXTI_TypeDef; 
    IMR:中断屏蔽寄存器。这是一个 32 寄存器。但是只有前 19 位有效(19个外部中断)。当位 x 设置为 1 时,则开启这个线上的中断,否则关闭该线上的中断。
    EMR:事件屏蔽寄存器,同 IMR,只是该寄存器是针对事件的屏蔽和开启。
    RTSR:上升沿触发选择寄存器。该寄存器同 IMR,也是一个 32 为的寄存器,只有前 19位有效。位 x 对应线 x 上的上升沿触发,如果设置为 1,则是允许上升沿触发中断/事件。否则,不允许。
    FTSR:下降沿触发选择寄存器。同 RTSR,不过这个寄存器是设置下降沿的。下降沿和上升沿可以被同时设置,这样就变成了任意电平触发了。
    SWIER:软件中断事件寄存器。通过向该寄存器的位 x 写入 1,在未设置 IMR 和 EMR 的时候,将设置 PR 中相应位挂起。如果设置了 IMR 和 EMR 时将产生一次中断。被设置的 SWIER位,将会在 PR 中的对应位清除后清除。
    PR:挂起寄存器。当外部中断线上发生了选择的边沿事件,该寄存器的对应位会被置为 1。0:表示对应线上没有发生触发请求。通过向该寄存器的对应位写入 1 可以清除该位。在中断服务函数里面经常会要向该寄存器的对应位写 1 来清除中断请求 。

        通过以上配置就可以正常设置外部中断了,但是外部 IO 口的中断,还需要一个寄存器配置,也就是 IO 复用里的外部中断配置寄存器 EXTICR。这是因为 STM32 任何一个 IO 口都可以配置成中断输入口,但是 IO 口的数目远大于中断线数(16 个)。于是 STM32 就这样设计,GPIOA~GPIOG 的[15:0]分别对应中断线 15~0。

        这样每个中断线对应了最多 7 个 IO 口,以中断线 0为例:它对应了 GPIOA.0、 GPIOB.0、 GPIOC.0、 GPIOD.0、 GPIOE.0、 GPIOF.0、 GPIOG.0。而中断线每次只能连接到 1个 IO口上,这样就需要 EXTICR来决定对应的中断线配置到哪个 GPIO上了。

EXTICR 在 AFIO 的结构体中定义,如下:
typedef struct
{
    __IO uint32_t EVCR;
    __IO uint32_t MAPR;
    __IO uint32_t EXTICR[4];

} AFIO_TypeDef;


-------

EXTICR1


EXTICR2 对应EXTI4,EXTI5,EXTI6,EXTI7。

EXTICR3 对应EXTI8,EXTI9,EXTI10,EXTI11。

EXTICR4 对应EXTI12,EXTI13,EXTI14,EXTI15。

映射GPIOX_K 管脚。

例如,EXTI11,配置外部中断管脚11,通过对EXTIX[3:0]的设置分别设置为GPIOA  ~ GPIOG 。

//外部中断配置函数
//只针对 GPIOA~G;不包括 PVD, RTC 和 USB 唤醒这三个
//参数: GPIOx: 0~6, 代表 GPIOA~G;
//BITx: 需要使能的位;
//TRIM: 触发模式, 1, 下升沿; 2, 上降沿;3,任意电平触发
//该函数一次只能配置 1 个 IO 口, 多个 IO 口, 需多次调用
//该函数会自动开启对应中断, 以及屏蔽线
void Ex_NVIC_Config(u8 GPIOx, u8 BITx, u8 TRIM)
{
u8 EXTADDR; 
u8 EXTOFFSET;
EXTADDR=BITx/4; //得到中断寄存器组的编号
EXTOFFSET=(BITx%4)*4;//得到中断寄存器组内的偏移
RCC->APB2ENR|=0x01; //enable AFIO  clock
AFIO->EXTICR[EXTADDR]&=~(0x000F<AFIO->EXTICR[EXTADDR]|=GPIOx<//自动设置
EXTI->IMR|=1<if(TRIM&0x01)EXTI->FTSR|=1<

if(TRIM&0x02)EXTI->RTSR|=1<}

        Ex_NVIC_Config 完全是按照我们之前的分析来编写的,首先根据 GPIOx 的位得到中断寄存器组的编号,即 EXTICR 的编号,在 EXTICR 里面配置中断线应该配置到 GPIOx 的哪个位。然后使能该位的中断及事件,最后配置触发方式。这样就完成了外部中断的配置了。



 NVIC配置总结:

  1)  SCB->AIRCR 决定抢占优先级的位数,设置怎么解释IP(interrupt priority)分组。其实这个分组的设置在每个系统里面只要设置一次就够了,设置多次,则是以最后的那一次为准。整个系统的优先级分组格式都一样。

 2)   ISER 使能对应的中断bit,

 3)设置优先级。
       IP[channel] 决定具体的抢占优先级和子优先级。

       IP和SCB->AIRCR 一起决定中断的优先级。

       IABR 自读,显示当前正在执行的中断时那个管脚的中断。


外部中断配置总结:

    1) EXTI.BITx 映射到 GPIOx.BITx,通过AFIO_EXTICRn。

    2)开启外部中断线。

    3)设置触发方式。


推荐阅读

史海拾趣

东软载波(EastSoft)公司的发展小趣事

近年来,东软载波积极响应国家“一带一路”倡议,重点聚焦沿线国家的低压配用电网、能源互联网建设需求。公司依托成熟的电力物联网通信技术储备及经验,参与多个国家的智能电表项目,推动电网智能化改造。这些项目的成功实施不仅促进了当地电力基础设施的升级换代,也为东软载波在国际市场上树立了良好的口碑。

天钰(FITIPOWER)公司的发展小趣事

近年来,东软载波积极响应国家“一带一路”倡议,重点聚焦沿线国家的低压配用电网、能源互联网建设需求。公司依托成熟的电力物联网通信技术储备及经验,参与多个国家的智能电表项目,推动电网智能化改造。这些项目的成功实施不仅促进了当地电力基础设施的升级换代,也为东软载波在国际市场上树立了良好的口碑。

Able Systems公司的发展小趣事

随着电子行业的快速发展,Able Systems公司不断引进新技术,对产品进行升级改进。公司在打印机的设计和制造方面结合独家采购的领先技术,确保产品能够满足最苛刻的要求。这种对技术创新的执着追求,使得Able Systems的产品在行业中始终保持领先地位。

台湾致强(FORT)公司的发展小趣事

致强科技自2005年成立以来,便专注于高功率、低阻值且低TCR(温度系数)的电阻产品研发与生产。团队由一群具有机电整合、金属材料加工及冶金制程丰富经验的专家组成,他们独立研发出全合金材料的电阻生产制程,这一创新不仅区别于业界常见的厚膜或厚膜贴合金制程,还大幅提升了电阻的性能与稳定性。通过不断的技术迭代,致强科技成功推出了一系列高精度、高功率的合金电阻产品,广泛应用于各类电子产品中,满足了市场对高质量电流检知电阻的迫切需求。

安纳森(AnaSem)公司的发展小趣事

随着技术的不断成熟和市场的逐步扩大,安纳森开始将目光投向更广阔的全球市场。公司积极与全球各地的合作伙伴建立战略合作关系,共同开拓市场。同时,安纳森还设立了多个海外研发中心和销售网点,以便更好地了解当地市场需求,提供更贴近用户的产品和服务。这一系列的全球化布局,不仅提升了安纳森的品牌影响力,也为其未来的发展奠定了坚实的基础。

GPD Optoelectronics Corp公司的发展小趣事

随着技术的不断成熟和市场的逐步扩大,安纳森开始将目光投向更广阔的全球市场。公司积极与全球各地的合作伙伴建立战略合作关系,共同开拓市场。同时,安纳森还设立了多个海外研发中心和销售网点,以便更好地了解当地市场需求,提供更贴近用户的产品和服务。这一系列的全球化布局,不仅提升了安纳森的品牌影响力,也为其未来的发展奠定了坚实的基础。

问答坊 | AI 解惑

dsp视频教程(电子科技大学 )

第一章简略地讨论数字信号处理的基本思想及其优越性。 第二章介绍世界各大公司DSP处理器的最新发展,以及系统设计工程师们最为关心的如何评价和选择DSP处理器的问题。 第三章比较系统地介绍目前在国内外应用最广泛的TI的TMS320C2000、C5000和C600 ...…

查看全部问答>

用单片机和FPGA设计的万年历

这是一个学长的毕业设计。。现在发给大家…

查看全部问答>

加密IC

加密IC保护您的软件,防止别人抄袭。 有关产品的介绍:采用智能卡专用硬件平台,内置宝兴达公司自主开发的嵌入式系统,专门为保护用户代码,防止非法访问和外部攻击而设计的新一代安全芯片。硬件平台为8051内核,采用串口通讯协议,用户编程基于标 ...…

查看全部问答>

totally confused

I do driver on mobile for 3 years,I worked hard always, I believe in my skills,I always say there is nothing I can not do!I can do all kinds of drivers,I can do framwork,filesystem,gdi,protocol,I can solve out any bug in 2 hour ...…

查看全部问答>

用AT89C52设计一款PS2键盘,遇到的问题

请问各位:     PS2键盘是不是一定要和PC机握手才能工作的?握手初始化部分的程序一定要写吗?…

查看全部问答>

wince6 如何禁用输入面板

如题:在wince6下打开网页的时候,如果网页上有可输入的框,则系统会自动弹出一个输入面板(软键盘)。 我不想让这个东西弹出来(有自己的界面逻辑和输入控制),需要如何修改?谢谢!…

查看全部问答>

淘宝上发现一个液晶屏,不知怎么样,大家给个建议哈~~~~

一个320*240的点阵液晶,二手拆机,虽说可能有些划痕,不过价格实在是太超值了,   http://item.taobao.com/item.htm?id=6948951424   大家感觉怎么样呢? :D …

查看全部问答>

MSP430F149串口上电不能发送字符

我是初学者,一边看数据手册一边写程序,之前用BCS  定时器都好好的,现在用到串口了,结果出问题了。。。。主程序中初始化基本时钟系统,初始化串口,初始化P3端口,进入while(1)循环,循环中用查询方式,把板子接收到的字符再发送给超级终端 ...…

查看全部问答>

FPGA与MCU异步通讯的同步化实践

FPGA+MCU是一中非常流行的架构,MCU的并行总线在和FPGA通讯的时候一般都是异步的。         常见的MCU有单片机、ARM以及DSP等等,所谓的并行接口比如TI的TMS320C5410的HPI口。在FPGA加MCU的架构里往往存 ...…

查看全部问答>

KL46 Bootloader的疑问

看了Freescale的有关Bootloader文档,AN2295,有些疑问 1,第31页有管ICF文件这么一段描述: 编辑后ROM开始地址为0x4000,Code Start地址为什么只增加了0x3FF0?(0x4400 - 0x410),而不是增加0x4000呢?2.我现在使用的是MKL46系列CortexM0+ M ...…

查看全部问答>