在STM32中,外围设备的寄存器在上电的情况下默认是没有时钟的,不给时钟的情况下操作外设是无效的,外设也不会工作,这样的目的是降低功耗。 所以在操作外设之前必须要先使能它的时钟,这就需要我们用RCC来完成时钟的使能
1. 引入
通过按键KEY去控制LED灯:
不停的去读取按键相应的GPIO口的电平状态
高电平(1) ---> 弹起
低电平(0) ---> 按下
然后再根据GPIO引脚的电平状态,来判断按键的按下或弹起的状态,"通知" CPU,然后再去做相应的处理......大概的代码就是: while (1) { if (第一个按键按下) { LED1灯亮 } else { LED1灯灭 } ...... if (第四个按键按下) { LED4灯亮 } else { LED4灯灭 } }
因为需要一直不停的去判断按键对应的GPIO的电平状态,所以需要加上一个while(1),这种CPU的工作方式就称之为 "轮询"
"轮询":轮流询问,但是轮询有一些缺陷:
(1) 浪费CPU
(2) 占用总线,Bus is always busy
(3) 轮询有一个时间差,事件响应不及时
有没有办法不让CPU主动去询问事件是否发生,而是当事件发生后,主动通知CPU呢?
===> 中断
2. 中断的概念
一般中断定义为打断CPU指令正常执行顺序的事件,转而处理紧急程序,然后返回原暂停的程序继续运行
现代CPU架构为了能够及时响应外部或内部的一些紧急事件,都支持中断,并且会提供相应的中断响应机制===> 中断机制
3. ARM Cortex-M4 中断机制
当中断控制器(NVIC)通知CPU产生了某个事件,此时,CPU就会停止正在做的事情,转到处理模式去处理这个事件
而且M4给不同的中断一个唯一的编号(中断编号:用来区分不同的中断事件)当不同的中断事件产生时,CPU会做不同的处理
CPU怎么根据不同的中断事件去做不同的处理呢?根据中断向量表
中断向量表是什么?就是一个数组,保存不同的中断事件处理函数的地址的数组
所以中断向量表实际上就是一个函数指针数组中断编号:实际上就是该数组的下标
所以当某个事件发生时,中断产生,那么CPU就会根据此中断对应事件编号将其作为下标去调用该下标对应的那个中断处理函数
中断处理函数的格式一般为:void handler_func(void)
{
}
我们可以发现中断处理函数实际上没有返回值也不需要参数,why???
首先我们要明白中断函数与普通函数的区别:
普通函数:用户主动调用的,所以用户在调用时可以准备好参数,当然也可以解析返回值
中断函数:CPU被动调用,不是用户主动调用的。是当有紧急事件发生时,CPU被动去执行中断函数。它可以在用户指令的任何时刻去调用它,因为中断在任何时刻都可能产生
对于我们用户来讲,我们并不知道什么时候去调用中断函数。那么我们连什么时候调用都不知道,所以更无从去准备参数以及解析返回值