历史上的今天
今天是:2024年09月11日(星期三)
2019年09月11日 | STM32Cube-EXTI
2019-09-11 来源:eefocus
这一章用上一章GPIO的工程修改。复制GPIO的工程,修改文件夹名。点击xxxx.ioc打开STM32cubeMX的工程文件重新配置。PA0管脚重新配置为GPIO_EXIT0模式。

WAKEUP按键已经外部下拉,按下是PA0为高电平。在GPIO配置中配置PA0为上升沿触发。内部下拉,添加用户标签WAKEUP。



在NVIC(嵌套向量中断控制器)中,勾选EXIT Line0 interrupt使能PA0中断。右边两个选项设置抢占优先级和响应优先级。此处我们选择默认的,不修改。


在这里简单介绍一下NVIC(嵌套向量中断控制器)。NVIC就是控制中断响应的。主要由三个参数,一个是中断使能,一个是抢占优先级,还有一个就是响应优先级。(优先级数值越小,优先级别越高)
中断使能很好理解,就是是否开启中断,如果开启中断,则满足中断触发条件时程序会跳到中断服务程序运行,否则不响应中断主程序继续运行。
抢占优先级是用来判断一个中断是否可以打断另外一个中断的中断服务程序抢先运行。例如A中断触发,正在运行A中断的服务程序,此时B中断也触发,如果B中断的抢占优先级比A的高,则程序会打断A的中断服务程序,去运行B的中断服务程序,即中断嵌套。等B的中断服务程序运行完后继续运行A的中断服务程序。如果B的抢占优先级没有高过A的抢占优先级,则程序不会打断A的中断服务程序,而是待定A的中断服务程序运行完成后才运行B的中断服务程序。
响应优先级是用来判断抢占优先级相同的几个中断那个中断会优先响应。如果几个抢占优先相同的中断同时触发,那么响应优先级高的最先运行。
判断中断的优先级,先看抢占优先级,抢占优先级高的中断优先级别高。抢占优先级相同的情况下,响应优先高的中断优先级别高。抢占优先级和响应优先级相同的情况下,更加中断向量表确定。
在这里简单讲解一下优先级分组。STM32以4个比特位表示中断的抢占优先级和响应优先级。中断优先级分组是为了给抢占式优先级和响应优先级在中断优先级寄丛器的四个比特位分配各个优先级数字所占的位数。例如3位用于抢占优先级(优先级有2^3=8种优先级),1位用于响应优先级(优先级有2^1=2种优先级)。

在这里我们就配置好stm32CubeMX工程,重新生成报告,以及重新生成代码,编译程序。
打开main.c文件。把main()函数里while循环上一章的代码删掉,while循环里面为空。在main.c文件后面USER CODE BEGIN 4 和 USER CODE END 4 中间添加中断回调函数。

中断函数里面先判断是否为EXIT线0中断,如果是则LED2的状态翻转。在STM32F1的数据手册中可以找到下面这张图。PA0为EXTI线0中断。

重新编译程序,编译通过后下载到开发板。如果没有错误,按下一下WAKEUP按键LED2的状态改变一次。
下面简单讲解一下中断程序的运行流程。首先main函数主程序中一直在while循环里面执行。当按键(PA0引脚)按下时,边沿检测电路检测到上升沿,触发中断,设置中断标识位。NVIC中断控制器判断EXTI0中断优先是否为最高,若为最高优先级则执行EXIT0中断。

再执行中断服务函数之前,内核先将现在使用到的寄存器和主程序中断点的地址压入堆栈(保护现场)。然后程序在中断向量表中找到EXTI0中断对应的地址(0x0000 0058)。这个地址存储的为EXTI0中断服务函数的口人地址。然后程序转跳到中断服务函数执行。

在startup_stm32f103xe.s启动文件中,我们可以找到中断向量表。

在stm32f1xx_it.c中断服务函数文件中,我们可以找到EXTI0中断的服务函数。

中断服务函数里面就调用了GPIO外部中断处理函数HAL_GPIO_EXTI_IRQHandler(),参数为GPIO_PIN_0,即EXTI0中断。GPIO外部中断处理函数主要就是清除中断标识位,然后调用中断回调函数HAL_GPIO_EXTI_Callback()。我们只需重构中断回调函数,在函数里面添加我们的应用代码即可(程序中为翻转LED2状态)。

执行完中断服务函数后。内核从堆栈去除压入的寄存器数据恢复现场,取出主程序中断点的地址,转到到主程序中断点的地址继续运行主程序。
到这里就完成一次中断服务。简单的来说,触发中断时,硬件先标识中断标识位,然后NVIC中断控制器判断中断优先级是否可以执行此中断。执行中断时,先保护现在程序的状态,将数据保存进堆栈中,执行完中断服务函数后,再在堆栈中取数据回复现场,跳回主程序继续运行。如果在中断服务函数中有更高优先级的中断触发,则也会将现在的数据保存去执行更高优先级的中断服务函数,即中断嵌套。高优先级的中断执行完后,恢复现场,继续执行低优先级的服务函数。
下一篇: STM32Cube-按键控制LED
史海拾趣
|
CE6.0下关于InterruptInitialize()的问题 请教了,我在CE6.0下,在应用程序里面调用InterruptInitialize()出错,我的系统逻辑中断是物理中断+SYSINTR_FIRMWARE直接得到的,是不是CE6.0不允许应用程序调用InterruptInitialize()函数?还有,就是我在驱动程序中使用 KernelIoControl(IO ...… 查看全部问答> |
|
最近一些同事用C++写了一部分代码,近半年写出来的代码映象要比我们积累了10年的代码编译出来还要大. 我用NMPPC讲变量大小排序导出,却发现找不出新代码中哪些全局变量或局部变量过大.请问有什么较好的分析方法?… 查看全部问答> |
|
DShow开发用Receive实现格式转换有问题 HRESULT Receive(IMediaSample *pSample) { YUV2RGB565(pSample, m_width, m_height, unsigned char* pRGB); return S_OK; } 在trans filter ...… 查看全部问答> |
|
又弄出新问题了,寻求高人指导(优龙2440开发板换flash后bootloader出现问题flash换成k9k8g08优龙得是k9s1208) static int CheckBadBlk(U32 addr) { U8 dat; addr &= ~0x3f; ...… 查看全部问答> |
|
光耦隔离放大器的输入信号为DSP PWM引脚输出的3.3V的脉冲信号,输出信号接MOSFET的栅极,希望输出信号的幅值可以达到15V,应该选用什么型号. 望高手指点.谢谢!!… 查看全部问答> |
|
我们最近做了块的TI的stellaris开发板,主要是针对网络应用,所以选择了个老的片子 :LM3S6911,没有用新出的功能更多的9xxx,8xxx系列;还有个想法就是这样成本会降低,这个权当是入门级的LM3S开发板。现在手头除了调试用的2块板子外,还剩18块空板 ...… 查看全部问答> |
|
如图所示是一个电桥式压力传感器,每个桥臂大约是5K的电阻,根据要求使用1.5mA驱动它,设计使用TL431,焊接后发现如果传感器上两个信号输出悬空,不接AD620是正常的,也就是流过传感器电流是1.5ma,当时当接上AD620后测量发现电流下降了而且TL431的 ...… 查看全部问答> |




