#import "../template.typ": *

#show: project.with(
  title: "实验报告 4",
  authors: (
    "absolutex",
  )
)

= 定时器中断实验
== 实验目的

STM32F429的定时器功能十分强大，有TIME1和TIME8等高级定时器，也有TIME2\~TIME5，TIM9\~TIM14等通用定时器，还有TIME6和TIME7等基本定时器，总共达14个定时器之多。在本章中，我们将使用TIM3的定时器中断来控制DS1的翻转，在主函数用DS0的翻转来提示程序正在运行。本章实验将介绍定时器中断的配置，以及定时器的使用。

== 实验原理

STM32F429的通用定时器包含一个16位或32位自动重载计数器（CNT），该计数器由可编程预分频器（PSC）驱动。STM32F429的通用定时器可以被用于：测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。使用定时器预分频器和RCC时钟控制器预分频器，脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM3的通用TIMx(TIM2\~TIM5和TIM9\~TIM14)定时器功能包括：16位/32位(仅TIM2和TIM5)向上、向下、向上/向下自动装载计数器（TIMx_CNT）、16位可编程(可以实时修改)预分频器(TIMx_PSC)、4个独立通道（TIMx_CH1\~4，TIM9\~TIM14最多可以用1个定时器控制另外一个定时器）的同步电路、如下事件发生时产生中断/DMA（TIM9\~TIM14不支持DMA）。实验使用定时器产生中断，然后在中断服务函数里面翻转DS1上的电平，来指示定时器中断的产生。

== 代码描述

#include_code_file("../代码/7.timer.c","timer.c 片段", "c")

#include_code_file("../代码/7.main.c","main.c 片段", "c")

== 实验结果

DS0与DS1以不同频率闪烁。当DS1亮起时，若DS0已亮起，将会强制熄灭DS0。在可观测的一段时间后，DS0将再次亮起，表明中断程序结束，系统恢复到中断前的状态。

== 心得体会

在本次实验中，我了解了定时器中断的原理，以及如何编写中断服务，使用定时器中断来控制LED的亮灭。并且我还学习了调整定时器初始化的自动重装载参数，从而调整定时器中断的触发频率的方法。

定时器中断程序能够在固定的一段时间间隔后执行中断程序，也可以用于系统维护、资源释放，方便进行资源的调度调整。

= PWM输出实验
== 实验目的

在本次实验中，将介绍如何使用STM32F429的TIM3产生PWM输出，利用TIM3的通道4来产生PWM来控制DS0的亮度。

== 实验原理

脉冲宽度调制（PWM），是英文 `Pulse Width Modulation` 的缩写，简称脉宽调制，是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点，就是对脉冲宽度的控制，PWM原理如图所示：

#figure(
  image("pwm原理.png", width: 55%),
  caption: [PWM原理示意图],
)

图中，我们假定定时器工作在向上计数PWM模式，且当 CNT\<CCRx 时，输出0，当CNT>=CCRx时输出1。那么就可以得到如上的PWM示意图：当 CNT 值小于CCRx的时候，IO 输出低电平(0)，当 CNT 值大于等于CCRx 的时候，IO 输出高电平(1)，当 CNT 达到 ARR 值的时候，重新归零，然后重新向上计数，依次循环。改变 CCRx 的值，就可以改变 PWM 输出的占空比，改变 ARR 的值，就可以改变 PWM 输出的频率，这就是 PWM 输出的原理。

== 代码描述

#include_code_file("../代码/8.c","main.c 片段", "c")

== 实验结果

观察到DS0通过PWM调整占空比实现亮度渐变的闪烁，并且可以通过四个按键来控制其不同的闪烁频率。

下图是CH4通道的电平输出波形的瞬时值。实际上。此矩形波的占空比会不断改变，并且随着不同按键的按下，占空比的改变速率也会发生变化。

#figure(
  image("1.jpg", width: 60%),
  caption: [PWM输出],
)

== 心得体会

本次实验最开始是想做同时控制DS0和DS1随着占空比的变化而改变亮度，并让两个PWM频率通过不同的通道输出在示波器上。但是这涉及到比较复杂的底层代码修改。调试了很久，都无法达到预期效果，才放弃了这个想法，选择了按键控制频率的改进。按键控制频率只需要修改主程序代码，相对来说比较简单。
