STM32学习笔记(九) 外部中断,待机模式和事件唤醒
学会知识只需要不段的积累和提高,但是如何将知识系统的讲解出来就需要深入的认知和系统的了解。外部中断和事件学习难度并不高,不过涉及到STM32的电源控制部分,还是值得认真了解的,在本文中我将以实际代码为例详细讲解这些内容,希望对每一个阅读者有帮助。
1.外部中断
如果已经学习了SysTick系统时钟滴答实验,掌握了Cortex-M3中断的相关知识,那么外部中断也是比较好理解的,和SysTick中断一样,外部中断也是当有信号触发时,如果中断屏蔽寄存器允许触发,就会产生中断,这时CPU查找中断向量表,找到入口函数,就会正确的执行相关代码,因为外部中断本身就是依托于普通GPIO口的上升沿或者下降沿信号的,所以本例中以按键作为测试外部中断的硬件电路。
根据工作原理图:KEY1 ~ PC4; KEY2 ~ PB10;
KEY3 ~ PC13; KEY4 ~ PA0;
其中KEY1,2,3作为外部中断引脚,KEY4作为唤醒引脚,后续会讲解。
知晓了工作原理图,下面就要确定其对应的中断线号了,这个在参考手册外部中断/事件线路映像章节中有详细的说明,这里截图部分:

从上面可以看出,不同区域的相同位置的管脚共用同一个中断线号,依次类推,上面的四个管脚分别对应的中断线号为EXIT4, EXIT10, EXIT13,EXIT0,在这里还有个注意点:那就是一个中断线号只能反过来对应一个管脚,这就需要设计外部中断硬件电路时不要重复,如PA0和PB0不能同时设计为外部中断。
了解了这些之后,如果熟悉STM32设计流程的话,那么就知道顺序是:
1.外部中断管脚GPIO初始化,代码如下:
/****************************************************************
* function : EXTI_GPIO_Config * Description : 外部中断触发对应GPIO口配置
KEY1 PC4 外部中断4
KEY2 PB10 外部中断10
KEY3 PC13 外部中断13
KEY4 PA0 WAKEUP唤醒事件 * input : 无 * output : 无
*****************************************************************/
void EXTI_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB
| RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = EXTI_KEY1_Pin;
GPIO_Init(EXTI_KEY1_Port, &GPIO_InitStructure);
GPIO_EXTILineConfig(EXTI_KEY1_PortSource, EXTI_KEY1_PinSource); //将GPIO复用为外部中断触发端口 GPIO_InitStructure.GPIO_Pin = EXTI_KEY1_Pin;
GPIO_Init(EXTI_KEY2_Port, &GPIO_InitStructure);
GPIO_EXTILineConfig(EXTI_KEY2_PortSource, EXTI_KEY2_PinSource); GPIO_InitStructure.GPIO_Pin = EXTI_KEY3_Pin;
GPIO_Init(EXTI_KEY3_Port, &GPIO_InitStructure);
GPIO_EXTILineConfig(EXTI_KEY3_PortSource, EXTI_KEY3_PinSource); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Pin = EXTI_KEY4_Pin;
GPIO_Init(EXTI_KEY4_Port, &GPIO_InitStructure);
GPIO_EXTILineConfig(EXTI_KEY4_PortSource, EXTI_KEY4_PinSource);
}
2.外设EXTI初始化
3.在中断屏蔽寄存器中允许对应中断触发
/****************************************************************
* function : EXTI_MODE_Config * Description : 外部中断触发配置及向量表开启对应中断
其中KEY1作为中断进入_WFE模式
KEY2和KEY3作为普通中断点亮对应LED灯
KEY4作为事件用来唤醒CPU * input : 无 * output : 无
*****************************************************************/
void EXTI_MODE_Config(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure; EXTI_DeInit(); EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //外部按键触发中断
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //外部中断使能
EXTI_InitStructure.EXTI_Line = EXTI_KEY1_Line; //外部中断线号4
EXTI_Init(&EXTI_InitStructure); EXTI_InitStructure.EXTI_Line = EXTI_KEY2_Line; //外部中断线号10
EXTI_Init(&EXTI_InitStructure); EXTI_InitStructure.EXTI_Line = EXTI_KEY3_Line; //外部中断线号13
EXTI_Init(&EXTI_InitStructure); EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event; //外部按键触发事件
EXTI_InitStructure.EXTI_Line = EXTI_KEY4_Line; //外部中断线号0
EXTI_Init(&EXTI_InitStructure);
//PWR_WakeUpPinCmd(ENABLE); //PA0作为唤醒引脚使能 NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0); //向量表位于FLASH中,偏移0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /*在向量表中激活对应的中断线号*/
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStructure.NVIC_IRQChannel = EXTI_KEY1_IRQn;
NVIC_Init(&NVIC_InitStructure); // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
// NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
// NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannelSubPriority = ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStructure.NVIC_IRQChannel = EXTI_KEY2_3_IRQn;
NVIC_Init(&NVIC_InitStructure);
}
4.中断函数处理
按键PC4对应外部中断入口,因为按键默认高电平,当有按键按下时,就会产生下降沿信号,触发中断,此时CPU就在中断向量表里查询外部中断的入口地址,如PC4对应的入口地址就是void EXTI4_IRQHandler(void) ,开始执行中断中内容,具体实现流程可参考SysTick章节。
/****************************************************************
* function : EXTI4_IRQHandler * Description : 外部中断4入口函数,实现LED点亮以及系统进入_WFE模式 * input : 无 * output : 无
*****************************************************************/
void EXTI4_IRQHandler(void)
{
led_light_up();
EXTI_ClearFlag(EXTI_Line4); //清除中断线号4
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE); //进入WFE停止低功耗模式 仅事件能唤醒
SystemInit(); //退出STOP模式要初始化时钟,因为睡眠时切换到内部时钟
LED1_OFF();
}
在stm32的头文件和启动文件设计中,中断线号10~15共用相同的入口函数,因此需要在中断中进行判断,来确定是那个信号触发了中断。
/****************************************************************
* function : EXTI15_10_IRQHandler * Description : 外部中断10和13共用中断入口,通过触发后状态检查确定
触发中断的管脚并执行相应代码。 * input : 无 * output : 无
*****************************************************************/
void EXTI15_10_IRQHandler(void)
{
ITStatus EXTI10_Status;
ITStatus EXTI13_Status;
EXTI10_Status = EXTI_GetITStatus(EXTI_Line10); //获得外部中断10的状态
EXTI13_Status = EXTI_GetITStatus(EXTI_Line13); //获得外部中断13的状态
if(EXTI10_Status == SET)
{
led_light_up();
}
if(EXTI13_Status == SET)
{
led_light_up();
}
EXTI_ClearFlag(EXTI_Line10 | EXTI_Line13); /*清除外部中断10或者13的挂起位 */
}
外部中断涉及到的知识并并不多,不过仔细观察上面的代码,就会发现KEY4(PA0)并没有配置为中断,而配置为了事件,且被设置为唤醒引脚,KEY1(PC4)在中断里不只点亮了LED,还调用了PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE); 这种功能其实很有用,涉及到低功耗和外部事件唤醒,下面我来详细说明。
2.外部事件和中断的区别和联系
外部事件和中断都是由管脚信号触发的,参考下图:

这张图可以很直观的看出中断和事件的区别,当外部有信号输入时,如果通过了事件屏蔽寄存器,那么事件信号就进入脉冲触发器,引发一个脉冲信号,直接传递给相应的外设,用于触发,这就是一个纯硬件的过程,理解DMA的应该知道,这个方式不需要CPU参与,但是这也有它的缺点,如功能比较单一,仅能提供信号,不能提供信息,也就是只能产生指定功能的事件。如果通过中断屏蔽寄存器,就被直接送到CPU中,产生中断,如进入上面的入口函数开始处理。从这就可看出,事件是单纯硬件触发执行的过程,与CPU本身设计支持有关,而中断中则可以软件实现各种功能,而低功耗模式和事件唤醒就是stm32支持的事件之一。
3.低功耗模式和事件唤醒
低功耗模式是嵌入式设计用于可移动设备的重要功能,在这种状态下,CPU会关闭时钟,从而降低耗电,延长单次使用时间。

上面进入的就是停机-低功耗-WFE模式,因此只能由按键4事件唤醒。其实低功耗模式还有待机模式以及睡眠模式,这里并没有使用到,以后如果用到会穿插讲解。中断无法唤醒,另外,当CPU退出停止模式时,会强制切换到内部时钟,因此在进入停止模式后一句要加上SystemInit()重新配置系统时钟,避免时钟改变。具体代码参考:http://files.cnblogs.com/files/zc110747/7.EXTI_LED.7z
STM32学习笔记(九) 外部中断,待机模式和事件唤醒的更多相关文章
- stm32寄存器版学习笔记03 外部中断
stm32的每个I/O口都可以作为中断输入,要把I/O口设置为外部中断输入,必须将I/O口设置为上拉/下拉输入 或 浮空输入(但浮空的时候外部一定要带上拉或下拉电阻,否则可能导致 中断不停的触发),干 ...
- stm32学习笔记——外部中断的使用
stm32学习笔记——外部中断的使用 基本概念 stm32中,每一个GPIO都可以触发一个外部中断,但是,GPIO的中断是以组为一个单位的,同组间的外部中断同一时间只能使用一个.比如说,PA0,PB0 ...
- STM32学习笔记(四)——串口控制LED(中断方式)
目录: 一.时钟使能,包括GPIO的时钟和串口的时钟使能 二.设置引脚复用映射 三.GPIO的初始化配置,注意要设置为复用模式 四.串口参数初始化配置 五.中断分组和中断优先级配置 六.设置串口中断类 ...
- STM32学习笔记-NVIC中断知识点
STM32学习笔记-NVIC中断知识点总结 中断优先级设置步骤 1. 系统运行后先设置中断优先级分组 函数:void NVIC_PriorityGroupConfig(uint32_tNVIC_Pri ...
- stm32学习笔记----双串口同时打开时的printf()问题
stm32学习笔记----双串口同时打开时的printf()问题 最近因为要使用串口2外接PN532芯片实现通信,另一方面,要使用串口1来将一些提示信息输出到上位机,于是重定义了printf(),使其 ...
- STM32学习笔记——点亮LED
STM32学习笔记——点亮LED 本人学习STM32是直接通过操作stm32的寄存器,使用的开发板是野火ISO-V2版本: 先简单的介绍一下stm32的GPIO: stm32的GPIO有多种模式: 1 ...
- 并发编程学习笔记(9)----AQS的共享模式源码分析及CountDownLatch使用及原理
1. AQS共享模式 前面已经说过了AQS的原理及独享模式的源码分析,今天就来学习共享模式下的AQS的几个接口的源码. 首先还是从顶级接口acquireShared()方法入手: public fin ...
- STM32学习笔记——OLED屏
STM32学习笔记--OLED屏 OLED屏的特点: 1. 模块有单色和双色可选,单色为纯蓝色,双色为黄蓝双色(本人选用双色): 2. 显示尺寸为0.96寸 3. 分辨率为128*64 4. ...
- stm32中断优先级管理与外部中断编程
stm32中断优先级管理与外部中断编程 中断优先级管理 外部中断编程 官方示例程序 exti.h #ifndef __EXTI_H #define __EXIT_H #include "sy ...
随机推荐
- 滚轮事件js
<!DOCTYPE html> <html> <head> <title>jane</title> <style>div ...
- phpcms 导航栏点击栏目颜色定位方法和phpcms list页实现分页
另:一个栏目下面如果没有子栏目,那么它调用的模板就是列表页模板(及list_为前缀的模板):如果一个栏目下面有子栏目,那么它调用的就是栏目首页模板(category_为前缀的模板). 当你这个栏目添加 ...
- 解决python "Non-ASCII character"错误
原文http://jingyan.baidu.com/article/219f4bf7d04887de442d3899.html 1.出现问题的原因:程序中的编码错误,python默认是acii模式, ...
- 最长公共子序列PK最长公共子串
1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. (1)递归方法求最长公共子序列的长度 1) ...
- spring boot servlet、filter、listener
http://blog.csdn.net/catoop/article/details/50501686
- LeetCode Two Sum II - Input array is sorted
原题链接在这里:https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/ 题目: Given an array of intege ...
- 解决 git 中文路径显示 unicode 代码的问题
解决 git 中文路径显示 unicode 代码的问题 当被修改的文件中带有中文字符时,中文字符会被转换为 unicode 代码,看不出原来的文件名. 这时,只要配置 :: git config -- ...
- Python基础、 内置函数
一.概述 Python中内置了很多函数: 可以通过help().dir()方式查看函数的功能,使用内置函数通常效率更高 abs() abs函数接收一个数字对象,返回它的绝对值,如果接受的对象不是数字抛 ...
- Vcenter server 5.5添加用户角色及分配权限
角色:各种角色定义了对此角色可操作细节的权限组合. 用户权限:用户权限是对ESXi 5.0中的对象实例(如ESXi 5.0主机,虚拟机,存储,网络等)进行权限的分配.通过在这些对象上绑定“用户+角色” ...
- tcp_tw_recycle 的问题, 使用某一个wifi,APP老是连接不上网络
ss -tan 反映出来的情况就是在服务器上抓包,发现有SYN包,但服务器就是不回ACK包,因为SYN包已经被丢弃了.为了验证这一结果,可以执行netstat -s | grep timestamp ...