您的当前位置:首页正文

外部中断实现按键识别实验

2022-01-24 来源:客趣旅游网
外部中断实现按键识别实验

二、预备知识

外部中断建立过程 启动代码文件

建立中断向量表 startup_stm32f10x yy. s 分配栈空间并初始化 GPIO初始化 用户应用主程序文件

main. C

EXTI中断线引脚映射 EXTI中断初始化 中断服务程序文件 stm32f10x it.c

NVIC初始化,中断使能 编写对应的中断服务程序 STM32F10x的NVIC相关库函数: 函数NVIC_Init: 函数名 函数原形 功能描述 输入参数 输出参数 返回值 先决条件 NVIC_Init void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) 根据 NVIC_InitStruct 中指定的参数初始化外设 NVIC 寄存器 NVIC_InitStruct:指向结构 NVIC_InitTypeDef 的指针,包含了外设 GPIO 的配置信息 无 无 无 被调用函数 无 typedef struct {

uint8_t NVIC_IRQChannel;

uint8_t NVIC_IRQChannelPreemptionPriority; uint8_t NVIC_IRQChannelSubPriority; FunctionalState NVIC_IRQChannelCmd; } NVIC_InitTypeDef;

参数NVIC_IRQChannel用以使能或失能指定的IRQ通道。

WWDG_IRQn PVD_IRQn RTC_ IRQn RCC_IRQn

TAMPER_ IRQn Flashltf_IRQn

窗口看门狗中断

PVD通过EXTI探测中断 篡改中断 RTC全局中断 FLASH全局中断 RCC全局中断

EXTI0_IRQn EXTI1_IRQn EXTI2_IRQn EXTI3_IRQn EXTI4_IRQn

外部中断线0中断 外部中断线1中断 外部中断线2中断 外部中断线3中断 外部中断线4中断 DMA通道1中断 DMA通道2中断 DMA通道3中断 DMA通道4中断 DMA通道5中断 DMA通道6中断 DMA通道7中断 ADC全局中断

USB高优先级或者CAN发送中断 USB低优先级或者CAN接收0中断 CAN接收1中断 CAN SCE中断 外部中断线9~5中断 TIM1暂停中断 TIM1刷新中断 TIM1触发和通信中断 TIM1捕获比较中断 TIM2全局中断 TIM3全局中断 TIM4全局中断 I2C1事件中断 I2C1错误中断 I2C2事件中断 I2C2错误中断 SPI1全局中断 SPI2全局中断 USART1全局中断 USART2全局中断 USART3全局中断 外部中断线15~10中断 RTC闹钟通过EXTI线中断 USB通过EXTI线从悬挂唤醒中断

DMAChannel1_IRQn DMAChannel2_IRQn DMAChannel3_IRQn DMAChannel4_IRQn DMAChannel5_IRQn DMAChannel6_IRQn DMAChannel7_IRQn ADC_IRQn

USB_HP_CANTX_IRQn CAN_RXI_IRQn CAN_SCE_IRQn EXTI9_5_IRQn TIM1_BRK_IRQn TIM1_UP_IRQn TIM1_CC_IRQn TIM2_IRQn TIM3_IRQn TIM4_IRQn

USB_LP_CAN_RX0_IRQn

TIM1_TRG_COM_IRQn

I2C1_EV_IRQn I2C1_ER_IRQn I2C2_EV_IRQn I2C2_ER_IRQn SPI1_IRQn SPI2_IRQn

USART1_IRQn USART2_IRQn USART3_IRQn EXTI15_10_IRQn RTCAlarm_IRQn USBWakeup_IRQn

函数NVIC_PriorityGroupConfig: 函数名 函数原形 功能描述 输入参数 输出参数 NVIC_PriorityGroupConfig void NVIC_PriorityGroupConfig(u32 NVIC_PriorityGroup) 设置优先级分组:先占优先级和从优先级 NVIC_PriorityGroup:优先级分组位长度 参阅 Section: NVIC_PriorityGroup 查阅更多该参数允许取值范围 无 返回值 先决条件 被调用函数 无 优先级分组只能设置一次 无 STM32F10x的EXTI相关库函数: 函数EXTI_Init: 函数名 函数原形 功能描述 输入参数 输出参数 返回值 先决条件 被调用函数 EXTI_Init void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) 根据 EXTI_InitStruct 中指定的参数初始化外设 EXTI 寄存器 EXTI_InitStruct:指向结构 EXTI_InitTypeDef 的指针,包含了外设 EXTI 的配置信息,参阅 Section: EXTI_InitTypeDef 查阅更多该参数允许取值范围 无 无 无 无 EXTI_InitTypeDef定义于头文件“stm32f103x_exit.h”: typedef struct {

uint32_t EXTI_Line; EXTIMode_TypeDef EXTI_Mode; EXTITrigger_TypeDef EXTI_Trigger; FunctionalState EXTI_LineCmd; }EXTI_InitTypeDef;

函数EXTI_GetITStatus: 函数名 函数原形 功能描述 输入参数 输出参数 返回值 先决条件 被调用函数 函数名 函数原形 功能描述 输入参数 输出参数 返回值 先决条件 EXTI_GetITStatus ITStatus EXTI_GetITStatus(u32 EXTI_Line) 检查指定的 EXTI 线路触发请求发生与否 EXTI_Line:待检查 EXTI 线路的挂起位 参阅 Section: EXTI_Line 查阅更多该参数允许取值范围 无 EXTI_Line 的新状态(SET 或者 RESET) 无 无 EXTI_ClearFlag void EXTI_ClearFlag(u32 EXTI_Line) 清除 EXTI 线路挂起标志位 EXTI_Line:待清除标志位的 EXTI 线路 无 无 无 函数EXTI_ClearFlag: 被调用函数 函数名 函数原形 功能描述 输入参数 1 无 GPIO_EXTILineConfig void GPIO_EXTILineConfig(u8 GPIO_PinSource) 选择 GPIO 管脚用作外部中断线路 GPIO_PortSource: 选择用作外部中断线源的 GPIO 端口 参阅 Section: GPIO_PortSource 查阅更多该参数允许取值范围 GPIO_PinSource:待设置的外部中断线路 该参数可以取 GPIO_PinSourcex(x 可以是 0-15) 无 无 无 无 GPIO_PortSource, u8 EXTI中断线GPIO引脚映射库函数: 输入参数 2 输出参数 返回值 先决条件 被调用函数 三、实验步骤: 功能描述:程序运行后背光灯亮,按下左键背光灯灭,按下右键背光灯亮,按键是通过外部中断实现的。

1、设置相应的时钟

打开PA 、PB端口时钟,并且打开复用时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO,ENABLE);

STM32 的所有 GPIO 都引入到 EXTI 外部中断线上,使得所有的GPIO 都

能作为外部中断的输入源,所以如果把 GPIO 用作 EXTI 外部中断时,还需要开启 AFIO 时钟。 2、设置好相应的中断

设置相应的中断实际上就是设置NVIC,在STM32的固件库中有一个结构体NVIC_InitTypeDef,里面有相应的标志位设置,然后再用NVIC_Init()函数进行初始化。详细代码如下:

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择中断分组2 NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //选择中断通道号

//抢占式中断优先级设置为1

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //响应式中断优先级设置为1

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断 NVIC_Init(&NVIC_InitStructure); //中断初始化

由于有2个中断,需要有2个bit来指定抢占优先级,所以选择第2组。又由于EXTI15-10共用一个中断响应函数,所以EXTI14,EXTI15选择的中断通道是EXTI15_10_IRQn,详细信息可以在头文件中查询得到。用到的NVIC相关的库函数在stm32f10x_nivc.c中,需要将此文件复制并添加到工程中。 3、IO口初始化

连接外部中断的引脚需要设置为输入状态 GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15; //选择引脚14,15 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出最大50MHz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //内部上拉输入 GPIO_Init(GPIOB,&GPIO_InitStructure); //设置PB.14/PB.15 4、把相应的IO口设置为中断线路

由于GPIO并不是专用的中断引脚,因此在用GPIO来触发外部中断的时候需要设置将GPIO相应的引脚和中断线连接起来。 EXTI_InitTypeDef EXTI_InitStructure; //清空中断标志 EXTI_ClearITPendingBit(EXTI_Line14); EXTI_ClearITPendingBit(EXTI_Line15);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource15);

EXTI_InitStructure.EXTI_Line = EXTI_Line14|EXTI_Line15;//中断线路14,15

//设置为中断请求,非事件请求

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //设置中断触发方式为下降沿触发

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

EXTI_InitStructure.EXTI_LineCmd = ENABLE; //外部中断使能 EXTI_Init(&EXTI_InitStructure);

至此,中断的配置完毕。不过,现在只能够说该中断已经配置完毕,但还不能使用它。我们还缺少一个中断的执行函数,当中断被触发后,程序要马上跳转到中断函数去执行中断操作,这个函数在工程创建时默认时没有的。需要去添加,而且需要注意的是,中断函数的名称必须是由标准库提供的,否则无法识别。 5、创建中断响应函数

EXTI15_10_IRQHandler 就是中断线EXTI_Line14, EXTI_Line15的中断函数,所以,我们把这个函数添加到工程中即可。最好添加到stm32f10x_it.c 这个文件中,方便管理。

可以在这个函数中添加你想要的功能,代码如下: /************************************************ 函数名称 : EXTI15_10_IRQHandler 功 能 : GPIO中断

*************************************************/ void EXTI15_10_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line14)!=RESET) //中断IO判断

{if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0)

{

Delay_Ms(10); //按键消抖 if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0) {Led_On; //右键背光灯亮

}

} } EXTI_ClearITPendingBit(EXTI_Line14); //别忘记清除中断标志位 if(EXTI_GetITStatus(EXTI_Line15)!=RESET)//中断IO判断

{if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==0)

{

Delay_Ms(10); //按键消抖 if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==0)

{Led_Off; //左键背光灯灭 }

} } EXTI_ClearITPendingBit(EXTI_Line15); //别忘记清除中断标志位 }

6、创建主函数

//例程名称:按键实现外部中断

#include \"stm32f10x.h\" #include \"led.h\"

#include \"systick.h\" #include \"exti.h\"

int main(void) { Delay_Init(); Led_Init(); Exti_Init(); while(1) { } }

因篇幅问题不能全部显示,请点此查看更多更全内容