目录
如果PA0 PB0 PC0 都连接到EXTI0的时候怎么办?
EXTI简介
EXTI(External interrupt/event controller)—外部中断/事件控制器,管理了控制器的 20 个中断/事 件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的 检测。
EXTI功能框图
EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件,这两个功能从硬件上就有所 不同。 首先我们来看图EXTI功能框图中红色虚线指示的电路流程。它是一个产生中断的线路,最终信 号流入到NVIC控制器内。
编号1是输入线,EXTI控制器有19个中断/事件输入线,这些输入线可以通过寄存器设置为任 意一个GPIO,也可以是一些外设的事件
编号2是一个边沿检测电路,它会根据上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择 寄存器(EXTI_FTSR)对应位的设置来控制信号触发。。边沿检测电路以输入线作为信号输入端,如 果检测到有边沿跳变就输出有效信号1给编号3电路,否则输出无效信号0。而EXTI_RTSR和EXTI_FTSR两个寄存器可以控制需要检测哪些类型的电平跳变过程,可以是只有上升沿触发、只 有下降沿触发或者上升沿和下降沿都触发
EXTI_Line:输入线的选择是通过AFIO来选择的,这里的EXTI_Line是为了编程的时候,编程寄存器的哪一个位
EXTI_Mode :事件EXTI_Mode_Event和中断EXTI_Mode_Interrupt两种模式
EXTI_Trigger:上升沿,下降沿,上升沿和下降沿
GPIO中断实验
1-初始化要连接到EXTI的GPIO
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK, ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin=KEY1_INT_GPIO_PIN;
GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStruct);
2-初始化EXTI用于产生中断/事件
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_Falling;
EXTI_Init(&EXTI_InitStruct);
3-初始化NVIC,用于处理中断
static void nvic_exti_config(void)//加上static说明这个函数只能被bsp_exti.c这个文件调用
{
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;//主优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;//子优先级
NVIC_Init(&NVIC_InitStruct);
}
4-编写中断服务函数
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0)!=0)//确保是该中断线产生的中断
{
LED_G_TOGGLE;
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
5-main函数
int main(void)
{
led_init();
exti_key_init();
while(1)
{
}
}
bsp_exti.c代码
#include "bsp_exti.h"
static void nvic_exti_config(void)//加上static说明这个函数只能被bsp_exti.c这个文件调用
{
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;//主优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;//子优先级
NVIC_Init(&NVIC_InitStruct);
}
void exti_key_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
//配置中断优先级
nvic_exti_config();
//初始化GPIO
RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK, ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin=KEY1_INT_GPIO_PIN;
GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStruct);
//初始化EXTI
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_Falling;
EXTI_Init(&EXTI_InitStruct);
}
bsp_exti.h代码
#ifndef _BSP_EXTI_H
#define _BSP_EXTI_H
#include "stm32f10x.h"
#define KEY1_INT_GPIO_PIN GPIO_Pin_0
#define KEY1_INT_GPIO_PORT GPIOA
#define KEY1_INT_GPIO_CLK RCC_APB2Periph_GPIOA
void exti_key_init(void);
#endif
如果PA0 PB0 PC0 都连接到EXTI0的时候怎么办?
可以在中断服务函数中进行判断,比如判断GPIOA->IDR,GPIOB->IDR