总结STM32外部中断

weixin_52131122 2021-04-04 05:27:38

实验效果:用外部中断,实现PA1上接按键,选择上升沿触发中断,中断PB1上闪烁的LED,


先来看看配置外部中断的整体代码,然后再一个函数一个函数的解释

[color=#00FFFF]#include "exti.h"
/*
初始化总中断NVIC
*/
static void NVIC_Configur(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*************************/
/*
初始化GPIO口,GPIOA_PIN1
*/
void GPIO_Configur(void)
{
GPIO_InitTypeDef GPIO_InitStructure ; //命名GPIO初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//选择PIN
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING; //悬浮输入
GPIO_Init(GPIOA,&GPIO_InitStructure);//调用初始化函数
}
/**************************/
/*
告诉GPIO那个引脚作为外部中断引脚
*/
void AFIO_Configur(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能AFIO的时钟
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);
}
/******************************/
/*
配置EXTI
*/
void EXTI_Configur(void)
{
NVIC_Configur();
GPIO_Configur();
AFIO_Configur();
EXTI_InitTypeDef EXTI_InitStructure;//命名ETTI初始化结构体
EXTI_InitStructure.EXTI_Line=EXTI_Line1;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
[/color]
****************************************************************************************************
****************************************************************************************************
****************************************************************************************************
先来看看第一个函数
static void NVIC_Configur(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}[/align]

为什么要编写这段函数呢?
先来看看NVIC的全称(Nested vectoredinterrupt controller)即嵌套向量中断控制器
由于STM32的中断系统非常强大,每个GPIO都能产生中断,所以需要一个能管理这些中断的控制器
下面是32的中断和事件,我只放出了一部分,还有很多可以在STM参考手册上看


那NVIC到底是怎么管理这些中断的,我们从函数一个一个看

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
32的中断优先级是可以自己设置的,所以我们要先给他配置优先级,所以这是给他的优先级选组的函数,为什么要选组先这个表

左边NVIC_IRQChannelPreemptionPriority是主优先级,右边NVIC_IRQChannelSubPriority是次优先级
每个组都有对应的主次优先级的选择范围,32会先比较主优先级,如果主优先级都一样,会比较次优先级,如果主次都一样,会用32自己配置的优先级。

NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

这四段函数,开始配置NVIC结构体的成员。

第一段函数,是选择你要用的中断的名字 ,名字在stm32f10x.h文件中找(随便补充一下,关于NVIC的函数可以在misc.h中找到)
EXTI1有0-15个,分别对应16个IO口,我们要用PA1,所以就选EXTI1


第二,三段函数,就是选择中断的主次优先级

第四段使能NVIC

然后初始化结构体,命名初始化,这些库函数套路程序就不解释了

配置GPIO,凡是要用GPIO都要配置它,要注意输入的时候悬浮输入和不用配置频率
void GPIO_Configur(void)
{
GPIO_InitTypeDef GPIO_InitStructure ; //命名GPIO初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//选择PIN
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING; //悬浮输入
GPIO_Init(GPIOA,&GPIO_InitStructure);//调用初始化函数
}

/**************************/
/*
告诉GPIO那个引脚作为外部中断引脚
*/
void AFIO_Configur(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能AFIO的时钟
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);
}

PS:记得使能AFIO的时钟

最后一步配置外部中断EXTI
void EXTI_Configur(void)
{
NVIC_Configur();
GPIO_Configur();
AFIO_Configur();
EXTI_InitTypeDef EXTI_InitStructure;//命名ETTI初始化结构体
EXTI_InitStructure.EXTI_Line=EXTI_Line1;//初始化那个EXTI
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//选择中断模式
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//选择上升沿触发
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure);
}

然后在主函数中,写中断服务函数
在51中编写中断服务函数的名字可以直接编写,只要后面加个入口标志就行了
但是32已经有编好的中断服务函数,在启动文件里面可以找到


void EXTI1_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line1)==1) /*如果一条线上有PA0 PB0,如何判断是那个触发的中断?
{ 先判断总线,再判断IO口的电平(操作寄存器) */
Delay(3000000);
EXTI_ClearFlag(EXTI_Line1);/*清除触发标志*/
}
}

调用函数EXTI_GetITStatus(),如果有外部中断被触发,函数会返回一个1

/*如果一条线上有PA0 PB0,如何判断是那个触发的中断?这是野火教学视频留下的一个问题
我觉得 先判断总线,再判断IO口的电平(操作寄存器) 就可以了*/
这个题目就是让我们明白,不要只会调用库函数,还要懂得,这些库函数操作了那些寄存器。
还有就是EXTI_ClearFlag(EXTI_Line1);/*清除触发标志*/,这个函数,EXTI_GetITStatus()返回一个1本质是吧挂起寄存器置1了
然后它不会自动清0;所以要用EXTI_Clear



...全文
499 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_52131122 2021-04-21
  • 打赏
  • 举报
回复
再补充一下,51单片机的外部引脚口是设置好的,而三二没有,所以外部引脚口要自己配置。
weixin_52131122 2021-04-21
  • 打赏
  • 举报
回复
补充一下,EXTIX(0<x<22)中断/事件线有23条,其中0-15代表GPIO(A,B,C,D.....)X
1030486762567 2021-04-13
  • 打赏
  • 举报
回复
水分加我一个
EV-LI 2021-04-04
  • 打赏
  • 举报
回复
博主,这贴很良心,新手小白的我看了后,很快就懂了,望日更。
EV-LI 2021-04-04
  • 打赏
  • 举报
回复
博主,这贴很良心,新手小白的我看了后,很快就懂了,望日更。

27,383

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧