历史上的今天
返回首页

历史上的今天

今天是:2024年12月24日(星期二)

正在发生

2021年12月24日 | stm32中断初识与实践(下)

2021-12-24 来源:eefocus

这一部分我们将使用按键作为触发源,在产生中断时,实现控制LED灯的亮灭状态切换。

在具体应用前,我们还需先认识认识EXTI。


EXTI

全称为External interrupt/event controller,即外部中断/事件控制器。其管理了20个中断/事件线,每条线都有对应的一个边沿检测器,用于输入信号上升沿和下降沿的检测。如图6-1为stm32参考手册里的EXTI框图。

图6-1

图中有两条走向的线路,蓝色线路用于产生中断,绿色线路产生事件。我们从右往左看图。


查阅按键原理图可知,按键按下时,电平状态由低变高,会在输入线呈现出一个上升沿信号,这个信号到达边沿检测电路后,会被上升沿触发选择寄存器(EXTI_RTSR)检测并触发,输出有效信号1给编号3电路,否则输出无效信号0。如果电平由高变低,则会被下降沿触发选择寄存器(EXTI_FTSR)检测触发。


触发的信号到达编号3电路,这是一个或门电路,它的输入信号除了来源于边沿检测电路,还有来自软件中断事件寄存器(EXTI_SWIER)。无论是来自EXTI_SWIER或边沿检测电路的信号,只要有一个是有效信号1,那么便可以输出有效信号1给编号3电路。编号3电路之后,分为两条线,一条产生中断,一条产生事件。


信号沿着蓝色线路产生中断,编号3输出信号到编号4。编号4是一个与门电路,它的另一个信号来源是中断屏蔽寄存器(EXTI_IMR)。众所周知,与门电路要求输入信号都为1才能输出1,换言之,如果EXTI_IMR置为0,那么编号4电路输出的信号都为0,只有EXTI_IMR置1时,编号4输出的信号才由编号3决定。这样一来我们可以通过EXTI_IMR来控制是否产生中断。随后,编号4电路输出的信号会被保存到挂起寄存器(EXTI_PR)内。最后将EXTI_PR里的值输出到NVIC,实现中断控制。


信号沿着绿色线路产生事件,最终会输出一个脉冲信号。编号3输出信号到编号5,编号5也是一个与门电路,信号来源于编号3电路和事件屏蔽寄存器(EXTI_EMR)。和编号4的与门电路一样,我们可以通过EXTI_EMR来控制是否产生事件。当编号5输出有效信号1时会在脉冲发生器(Pulse generator)输出一个脉冲信号(无效信号不会输出脉冲)。这个脉冲信号可以给其他外设电路使用,如TIM、ADC等等,一般用来触发TIM或ADC开始转换。


EXTI的中断/事件线

EXTI有20条中断/事件线,其中有16条用于GPIO线上的外部中断/事件,占用EXTI0~EXTI15,其他4条用于特定外设的外部中断/事件。如图6-2。

 

图6-2

 

可以通过操作AFIO的四个外部中断配置寄存器(AFIO_EXTICR1~AFIO_EXTICR4)的EXTIx[3:0]位选择配置PAx、PBx、PCx...PGx等引脚。如图6-3为AFIO_EXTICR1寄存器描述。

 

图6-3

 

EXTI_InitTypeDef

EXTI_InitTypeDef是EXTI初始化结构体,其定义在stm32f10x.h文件中,如图6-4所示。

 

图6-4

 

有四个结构体成员,

  • EXTI_Line:中断/事件线,可选择EXTI0~EXTI19,如图6-2所示;

  • EXTI_Mode:EXTI模式,可设置产生中断(EXTI_Mode_Interrupt)或产生事件(EXTI_Mode_Event);

  • EXTI_Trigger:EXTI边沿触发,可选择上升沿触发(EXTI_Trigger_Rising)、下降沿触发(EXTI_Trigger_Falling)或者上升沿下降沿都触发(EXTI_Trigger_Rising_Falling);

  • EXTI_LineCmd:使能(ENABLE)/失能(DISABLE)EXTI线。

开始实验

按键按下时,产生电平变化,EXTI检测到上升沿信号,触发中断,执行中断服务函数,实现LED灯的亮灭切换。


简要分析下编程要点:

  1. 初始化产生中断的外设(GPIO);

  2. 配置NVIC;

  3. 初始化EXTI;

  4. 中断服务函数;

  5. main函数

NVIC配置

我们先对NVIC进行配置,将其封装为函数NVIC_Configuration(),供后续调用。


/**

  * @brief  NVIC配置

  * @param  无

  * @retval 无

 */ static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 配置优先级分组 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // 配置按键中断源 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级为1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断寄存器 NVIC_Init(&NVIC_InitStructure); }


NVIC配置部分,需要配置优先级分组、中断源、抢占优先级、子优先级以及使能中断寄存器等。关于优先级分组配置以及NVIC_InitTypeDef结构体分析,已在上篇文章里详细说明,读者可点击进入阅读。


EXTI中断配置


/**

  * @brief  EXTI按键中断配置

  * @param  无

  * @retval 无

 */ void EXTI_Key_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; /* 调用函数配置NVIC */ NVIC_Configuration(); /* 初始化GPIO */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); /* 初始化EXTI */ // 配置中断线的输入源 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); EXTI_InitStructure.EXTI_Line = EXTI_Line0; // 配置中断线为EXTI0 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 配置为中断模式 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;// 上升沿触发中断 EXTI_InitStructure.EXTI_LineCmd = ENABLE; // 使能中断 EXTI_Init(&EXTI_InitStructure); }


这个配置函数里用到了GPIO和EXTI两个初始化结构体,对其分别进行初始化配置,同时调用NVIC_Configuration()函数配置NVIC。


其中,

  • GPIO_EXTILineConfig()固件函数是对AFIO_EXTICR1的操作,所以我们需要开启AFIO时钟;

  • 需要把GPIO配置为输入模式(浮空输入),由外部电路决定引脚状态;

  • 通过查阅按键原理图可得,按键引脚为PA0,可得GPIO端口源和引脚源,并将其中断线配置为EXTI0;

  • 由按键原理图可得,按键按下时为高电平,所以使用上升沿触发中断。

中断服务函数

上篇文章里已经说明中断服务函数名应在启动文件里找到,并统一写在stm32f10x_it.c文件中。



/**

  * @brief  EXTI0线中断服务函数

  * @param  无

  * @retval 无

 */ void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0) != RESET) // 确保产生了EXTI0线中断 { LED_TOGGLE; // LED灯状态切换 EXTI_ClearITPendingBit(EXTI_Line0);// 清除中断标志位 } }


需要先确保是否产生了中断,这一步我们直接调用stm32f10x_exti.c文件里的库函数EXTI_GetITStatus(),通过其返回值判断。EXTI_GetITStatus()函数操作的是中断屏蔽寄存器(EXTI_IMR)和挂起寄存器(EXTI_PR),通过两个寄存器的值判断是否产生中断,。由图6-1功能框图可得,如果相应线的EXTI_IMR和EXTI_PR都置1,则返回“SET”,即产生中断。具体的源码实现可查看3.5版本的stm32f10x固件库。


LED_TOGGLE是一个宏,在宏里实现LED状态切换。具体的实现在专栏(stm32):GPIO输入——按键检测文章里已经有过说明,读者可移步阅读。


中断服务实现后,需要清除该中断线的中断标志位,以免下次程序判断失误。


main函数


int main(void) { LED_GPIO_Config(); // LED端口初始化 EXTI_Key_Config(); // EXTI按键中断配置 while(1){} // 等待中断产生 } 


当按键按下时,即进入中断,执行中断服务函数,完成实验。

推荐阅读

史海拾趣

EICHHOFF公司的发展小趣事

在电子行业的快速发展中,EICHHOFF公司始终保持着对技术创新的追求。XX年代,公司成功研发出了一款具有革命性意义的连接器产品,该产品凭借其独特的设计和卓越的性能,迅速在市场上获得了广泛认可。这一创新不仅为EICHHOFF带来了丰厚的利润,也进一步巩固了其在行业中的领先地位。

此后,EICHHOFF公司继续加大研发投入,不断推出具有竞争力的新产品。这些产品不仅在性能上有所提升,还在设计和功能上进行了创新,满足了客户日益增长的需求。

Elpida Memory公司的发展小趣事

为了挽救Elpida Memory,日本政府采取了积极的援助措施。2009年,日本政府通过《产业再生法》修正案,向Elpida Memory提供了数百亿日元的公共资金和融资支持。这些资金帮助Elpida Memory度过了最困难的时期,并为其后续的重组和发展提供了有力的支持。

广州盛炬(GZSJ)公司的发展小趣事

Elpida Memory的成立,标志着日本在DRAM(动态随机存取存储器)领域的一次重要整合。1999年,为了应对全球半导体市场的激烈竞争,日本政府主导了日立、NEC、三菱电机等公司的DRAM业务整合,成立了Elpida Memory。这一举措旨在保护日本在DRAM领域的市场份额和技术优势,同时也为Elpida Memory的未来发展奠定了坚实的基础。

Conxall公司的发展小趣事

随着科技的飞速发展,物联网成为了新的热点。Conxall公司敏锐地捕捉到了这一机遇,投入大量资源进行物联网技术的研发。经过数年的努力,公司成功推出了一款具有高度集成和智能化特点的物联网模块,广泛应用于智能家居、智慧城市等领域,为公司的快速发展奠定了坚实的基础。

川晶科技公司的发展小趣事

随着环保意识的不断提高,绿色制造成为电子行业的重要发展趋势。川晶科技积极响应国家绿色发展的号召,通过引进先进的环保设备和技术,实现了生产过程的绿色化、低碳化。公司不断优化生产工艺,减少能源消耗和废弃物排放,推动产品向绿色、环保方向发展。川晶科技的绿色制造实践得到了业界的广泛赞誉,成为行业内的绿色标杆。

APSA公司的发展小趣事

APSA公司在创业初期,专注于电子行业中某一特定领域的技术研发。通过团队的不懈努力和持续创新,公司成功开发出一款具有竞争力的产品,填补了市场空白。这一技术突破不仅为APSA公司赢得了首批客户,也为公司的后续发展奠定了坚实的基础。

问答坊 | AI 解惑

SD街头快打音乐用AVR单片机播放

SD街头快打音乐用AVR单片机播放…

查看全部问答>

请教一个有关反相时钟驱动路径的约束

电路中用相位相反的时钟去触发相邻触发器。 如果有一个触发器FF1的输出经过组合逻辑电路后与触发器FF2的输入, 除了输出延时外,请问还要如何进行约束? …

查看全部问答>

半天时间搞懂模拟电路

模拟电路精简教程。四十余页包含了模拟电路几乎所有重要知识点,讲解精细,透彻。不敢私藏,传上来与众共享。…

查看全部问答>

测试流接口驱动的测试程序如何写啊?

怎么写测试流接口驱动的测试程序啊?就是在应用程序中如果调用流接口驱动的那几个接口函数啊? 呵呵 有个简单的例子更好。。…

查看全部问答>

启动程序与引导程序有什么区别呀????

启动程序与引导程序有什么区别呀????…

查看全部问答>

求救!有关WinCE6.0 R2 NandFlash驱动的新架构MDD+PDD+FMD的问题

现在NANDFlash驱动的新架构MDD+PDD+FMD已经抛弃了旧的分区驱动mspart和MBR格式,采用region+partition的概念,整个nandflash分为多个region,每个region又可分为多个partition,每个region的开头有一个分区表。 有哪位达人知道这个分区表的格式? ...…

查看全部问答>

指令在哪?

我想开始一个I/O 程序,如何开始?指令及汇编的资料找不到,用C也不知如何开始  …

查看全部问答>

STM32F100C系列如何在不使用JTAG和SWD的情况下烧写程序?

STM32F100C系列如何在不使用JTAG和SWD的情况下烧写程序? 我是新手,请多多指教!…

查看全部问答>

如何学习松翰单片机

有没有成套的松翰开发板买。像51一样方便编译的。 如果没有,请问我要买什么硬件。请列出来 还有,那个松翰仿真器,是不是有接口来连接硬件使用的。就是不用芯片,直接可以接到硬件上使用。 谢谢了…

查看全部问答>

参与HELPER2416开发板助学计划-----(1)晒晒板子

本帖最后由 cf0609 于 2014-7-18 22:55 编辑 前两天就收到板子了,因一些事情耽搁了一下,不好意思哈,现在才来发帖。今天先来晒晒板子的靓照吧。先来个全家福:板子的配件很齐全,除了jlink所有会用到的东西都有。 给板子上电看看,,,开机就 ...…

查看全部问答>