STM32之EXTI
Posted nwjlq
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32之EXTI相关的知识,希望对你有一定的参考价值。
简介:
exti--外部中断/事件控制器,控制器由20个边沿检测器组成,每个检测器都连接了所有端口对应引脚,每个输入线都可以独立的配置输入类型可触发事件(上升沿/下降沿/双边沿触发)。
功能框图;
图中黄色部分表示每个寄存器都有20个输入线与之相对应
如:中断屏蔽寄存器
寄存器中有20个外部输入线的中断屏蔽标志位。
红色虚线部分为中断部分:边沿检测电路通过上升/下降沿边沿触发选择寄存器对输入线输入的信号进行检测,当检测条件满足时(如:设置上升沿触发,则信号线来了一个上升沿),边沿检测电路输出1给图中的3(或门),或门输出信号传给图中4(与门),如果设置了中断屏蔽寄存器的值为1(表示开发中断请求),则与门输出电平1,请求挂起寄存器对应位置1,图中的5从请求挂起寄存器中取出值给NVIC,从而实现中断控制。
绿色虚线部分为事件部分:图中1 2 3与产生中断一样。图3产生的信号此时电平为1与6(与门)另一个输入信号事件屏蔽寄存器值进行与操作,如果事件屏蔽寄存器的对应位也为1,则输出电平1给脉冲发生器,脉冲发生器接收到电平1后,产生脉冲从图中8输出出去。
中断/事件线:
exti0~15可以对应多个io引脚,通过AFIO寄存器选择具体的引脚。
外部中断初始化结构体:
EXTI_Line:中断线选择,可以选择EXTI0~EXTI19
EXTI_Mode:模式 是产生中断还是事件
EXTI_Trigger:触发类型 是上升沿 下降沿还是双边沿触发
EXTI_LineCmd:是 使能还是失能中断线
实验:
通过开发板上的四个按键对4个LED控制。按下按键LED亮,再按下,LED灭
原理图:
编程思路:
1.初始化4个led端口 和4个按键其中key_up配置成下拉输入,其他按键配置成上拉输入
2.配置中断优先级
3.配置外部中断,在里面记得开启AFIO时钟
4.编写中断程序
exti头文件:
#ifndef _EXTI_H #define _EXTI_H #include "stm32f10x.h" //上键宏定义 #define KEY_UP_CLK RCC_APB2Periph_GPIOA #define KEY_UP_PIN GPIO_Pin_0 #define KEY_UP_PORT GPIOA //左键 #define KEY_LEFT_CLK RCC_APB2Periph_GPIOE #define KEY_LEFT_PIN GPIO_Pin_2 #define KEY_LEFT_PORT GPIOE //下键 #define KEY_DOWN_CLK RCC_APB2Periph_GPIOE #define KEY_DOWN_PIN GPIO_Pin_3 #define KEY_DOWN_PORT GPIOE //右键 #define KEY_RIGHT_CLK RCC_APB2Periph_GPIOE #define KEY_RIGHT_PIN GPIO_Pin_4 #define KEY_RIGHT_PORT GPIOE //LED #define LED_CLK RCC_APB2Periph_GPIOC #define LED_PORT GPIOC #define LED1_PIN GPIO_Pin_0 #define LED2_PIN GPIO_Pin_1 #define LED3_PIN GPIO_Pin_2 #define LED4_PIN GPIO_Pin_3 void EXTI_Config(void); #endif
exti源文件
#include "exti.h" static void LED_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(LED_CLK,ENABLE); //LED1 LED2 LED3 LED4初始化 GPIO_InitStruct.GPIO_Pin=LED1_PIN|LED2_PIN|LED3_PIN|LED4_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(LED_PORT,&GPIO_InitStruct); //默认熄灭 GPIO_SetBits(LED_PORT,LED1_PIN|LED2_PIN|LED3_PIN|LED4_PIN); } static void KEY_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; //开启四个键所对应io端口时钟 RCC_APB2PeriphClockCmd(KEY_UP_CLK|KEY_LEFT_CLK|KEY_DOWN_CLK|KEY_RIGHT_CLK,ENABLE); //上键 GPIO_InitStruct.GPIO_Pin=KEY_UP_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPD;//下拉输入模式 GPIO_Init(KEY_UP_PORT,&GPIO_InitStruct); //左键 GPIO_InitStruct.GPIO_Pin=KEY_LEFT_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;//上拉输入模式 GPIO_Init(KEY_LEFT_PORT,&GPIO_InitStruct); //下键 GPIO_InitStruct.GPIO_Pin=KEY_DOWN_PIN; GPIO_Init(KEY_DOWN_PORT,&GPIO_InitStruct); //右键 GPIO_InitStruct.GPIO_Pin=KEY_RIGHT_PIN; GPIO_Init(KEY_RIGHT_PORT,&GPIO_InitStruct); } static void KEY_EXTI_Config(void) { EXTI_InitTypeDef EXTI_InitStruct; //使用外部中断 端口复用 重映射需要开启AFIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //上键外部中断配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//外部中断线配置 EXTI_InitStruct.EXTI_Line=EXTI_Line0;//中断线 EXTI_InitStruct.EXTI_LineCmd=ENABLE; EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;//中断模式 EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;//上升沿检测 EXTI_Init(&EXTI_InitStruct); //左键外部中断配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);//外部中断线配置 EXTI_InitStruct.EXTI_Line=EXTI_Line2;//中断线 EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿检测 EXTI_Init(&EXTI_InitStruct); //下键外部中断配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);//外部中断线配置 EXTI_InitStruct.EXTI_Line=EXTI_Line3;//中断线 EXTI_Init(&EXTI_InitStruct); //右键外部中断配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);//外部中断线配置 EXTI_InitStruct.EXTI_Line=EXTI_Line4;//中断线 EXTI_Init(&EXTI_InitStruct); } static void NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组 //上键 NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn;//中断源 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; NVIC_InitStruct.NVIC_IRQChannelSubPriority=1; NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStruct); //左键 NVIC_InitStruct.NVIC_IRQChannel=EXTI2_IRQn;//中断源 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; NVIC_InitStruct.NVIC_IRQChannelSubPriority=2; NVIC_Init(&NVIC_InitStruct); //下键 NVIC_InitStruct.NVIC_IRQChannel=EXTI3_IRQn;//中断源 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; NVIC_InitStruct.NVIC_IRQChannelSubPriority=2; NVIC_Init(&NVIC_InitStruct); //右键 NVIC_InitStruct.NVIC_IRQChannel=EXTI4_IRQn;//中断源 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; NVIC_InitStruct.NVIC_IRQChannelSubPriority=3; NVIC_Init(&NVIC_InitStruct); } void EXTI_Config(void) { LED_GPIO_Config(); KEY_GPIO_Config(); NVIC_Config(); KEY_EXTI_Config(); } //上键中断 void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0)==SET) { if(GPIO_ReadOutputDataBit(LED_PORT,LED1_PIN)) GPIO_ResetBits(LED_PORT,LED1_PIN); else GPIO_SetBits(LED_PORT,LED1_PIN); EXTI_ClearITPendingBit(EXTI_Line0); } } //左键中断 void EXTI2_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line2)==SET) { if(GPIO_ReadOutputDataBit(LED_PORT,LED2_PIN)) GPIO_ResetBits(LED_PORT,LED2_PIN); else GPIO_SetBits(LED_PORT,LED2_PIN); EXTI_ClearITPendingBit(EXTI_Line2); } } //下键中断 void EXTI3_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line3)==SET) { if(GPIO_ReadOutputDataBit(LED_PORT,LED3_PIN)) GPIO_ResetBits(LED_PORT,LED3_PIN); else GPIO_SetBits(LED_PORT,LED3_PIN); EXTI_ClearITPendingBit(EXTI_Line3); } } //右键中断 void EXTI4_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line4)==SET) { if(GPIO_ReadOutputDataBit(LED_PORT,LED4_PIN)) GPIO_ResetBits(LED_PORT,LED4_PIN); else GPIO_SetBits(LED_PORT,LED4_PIN); EXTI_ClearITPendingBit(EXTI_Line4); } }
main 文件:
#include "stm32f10x.h" #include "exti.h" int main(void) { EXTI_Config(); while(1); }
以上是关于STM32之EXTI的主要内容,如果未能解决你的问题,请参考以下文章