2023暑期薪火培训_电控第二讲——中断管理与定时器

中断管理机制

中断基本介绍

中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。

举例来说, 单片机的中断处理过程就像打游戏时女朋友来电话. 基本可以分为以下几个阶段

单片机中断 举例
单片机内部开启中断 打开手机(如取消静音等)
某时刻中断信号到来(例如计数器溢出、某个引脚被拉高等) 手机响了
单片机的硬件捕捉到中断信号 你听到手机铃声
自动从当前函数跳转进入相应的单片机内部对应的中断处理函数(IRQHandler)(在中断处理函数的回调函数中进行编程,实现中断处理的用户逻辑) 你接起了电话
执行完中断处理函数后,单片机自动跳转回主函数执行被中断处 接着做原来的事

具体流程如下图所示:
image

在实际的代码中: 当中断产生式, 会首先调用对应的中断处理函数IRQHandler(), 并在其中调用对应的中断回调函数Callback()
image

需要注意的是, 中断回调函数为一个弱定义函数(即使用__weak__关键字修饰), 用户可以在适当的位置重新声明该函数, 并编写自己的用户逻辑.


EXTI中断实例

下面将通过一个简单的实例来演示外部中断(External Interrupt)

实例说明

本实例由STM32F103C8Tx最小系统板、LED灯珠、按钮组成. 预期效果为: 每按一次按钮, LED灯转换一次亮灭状态.

步骤

  1. 配置RCC->High Speed Clock为Crystal/Ceramic Resonator
  2. 设置在SYS->Debug为Serial Wire
  3. 配置时钟树(具体可参照上一讲)
  4. 配置引脚PA1为GPIO_EXTI1, PB9为GPIO_Output. 并根据配置好的引脚连接硬件.(注意LED灯最好串联电阻, 避免电压过高烧坏灯珠)
  5. 在GPIO选项中配置PA1为上升沿触发、GPIO状态为默认下拉.(若接线方式不同也可配置为下降沿触发、默认上拉)
  6. 在NVIC中使能EXTI1 中断.
  7. 配置项目基本信息, 生成项目.
  8. 在main.c中代码保护区声明中断回调函数, 并添加电平翻转语句:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
	HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
}
  1. 编译、烧录, 观察实验效果.

按键消抖(了解即可)

对于理想按钮,在按下/松开时仅产生一次电平翻转, 然而实际情况中由于按钮机械结构, 导致在按下时(约10ms范围内)产生数次电平翻转, 这导致单片机进入多次外部中断, 进而多次翻转输出电平. 添加消抖逻辑即可解决这一问题, 例如:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    static uint16_t lastIntTick = 0;
    if(HAL_GetTick() - lastIntTick > 300){
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
        lastIntTick = HAL_GetTick();
    }
}

中断优先级与中断嵌套

在一个中断函数执行完毕后, 程序会自动跳回中断执行前的6函数语句继续执行, 这带来一个问题: 如果在一个中断未处理完成时产生第二个中断, 程序执行的情况是怎样的?

答案是: 如果中断2的优先级大于中断1的优先级, 则中断1的处理函数将被中断2打断, 转而执行中断2的处理函数,直至执行完后, 才会继续执行中断1的处理函数, 具体进程如下图:
image

另一方面, 如果中断2的优先级小于等于中断1的优先级, 则程序优先执行完中断1的处理函数, 再执行中断2的处理函数, 具体进程如下图:
image

在NVIC中可以设置各个中断的优先级(少数中断优先级无法调整除外), 需要注意的是: 优先级数字越小, 其对应优先级越大. 优先级越小, 优先级越大


定时器

定时器基本介绍

定时器

定时器实际上是单片机中的一个内部外设. 常常与计数器共同出现, 计数器也是一个内部外设.
就和我们的秒表一样, 定时器实际上就是一个秒表 每隔一个单位走一个格(就是计一个数), 因为计数器的计数时间周期是固定的, 因此到了一定时间只要用计数值 × 计数时间周期, 就能得到一个时间段, 这个时间段就是我们定的时间(这就是定时器了)

定时器工作原理

若想要定时器正常的实现“闹钟”的功能,即定时进行提醒单片机去完成某个任务,参与工作的主要有三个:

  1. 计数器寄存器 (TIMx_CNT)
    计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。
  2. 自动重载寄存器 (TIMx_ARR)
    自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。
  3. 预分频器寄存器 (TIMx_PSC)
    预分频器的值由寄存器TIMx_PSC设定,是一个16位正整数值。用来将定时器时钟源进行分频输出。

定时器的计数频率由ARR与PSC决定, 其公式与运作原理如下:

image

\(Ftim = \frac{Tclk}{((arr+1)(psc+1))}\)

计数器模式

  1. 递增计数模式
    计数器从 0 计数到自动重载值,然后重新从 0 开始计数并生成计数器上溢事件。
  2. 递减计数模式
    计数器从自动重载值开始递减到 0,然后重新从自动重载值开始计数并生成计数器下溢事件。
  3. 中心对齐模式
    计数器从 0 开始计数到自动重载值–1 ,生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从0 开始重新计数。

定时器中断实例

实例说明

本实例由STM32F103C8Tx最小系统板、LED灯珠组成. 预期效果为: 每隔0.5s, LED灯转换一次亮灭状态.

步骤

  1. 设置定时器时钟源为Internal Clock.
  2. 设置定时器分频、重载参数.
    以500ms时间间隔中断一次为例:
    F_clk = 72MHz
    F_tim = 1000ms / 500 ms = 2 Hz
    F_tim = 2Hz = F_clk / (ARR+1) * (PSC+1)
    (ARR+1) * (PSC+1) = 36,000,000
    这里取PSC = 720 – 1, ARR = 50000 - 1
  3. 在NVIC Settings中启用定时器中断(update interrupt或global interrupt).
  4. 在代码中启用定时器中断, 并将电平翻转函数添加到定时器中断回调函数中.
  5. 编译、烧录, 观察实验效果.

PWM波

PWM基本介绍

PWM即为脉冲宽度调制Pulse width modulation的简称,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。

广泛应用在从测量、通信到功率控制与变换的许多领域中。
控制方式就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形

PWM波的本质就是一个占空比与周期均可调的方波信号, 如下图所示:
image

PWM控制舵机实例

实例说明

本实例由STM32F103C8Tx最小系统板、舵机组成. 预期效果为: 实现舵机角度的基本控制.

步骤

  1. 在TIM实验的基础上, 设置PWM输出.
  2. 修改定时器周期为20ms, 这里取PSC = 72 – 1, ARR = 20000 - 1.
  3. 在代码中使用 __HAL_TIM_SetCompare(&htim, Channel, Compre);设置占空比(在本例中占空比可取值500~2500, 对应脉冲时长0.5ms~2.5ms).
  4. 使用HAL_TIM_PWM_Start(&htim, Channel);开启PWM输出.
  5. 链接舵机, 观察结果.
posted @ 2023-06-27 23:30  北京理工大学机器人队  阅读(119)  评论(0编辑  收藏  举报