STM32开发项目:如何配置GPIO的外部中断

Bena ·
更新时间:2024-09-20
· 798 次阅读

目录如何配置GPIO的外部中断配置RCC时钟GPIO配置EXTI配置NVIC配置中断服务函数 IRQ_Handler 如何配置GPIO的外部中断

以STM32F103为例,记录配置GPIO外部中断的一般方法与流程。

配置RCC时钟

RCC时钟配置是STM32MCU顺利运行的必备步骤,笔者使用的参考代码如下:

void RCC_Config() { RCC_DeInit(); //使能HSE,并等待 HSE 稳定 RCC_HSEConfig(RCC_HSE_ON); ErrorStatus HSEStartUpStatus; HSEStartUpStatus = RCC_WaitForHSEStartUp(); //HSE启动成功 if (HSEStartUpStatus == SUCCESS) { //使能FLASH预存取缓冲区 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //SYSCLK周期与闪存访问时间的比例设置 FLASH_SetLatency(FLASH_Latency_2); //Configures the AHB clock (HCLK): AHB clock = SYSCLK RCC_HCLKConfig(RCC_SYSCLK_Div1); //Configures the High Speed APB clock (PCLK2): APB2 clock = HCLK RCC_PCLK2Config(RCC_HCLK_Div1); //Configures the High Speed APB clock (PCLK2): APB1 clock = HCLK/2 RCC_PCLK1Config(RCC_HCLK_Div2); //Configures the PLL clock source and multiplication factor: //HSE oscillator clock selected as PLL clock entry //The PLL multiplication factor is 9 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //Enables the PLL. RCC_PLLCmd(ENABLE); //等待PLL时钟稳定 while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) ; //Configures the system clock (SYSCLK): PLL selected as system clock RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //读取时钟切换状态位,确保PLLCLK被选为系统时钟 while (RCC_GetSYSCLKSource() != 0x08) ; } //HSE启动失败 else { while (1) ; } } GPIO配置

以PB10, PB11, PB12, PB13作为外部中断输入口为例:

void GPIO_Config() { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB, &GPIO_InitStructure); //选择EXTI的信号源 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource10); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource13); } EXTI配置

EXTI (External interrupt/event controller): 外部中断/事件控制器,管理了控制器的 20
个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿
检测和下降沿的检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为
中断或者事件,以及触发事件的属性。

void EXTI_Config() { EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line=EXTI_Line10 | EXTI_Line11 | EXTI_Line12 | EXTI_Line13; EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd=ENABLE; EXTI_Init(&EXTI_InitStructure); } NVIC配置

NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。但是各个芯片厂商在设计芯片的时候会对 Cortex-M3内核里面的 NVIC进行裁剪,把不需要的部分去掉,所以说 STM32 的 NVIC 是 Cortex-M3 的 NVIC 的一个子集。

在 NVIC 有一个专门的寄存器:中断优先级寄存器 NVIC_IPRx,用来配置外部中断的
优先级,IPR 宽度为 8bit,原则上每个外部中断可配置的优先级为 0~255,数值越小,优先
级越高。

但是绝大多数CM3芯片都会精简设计,以致实际上支持的优先级数减少,在F103
中,只使用了高 4bit用于表达优先级的这 4bit,又被分组成抢占优先级和子优先级。

如果有多个中断同时响应,抢占优先级高的就会 抢占 抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。

void NVIC_Config() { NVIC_InitTypeDef NVIC_InitStructure; //NVIC_PriorityGroup_2: 2 bits for pre-emption priority & 2 bits for subpriority NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } 中断服务函数 IRQ_Handler

在启动文件 startup_stm32f10x_xd.s 中,我们已经初始化了中断向量表。实际的中断服务函数都需要重新编写,为了方便管理,可以把中断服务函数统一写在 stm32f10x_it.c 这个源文件中。关于中断服务函数的函数名必须跟启动文件里面预先设置的一样,否则系统就在中断向量表中找不到中断服务函数的入口,实现不了中断。

void EXTI15_10_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line10)!=RESET) { DoSomething_Line10(); EXTI_ClearITPendingBit(EXTI_Line10); } else if(EXTI_GetITStatus(EXTI_Line11)!=RESET) { DoSomething_Line11(); EXTI_ClearITPendingBit(EXTI_Line11); } else if(EXTI_GetITStatus(EXTI_Line12)!=RESET) { DoSomething_Line12(); EXTI_ClearITPendingBit(EXTI_Line12); } else if(EXTI_GetITStatus(EXTI_Line13)!=RESET) { DoSomething_Line13(); EXTI_ClearITPendingBit(EXTI_Line13); } else if(EXTI_GetITStatus(EXTI_Line14)!=RESET) { DoSomething_Line14(); EXTI_ClearITPendingBit(EXTI_Line14); } else if(EXTI_GetITStatus(EXTI_Line15)!=RESET) { DoSomething_Line15(); EXTI_ClearITPendingBit(EXTI_Line15); } else { } } 全能骑士涛锅锅 原创文章 9获赞 5访问量 403 关注 私信 展开阅读全文
作者:全能骑士涛锅锅



外部中断 stm32 gpio 中断

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章