- EXTI叙述
- EXTI寄存器
- EXTI操作
- EXTI代码示例
EXTI叙述
可产生20个软件外部中断。
探测低于APB2时钟周期的外部脉冲。
当上升沿下降沿和软件触发请求时,看中断和事件的屏蔽器来决定是否进入下一步(可同时产生),若中断屏蔽器使能则挂起。
EXTI0-EXTI15对应GPIO引脚的0-15,剩下4位EXTI对应不同功能。
这里还指出需要配置AFIO_EXTICRx寄存器和使能AFIO时钟。
EXTI寄存器
PR需要注意在中断产生时自动置位,写入1重置,意思是这个在中断里要手动清除,否则中断始终处于挂起状态(此挂起非NVIC中的挂起,此挂起应该是指中断在运行,NVIC中的挂起是指低优先级中断挂起嵌套高优先级中断),将会一直处于中断状态(我认为的)。
SWIER在PR对应位为0无请求和IMR对应位已使能时写入1将会产生中断。
EXTI操作
-
开启时钟:
这里需要使能AFIO时钟,接收引脚无需使能GPIO时钟,因为用不到GPIO功能。
EXTI无时钟使能。 -
配置用到的的GPIO:
这里需要用到AF功能复用作外部中断,所以需要GPIO配置模式为浮动输入。
启用AFIO,配置其寄存器。这一步实际上集成在GPIO库函数中。 -
配置EXTI
中断线、中断/事件模式、上升/下降沿。 -
配置 NVIC
-
编写中断服务函数
在STARTUP函数中选取对应的终端服务函数名称并编程。注意在中断函数中需要进行清除挂起操作。
EXTI代码示例
EXTIConfig.h
#ifndef __EXTI_CONFIG_H_
#define __EXTI_CONFIG_H_
#include "stm32f10x.h"
#define Interrupt0 EXTI_GenerateSWInterrupt( EXTI_Line0 )//软件中断触发
void EXTI_NVIC_GPIOCompleteConfig(void);
void EXTIConfig( uint32_t EXTI_Line , EXTIMode_TypeDef EXTI_Mode , EXTITrigger_TypeDef EXTI_Trigger , FunctionalState EXTI_LineCmd );
void EXTI_NVIC_GPIOConfig( GPIO_TypeDef* GPIOx , uint16_t GPIO_Pin , EXTIMode_TypeDef EXTI_Mode ,\
EXTITrigger_TypeDef EXTI_Trigger , FunctionalState EXTI_LineCmd );
#endif
EXTIConfig.c
void EXTIConfig( uint32_t EXTI_Line , EXTIMode_TypeDef EXTI_Mode , EXTITrigger_TypeDef EXTI_Trigger , FunctionalState EXTI_LineCmd )
{
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStruct.EXTI_LineCmd = EXTI_LineCmd;
EXTI_Init( &EXTI_InitStruct );
}
void EXTI_NVIC_GPIOCompleteConfig(void)//硬件中断配置
{
RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO , ENABLE ); //Enable AFIO Clock
GPIO_InitConfig( GPIOA , GPIO_Pin_0 , GPIO_Speed_50MHz , GPIO_Mode_IN_FLOATING ); //Init GPIO to receive external interrupt(no enabling GPIO Clock because no use)
GPIO_EXTILineConfig( GPIO_PortSourceGPIOA , GPIO_PinSource0 ); //Open Alternate Fountion
NVIC_Config( EXTI0_IRQn , NVIC_PriorityGroup_1 ,\
1 , 1 , ENABLE ); //Config NVIC of EXTIchannel
EXTIConfig( EXTI_Line0 , EXTI_Mode_Interrupt , EXTI_Trigger_Falling , ENABLE ); //Config EXTI
}
void EXTI_NVIC_GPIOSoftwareConfig(void)//软件中断配置,比硬件中断少了GPIO相关的操作,调用interrupt0直接产生中断。
{
NVIC_Config( EXTI0_IRQn , NVIC_PriorityGroup_1 ,\
1 , 1 , ENABLE ); //Config NVIC of EXTIchannel
EXTIConfig( EXTI_Line0 , EXTI_Mode_Interrupt , EXTI_Trigger_Falling , ENABLE ); //Config EXTI
}
stm32f10x_it.c
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0)==SET) //Confirm SET of EXTI_Line0
{
GPIO_WriteBit( GPIOB, GPIO_Pin_0, (BitAction)(1-GPIO_ReadOutputDataBit( GPIOB , GPIO_Pin_0 )));
EXTI_ClearITPendingBit( EXTI_Line0 ); //这个pending标志位必须被清除,pend挂起即标志位
}
}
main.c
int main()
{
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE ); //InitConfig GPIO for LED
GPIO_InitConfig( GPIOB , GPIO_Pin_0 , GPIO_Speed_50MHz , GPIO_Mode_Out_PP );
EXTI_NVIC_GPIOCompleteConfig(); //Config EXTI fot EXTI0
while(1);
//此处采用A0作为检测口,B0用于中断服务函数。
// EXTI_NVIC_GPIOSoftwareConfig();
//
// while(1)
// {
// delay(1000);
// Interrupt0;
// }//软件中断使LED闪烁
}
欢迎交流指正~~