学习总结_3_STM32_EXTI外部中断的基本使用流程_库函数版

一、    基本流程、
1、对作为外部中断输入源的Pin脚,进行GPIO的初始化;
        PS:用于做为外部中断输入源的pin,可以设置为浮空输入(GPIO_Mode_IN_FLOATING),上拉输入(GPIO_Mode_IPU)或者下拉输入(GPIO_Mode_IPD),根据中断响应方式和外围连接电路选择;Stm32每个GPIO都可以设置为外部中断的输入源,但是不同端口相同Pin间,只能设置其中一个pin为中断输入源,即设置PA1为中断输入源,其他Px1(x为除A外的端口),不能设置为中断源;
2、打开GPIO的复用时钟,EXTI外部中断需要打开复用时钟,相关函数为:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE)

3、初始化外部中断EXTI(External interrupt/event controller—外部中断/事件控制器):
        A、选择 EXTI 的输入源,通过函数:

void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)

        B、定义EXTI_InitTypeDef类型结构体,用于EXTI初始化;定义后初始化:

/*结构体定义*/
typedef struct 
{ uint32_t EXTI_Line; // 中断/事件线 
EXTIMode_TypeDef EXTI_Mode; // EXTI 模式 
EXTITrigger_TypeDef EXTI_Trigger; // 触发类型 
FunctionalState EXTI_LineCmd; // EXTI 使能 
} EXTI_InitTypeDef;

/*EXTI的初始化函数*/		
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)

4、    设置NVCI中断控制器:

        A、配置中断优先级分组:

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);

        B、结构体定义及初始化函数:

/*结构体定义*/
typedef struct
{
	uint8_t NVIC_IRQChannel; //中断源选择 
 
	uint8_t NVIC_IRQChannelPreemptionPriority; //抢占优先级 
 
	uint8_t NVIC_IRQChannelSubPriority; //响应优先级
 
	FunctionalState NVIC_IRQChannelCmd; //中断使能或者失能  
} NVIC_InitTypeDef;

/*NVIC初始函数*/
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

5、编写中断服务函数:
        中断服务函数的函数名不可以更改,中断服务函数的名字必须与启动文件的startup_stm32f10x_xx.s(如:startup_stm32f10x_hd.s)内找;
        外部中断的中断服务函数名:

void EXTIx_IRQHandler() // x = 0,1,2,3,4;
void EXTI9_5_IRQHandler () // 5~9共用中断服务函数的函数名
void EXTI15_10_IRQHandler () // 10~15共用中断服务函数的函数名

        PS:对应共用函数名的中断,通过在中断函数内读取对应中断源的标志位,判断是否产生中断;
使用如下函数,确定中断源EXTIx,的中断标志位是否置1:

/*中断标志位读取函数*/
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);

        中断函数最后要记得清楚标志位:

/*清楚中断标志位函数*/
void EXTI_ClearITPendingBit(uint32_t EXTI_Line)

二、举例

        功能说明:

1、选定PA1作为外部中断EXTI1输入源,外部上拉,下降沿触发;
2、外部中断EXTI1有效触发后,PB6置位并打开timer,进行计时,以10ms周期,触发Timer中断;
3、Timer中断次数累积,计时到100ms后,翻转PB6的输出电平。
4、选定PB9作为外部中断EXTI9输入源,外部上拉,下降沿触发;
5、外部中断EXTI9,停止Timer计时,PB6拉低。
void Gpio_PB6_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

	GPIO_InitTypeDef GPIO_InitStructure;//GPIO_InitTypeDef类型的结构体,用于设置PB2的应用参数
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //选择Pin2脚,
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //
 
	GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB2
}


void Timer7_InitConfig(u16 arr, u16 per)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Period = arr-1;
    TIM_TimeBaseStructure.TIM_Prescaler = per-1;
    TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure);
	TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
    TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_Init(&NVIC_InitStructure);

    //TIM_Cmd(TIM7,ENABLE);
    
}


volatile u32 TIM7_Timing10msCount;

void Clear_TIM7_Timing10msCount(void)
{
	TIM7_Timing10msCount = 0;
}

void TIM7_IRQHandler()
{    
    if(TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET)
    {
        
        TIM7_Timing10msCount++;
        TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
    }
	if(TIM7_Timing10msCount >= 10)
	{
		GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction) 1 - GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_6));
		TIM7_Timing10msCount = 0;
	}
}

void GpioInterrupt_Init(void)       		
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);

	GPIO_InitTypeDef GPIO_InitStructure;//GPIO_InitTypeDef类型的结构体,用于设置PA1的应用参数
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //选择Pin1脚,
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //
 
	GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA1

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //选择Pin9脚,
    GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化PB9       

    //设置PA1/PB9为输入源的外设中断 EXTI参数
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//打开复用时钟

	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);	//选择中断源1,根据pin_x选择,x是几选几

	EXTI_InitTypeDef EXTI_InitStructure; //EXTI_InitTypeDef类型的结构体,用于设置PA1的中断参数
	EXTI_InitStructure.EXTI_Line = EXTI_Line1;	//中断/事件线选择,可选 EXTI0 至 EXTI19,PA1选择1,
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	//EXTI模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;	//EXTI边沿触发事件,可选上升沿触发(EXTI_Trigger_Rising)、下降沿触发 ( EXTI_Trigger_Falling) 或者上升沿和下降沿都触发( EXTI_Trigger_Rising_Falling)
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;	//控制是否使能EXTI线,ENABLE/DISABLE
	EXTI_Init(&EXTI_InitStructure);//初始化外设中断 EXTI

    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9);

    EXTI_InitStructure.EXTI_Line = EXTI_Line9; //中断/事件线选择,可选 EXTI0 至 EXTI19,PB9选择9,
//  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	//EXTI模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。
//	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;	//EXTI边沿触发事件,可选上升沿触发(EXTI_Trigger_Rising)、下降沿触发 ( EXTI_Trigger_Falling) 或者上升沿和下降沿都触发( EXTI_Trigger_Rising_Falling)
//	EXTI_InitStructure.EXTI_LineCmd = ENABLE;	//控制是否使能EXTI线,ENABLE/DISABLE
    EXTI_Init(&EXTI_InitStructure);

//  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//中断优先级分组

	NVIC_InitTypeDef NCIV_InitStructure;
	NCIV_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;	//中断通道设置EXTI1
	NCIV_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;	//抢占优先级为2
	NCIV_InitStructure.NVIC_IRQChannelSubPriority = 3;	//响应优先级3
	NVIC_Init(&NCIV_InitStructure);	//中断源为EXTI1的NVIC初始化

    NCIV_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;	//中断通道设置EXTI9
//	NCIV_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;	//抢占优先级为3
//	NCIV_InitStructure.NVIC_IRQChannelSubPriority = 3;	//响应优先级3
	NVIC_Init(&NCIV_InitStructure);	//中断源为EXTI5的NVIC初始化
	
}


void EXTI1_IRQHandler()
{
	if(EXTI_GetITStatus(EXTI_Line1) != RESET)
	{
		Clear_TIM7_Timing10msCount();
		TIM_Cmd(TIM7,ENABLE);
		GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction) 1);
		EXTI_ClearITPendingBit(EXTI_Line1);			
	}		
}

void EXTI9_5_IRQHandler()
{
	if(EXTI_GetITStatus(EXTI_Line9) != RESET)
	{
		Clear_TIM7_Timing10msCount();
		TIM_Cmd(TIM7,DISABLE);
		GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction) 0);
		EXTI_ClearITPendingBit(EXTI_Line9);			
	}		
}

/*主函数*/
int main(void)
{   
    Timer7_InitConfig(10000, 720);
    GpioInterrupt_Init();
    Gpio_PB6_Init();
    while(1)
	{
        
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
首先,需要确定要使用哪个外部中断线,以及触发方式(上升沿、下降沿、双边沿触发)。然后,需要配置相关的GPIO引脚为外部中断输入,以及NVIC中断向量表中相应的中断优先级。最后,使用库函数进行外部中断初始化和处理。 以下是一个示例代码,使用外部中断线0,触发方式为上升沿触发,对应的GPIO引脚为PA0: ```c #include "stm32f10x.h" #include "stm32f10x_exti.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" void EXTI0_IRQHandler(void) { // 处理中断事件 // ... EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志位 } int main() { // 使能GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置PA0为输入模式 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入 GPIO_Init(GPIOA, &GPIO_InitStructure); // 使能AFIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 将PA0映射到EXTI_Line0 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); // 配置EXTI_Line0为上升沿触发 EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line = EXTI_Line0; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); // 配置中断优先级 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); while (1) { // 主循环 // ... } } ``` 在上面的代码中,通过GPIO_InitStructure结构体配置PA0为上拉输入模式;通过EXTI_InitStructure结构体配置EXTI_Line0为上升沿触发,并将其映射到GPIOA的PA0引脚;通过NVIC_InitStructure结构体配置EXTI0_IRQn中断的优先级和使能中断。在EXTI0_IRQHandler中可以处理中断事件,同时需要在最后调用EXTI_ClearITPendingBit函数清除中断标志位,以允许下一次中断触发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值