今天可能会学得比较多,所以说三四五可能会全部连着一起更新
如果说时间比较紧张的话,一天还是只学一节就差不多了
今天学一下中断,中断这个东西很重要,在单片机微处理器这些环节里面,中断的核心位置是难以动摇的。
首先中断包括啥呢,中断源,中断向量(中断源的地址啥的),中断优先级,中断服务函数啥啥啥的。
对于STM32而言,是M3内核的,有16个内部中断,240个外部中断。256个中断优先级。因为STM32相较于51这种旧时代的微处理器而言,更加智能,所以说。STM32的中断通道存在多个中断共用的情况。就是说啥呢,某一个中断服务函数,被多个中断源所共同使用。所以说,在终端服务函数的入口处,就需要一个判别机制,判断优先级或者哪个中断又中断了谁谁谁。
STM32有两个优先级:抢占优先级和响应优先级
处理过程存在一个规律,大概就是:存在多个抢占优先级的中断,就看谁的抢占优先级高。如果说抢占优先级一样高,就处理响应优先级高的。如果谁抢占优先级和响应优先级一样高,这时候就按照中断的自然排序来处理中断。
在内核中有个叫NVIC的东西,就会对中断进行统一的一个协调和控制。主要就是来控制中断使能和确定中断优先级。
然后来了解下STM32的外部中断。(即来自外部GPIO的中断请求)
STM32有61个外部中断源,EXTI0---15,其中0-4都是专用的,其他的全是共用的。
EXTI0的引脚就是PA0----PG0
EXTI1就独赢的是PA1----PG1
...........
以此类推
中断源的触发条件主要是三种:上升沿,下降沿,双边沿----
那么接下来就需要一些程序的设计思路:
首先:GPIO初始化配置
然后:配置GPIO的引脚与中断线的映射关系
再者:配置GPIO对应的中断触发条件
之后:配置NVIC并使能中断
最后:编写中断服务函数
那么对于STM32CubeMX,GPIO就需要配置中断初始化参数了,在程序中需要写中断回调函数;
那么接下来就举一个例子,用一个key按键作为外部中断,设置为下降沿触发,然后编写中断函数,使得LED电平翻转(感觉就是换个思路处理按键。。。。)
其中CubeMX中需要吧GPIO设置为GPIO_EXTI功能,然后设置触发条件(上面提到的那三种)
最后使能一下NVIC的通道;
然后剩下的就是编写中断服务函数了
其中中断函数会涉及到的东西可以列在这里做一个小小的解读:
由于我这里使用的是F103RC,调用的是PC13的引脚,所以CubeMX给我的函数是:
EXTI15_10_IRQHandler(就是说10-15位置的意思)
之后第一行使用了一个中断的处理函数:
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
一般看不懂的时候就用ctrl+F进入函数定义的位置去看一看。
一般来说
HAL_GPIO_EXTI_IRQHandler中只需要看明白两句话就行(因为其他看不太懂……)
第一个是:
HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN):主要是清除中断标志,然后才会让内核发现
HAL_GPIO_EXTI_Callback(GPIO_PIN):回调函数,这玩意儿的定义是用的_ _WEAK就是一个虚函数。(因为C++没有学到面向对象编程,所以对虚函数不是特别的了解)
然后用户重写虚函数之后,它大致实现怎样的功能呢?就是判断GPIO_PIN是否是GPIO_PIN_13,然后直接对LED进行反转,之后就一直循环读取GPIO13,来判断是否为低电平。
这次就在CubeMX里的设置就会多一点点东西。虽然LED灯我们还是设置为OUTPUT的模式,但是按键我们就不再设置为输入模式了,而是设置为EXTI的模式,然后进入GPIO的设置后,KEY的设置就是上拉电阻,然后分别选择下降沿或上升沿(作为实验使用,一般来说,你想设置成啥触发,都是看项目要求来决定的)
然后就可以生成代码。
这里一般来说,多了一个函数
这个函数主要是处理中断所用。
在gpio.c里面也多了几行:
即NVIC的一个初始化;
那么接下来,我们就需要重写一下回调函数;
我们可以通过ctrl+F来找到Callback的函数位置。
因为它是一个虚函数,啥也没做,所以需要重新写。一般来说在main里面写或者你用新的头文件写都可以。
我们直接吧函数体复制到main.c函数的主题上方,重新void一个函数,就可以产生作用了。
那么我定义了如下的新的回调函数:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_13){
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_2);
}
if(GPIO_Pin == GPIO_PIN_0){
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_3);
}
}
这样就可以达到中断反转电平的效果了!!!
但是我好像还是没搞明白一些事儿,所以我决定再看看函数体的一个定义。因为再IF语句中,没有提到GPIO的A-G选择的问题。我因为这个疑问,翻了下中断使能以及很多的声明,还是没有发现有函数在括号里选择了GPIOx。所以我姑且认为如下:
因为CubeMX最开始的初始化中,只有PC13和PA0的中断和GPIO是进行了初始化的。所以说当我们使用EXTI0和EXTI13的时候,虽然GPIOA-G都是可以使用的,但是由于初始化GPIO口就他俩,所以说使用了这俩的中断,而其他的GPIO端口NVCI是没有进行初始化的。所以说,需要只有他俩可以使用中断(感觉发现后,我有点小蠢。。。)