当前位置: 首页 > news >正文

第二十一章 TIM——通用定时器

目录

第二十一章 TIM——通用定时器

1 定时器简介

2 通用定时器主要功能

3 通用定时器功能描述

3.1 时基单元

3.2 计数器模式

3.3 捕获/比较通道

3.4 输入捕获模式

3.5 PWM 输入模式(仅适用于 TIM9/12)

3.6 输出比较模式

3.7 PWM 模式

4 PWM

4.1 代码解析

4.2下载验证

5 更新中断

5.1 代码解析

5.2 下载验证

6 TIM_CalibrationLsi

6.1 代码解析

6.2 下载验证

7 TIM_InputCapture

7.1 代码解析

7.2 下载验证

8 TIM_Tim9

8.1 代码解析

8.2 下载验证


单芯片解决方案,开启全新体验——W55MH32 高性能以太网单片机

W55MH32是WIZnet重磅推出的高性能以太网单片机,它为用户带来前所未有的集成化体验。这颗芯片将强大的组件集于一身,具体来说,一颗W55MH32内置高性能Arm® Cortex-M3核心,其主频最高可达216MHz;配备1024KB FLASH与96KB SRAM,满足存储与数据处理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP协议栈、内置MAC以及PHY,拥有独立的32KB以太网收发缓存,可供8个独立硬件socket使用。如此配置,真正实现了All-in-One解决方案,为开发者提供极大便利。

在封装规格上,W55MH32 提供了两种选择:QFN100QFN68

W55MH32L采用QFN100封装版本,尺寸为12x12mm,其资源丰富,专为各种复杂工控场景设计。它拥有66个GPIO、3个ADC、12通道DMA、17个定时器、2个I2C、5个串口、2个SPI接口(其中1个带I2S接口复用)、1个CAN、1个USB2.0以及1个SDIO接口。如此丰富的外设资源,能够轻松应对工业控制中多样化的连接需求,无论是与各类传感器、执行器的通信,还是对复杂工业协议的支持,都能游刃有余,成为复杂工控领域的理想选择。 同系列还有QFN68封装的W55MH32Q版本,该版本体积更小,仅为8x8mm,成本低,适合集成度高的网关模组等场景,软件使用方法一致。更多信息和资料请进入http://www.w5500.com/网站或者私信获取。

此外,本W55MH32支持硬件加密算法单元,WIZnet还推出TOE+SSL应用,涵盖TCP SSL、HTTP SSL以及 MQTT SSL等,为网络通信安全再添保障。

为助力开发者快速上手与深入开发,基于W55MH32L这颗芯片,WIZnet精心打造了配套开发板。开发板集成WIZ-Link芯片,借助一根USB C口数据线,就能轻松实现调试、下载以及串口打印日志等功能。开发板将所有外设全部引出,拓展功能也大幅提升,便于开发者全面评估芯片性能。

若您想获取芯片和开发板的更多详细信息,包括产品特性、技术参数以及价格等,欢迎访问官方网页:http://www.w5500.com/,我们期待与您共同探索W55MH32的无限可能。

第二十一章 TIM——通用定时器

1 定时器简介

通用定时器是一个通过可编程预分频器驱动的 16 位自动装载计数器构成。它适用于多种场合,包括测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)。使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。每个定时器都是完全独立的,没有互相共享任何资源。它们可以一起同步操作

2 通用定时器主要功能

主要功能

通用 TIMx (TIM2、TIM3、TIM4 和 TIM5)定时器功能包括:

  • 16 位向上、向下、向上/向下自动装载计数器
  • 16 位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为 1~65536 之间的任意数值
  • 4 个独立通道:
    • 输入捕获
    • 输出比较
    • PWM 生成(边缘或中间对齐模式)
    • 单脉冲模式输出
  • 使用外部信号控制定时器和定时器互连的同步电路
  • 如下事件发生时产生中断/DMA:
    • 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
    • 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
    • 输入捕获
    • 输出比较
  • 支持针对定位的增量(正交)编码器和霍尔传感器电路
  • 触发输入作为外部时钟或者按周期的电流管理

通用定时器功能框图如下:

3 通用定时器功能描述

3.1 时基单元

可编程通用定时器的主要部分是一个16位计数器和与其相关的自动装载寄存器。这个计数器可 以向上计数、向下计数或者向上向下双向计数。此计数器时钟由预分频器分频得到。

计数器、自动装载寄存器和预分频器寄存器可以由软件读写,在计数器运行时仍可以读写。 时基单元包含:

  • 计数器寄存器(TIMx_CNT)
  • 预分频器寄存器 (TIMx_PSC)
  • 自动装载寄存器 (TIMx_ARR)

自动装载寄存器是预先装载的,写或读自动重装载寄存器将访问预装载寄存器。 根据在

TIMx_CR1 寄存器中的自动装载预装载使能位(ARPE)的设置,预装载寄存器的内容被立即或在 每次的更新事件 UEV 时传送到影子寄存器。当计数器达到溢出条件(向下计数时的下溢条件)并当TIMx_CR1 寄存器中的 UDIS 位等于'0'时,产生更新事件。更新事件也可以由软件产生。随后会详细描述每一种配置下更新事件的产生。

计数器由预分频器的时钟输出 CK_CNT 驱动,仅当设置了计数器 TIMx_CR1 寄存器中的计数器使能位(CEN)时,CK_CNT 才有效。

注:真正的计数器使能信号 CNT_EN 是在 CEN 的一个时钟周期后被设置。

预分频器描述

预分频器可以将计数器的时钟频率按 1 到 65536 之间的任意值分频。它是基于一个(在 TIMx_PSC 寄存器中的)16 位寄存器控制的 16 位计数器。这个控制寄存器带有缓冲器,它能够在工作时被改变。新的预分频器参数在下一次更新事件到来时被采用给出了在预分频器运行时,更改计数器参数的例子。当预分频器的参数从 1 变到 2 时,计数器的时序图如下:

当预分频器的参数从 1 变到 4 时,计数器的时序图如下:

3.2 计数器模式

向上计数模式

在向上计数模式中,计数器从 0 计数到自动加载值(TIMx_ARR 计数器的内容),然后重新从 0 开始计数并且产生一个计数器溢出事件。

每次计数器溢出时可以产生更新事件,在 TIMx_EGR 寄存器中(通过软件方式或者使用从模式控 制器)设置 UG 位也同样可以产生一个更新事件。

设置 TIMx_CR1 寄存器中的 UDIS 位,可以禁止更新事件;这样可以避免在向预装载寄存器中写 入新值时更新影子寄存器。在 UDIS 位被清'0'之前,将不产生更新事件。但是在应该产生更新事 件时,计数器仍会被清'0',同时预分频器的计数也被请 0(但预分频系数不变)。此外,如果设置 了TIMx_CR1 寄存器中的 URS 位(选择更新请求),设置 UG 位将产生一个更新事件 UEV,但硬件 不设置 UIF 标志(即不产生中断或 DMA 请求);这是为了避免在捕获模式下清除计数器时,同时产 生更新和捕获中断。

当发生一个更新事件时,所有的寄存器都被更新,硬件同时(依据 URS 位)设置更新标志位(TIMx_SR 寄存器中的 UIF 位)。

预分频器的缓冲区被置入预装载寄存器的值(TIMx_PSC 寄存器的内容)。

自动装载影子寄存器被重新置入预装载寄存器的值(TIMx_ARR)。

下图给出一些例子,当 TIMx_ARR=0x36 时计数器在不同时钟频率下的动作。内部时钟分频因子为 1时,计数器时序图:

内部时钟分频因子为 2,计数器时序图:

内部时钟分频因子为4,计数器时序图:

内部时钟分频因子为N,计数器时序图:

当 ARPE=0 时的更新事件(TIMx_ARR 没有预装入),计数器时序图:

当 ARPE=1 时的更新事件(预装入了 TIMx_ARR),计数器时序图:

3.3 捕获/比较通道

每一个捕获/比较通道都是围绕着一个捕获/比较寄存器(包含影子寄存器),包括捕获的输入部分(数字滤波、多路复用和预分频器),和输出部分(比较器和输出控制)。 下面几张图是一个捕获/比较通道概览。

输入部分对相应的 TIx 输入信号采样,并产生一个滤波后的信号 TIxF。然后,一个带极性选择的边缘检测器产生一个信号(TIxFPx),它可以作为从模式控制器的输入触发或者作为捕获控制。该信号通过预分频进入捕获寄存器(ICxPS):

输出部分产生一个中间波形 OCxRef(高有效)作为基准,链的末端决定最终输出信号的极性:

捕获/比较通道 1 的主电路:

捕获/比较模块由一个预装载寄存器和一个影子寄存器组成。读写过程仅操作预装载寄存器。

在捕获模式下,捕获发生在影子寄存器上,然后再复制到预装载寄存器中。

在比较模式下,预装载寄存器的内容被复制到影子寄存器中,然后影子寄存器的内容和计数器进行比较。

3.4 输入捕获模式

根据输入信号的特点,配置输入滤波器为所需的带宽(即输入为 TIx 时,输入滤波器控制位是TIMx_CCMRx 寄存器中的 ICxF 位)。假设输入信号在最多 5 个内部时钟周期的时间内抖动,我们须配置滤波器的带宽长于 5 个时钟周期。因此我们可以(以 fDTS 频率)连续采样 8 次,以确 认在 TI1 上一次真实的边沿变换,即在 TIMx_CCMR1 寄存器中写入 IC1F=0011。

选择 TI1 通道的有效转换边沿,在 TIMx_CCER 寄存器中写入 CC1P=0(上升沿)。

配置输入预分频器。在本例中,我们希望捕获发生在每一个有效的电平转换时刻,因此预 分频器被禁止(写 TIMx_CCMR1 寄存器的 IC1PS=00)。

设置 TIMx_CCER 寄存器的 CC1E=1,允许捕获计数器的值到捕获寄存器中。

如果需要,通过设置TIMx_DIER寄存器中的CC1IE位允许相关中断请求,通过设置 TIMx_DIER寄存器中的 CC1DE 位允许 DMA 请求。

当发生一个输入捕获时:

产生有效的电平转换时,计数器的值被传送到 TIMx_CCR1 寄存器。

CC1IF 标志被设置(中断标志)。当发生至少 2 个连续的捕获时,而 CC1IF 未曾被清除, CC1OF也被置'1'。

如设置了 CC1IE 位,则会产生一个中断。

如设置了 CC1DE 位,则还会产生一个 DMA 请求。

为了处理捕获溢出,建议在读出捕获溢出标志之前读取数据,这是为了避免丢失在读出捕获溢 出标志之后和读取数据之前可能产生的捕获溢出信息。

注: 设置 TIMx_EGR 寄存器中相应的 CCxG 位,可以通过软件产生输入捕获中断和/或 DMA 请求

3.5 PWM 输入模式(仅适用于 TIM9/12)

该模式是输入捕获模式的一个特例,除下列区别外,操作与输入捕获模式相同:

两个 ICx 信号被映射至同一个 TIx 输入。

这 2 个 ICx 信号为边沿有效,但是极性相反。

其中一个 TIxFP 信号被作为触发输入信号,而从模式控制器被配置成复位模式。

例如,你需要测量输入到 TI1 上的 PWM 信号的长度(TIMx_CCR1 寄存器)和占空比(TIMx_CCR2 寄存器),具体步骤如下(取决于 CK_INT 的频率和预分频器的值)

选择 TIMx_CCR1 的有效输入:置 TIMx_CCMR1 寄存器的 CC1S=01(选择 TI1)。

选择 TI1FP1 的有效极性(用来捕获数据到 TIMx_CCR1 中和清除计数器):置 CC1P=0(上升沿有效)。

选择 TIMx_CCR2 的有效输入:置 TIMx_CCMR1 寄存器的 CC2S=10(选择 TI1)。

选择 TI1FP2 的有效极性(捕获数据到 TIMx_CCR2):置 CC2P=1(下降沿有效)。

选择有效的触发输入信号:置 TIMx_SMCR 寄存器中的 TS=101(选择 TI1FP1)。

配置从模式控制器为复位模式:置 TIMx_SMCR 中的 SMS=100。

使能捕获:置 TIMx_CCER 寄存器中 CC1E=1 且 CC2E=1。

PWM 输入模式时序如下:

3.6 输出比较模式

此项功能是用来控制一个输出波形,或者指示一段给定的的时间已经到时。 当计数器与捕获/比较寄存器的内容相同时,输出比较功能做如下操作:

将输出比较模式(TIMx_CCMRx 寄存器中的 OCxM 位)和输出极性(TIMx_CCER 寄存器中的 CCxP

位)定义的值输出到对应的引脚上。在比较匹配时,输出引脚可以保持它的电平(OCxM=000)、

被设置成有效电平(OCxM=001)、被设置成无效电平(OCxM=010)或进行翻 转(OCxM=011)。

设置中断状态寄存器中的标志位(TIMx_SR 寄存器中的 CCxIF 位)。

若设置了相应的中断屏蔽(TIMx_DIER 寄存器中的 CCxIE 位),则产生一个中断。

若设置了相应的使能位(TIMx_DIER 寄存器中的 CCxDE 位,TIMx_CR2 寄存器中的 CCDS 位 选择 DMA 请求功能),则产生一个 DMA 请求。

TIMx_CCMRx 中的 OCxPE 位选择 TIMx_CCRx 寄存器是否需要使用预装载寄存器。 在输出比较模式下,更新事件 UEV 对 OCxREF 和 OCx 输出没有影响。

同步的精度可以达到计数器的一个计数周期。输出比较模式(在单脉冲模式下)也能用来输出一个单脉冲。输出比较模式的配置步骤:

1. 选择计数器时钟(内部,外部,预分频器)

2. 将相应的数据写入 TIMx_ARR 和 TIMx_CCRx 寄存器中

3. 如果要产生一个中断请求和/或一个 DMA 请求,设置 CCxIE 位和/或 CCxDE 位。

4. 选择输出模式,例如当计数器CNT与CCRx匹配时翻转 OCx的输出引脚,CCRx预装载未 用,开启 OCx 输出且高电平有效,则必须设置 OCxM='011' 、OCxPE='0' 、CCxP='0'和 CCxE='1'。

5. 设置 TIMx_CR1 寄存器的 CEN 位启动计数器

TIMx_CCRx 寄存器能够在任何时候通过软件进行更新以控制输出波形,条件是未使用预装载寄 存器(OCxPE='0',否则 TIMx_CCRx 影子寄存器只能在发生下一次更新事件时被更新)。下图给出了一个例子。

输出比较模式,翻转 OC1。

3.7 PWM 模式

脉冲宽度调制模式可以产生一个由 TIMx_ARR 寄存器确定频率、由 TIMx_CCRx 寄存器确定占空比的信号。

在 TIMx_CCMRx 寄存器中的 OCxM 位写入'110'(PWM 模式 1)或'111'(PWM 模式 2),能够独立地设置每个 OCx 输出通道产生一路 PWM。必须设置 TIMx_CCMRx 寄存器 OCxPE 位以使能相应的预 装载寄存器,最后还要设置 TIMx_CR1 寄存器的 ARPE 位,(在向上计数或中心对称模式中)使能 自动重装载的预装载寄存器。

仅当发生一个更新事件的时候,预装载寄存器才能被传送到影子寄存器,因此在计数器开始计 数之前,必须通过设置 TIMx_EGR 寄存器中的 UG 位来初始化所有的寄存器。OCx 的极性可以通过软件在 TIMx_CCER 寄存器中的 CCxP 位设置,它可以设置为高电平有效或 低电平有效。TIMx_CCER寄存器中的CCxE位控制OCx输出使能。详见TIMx_CCERx寄存器的 描述。

在 PWM 模式(模式 1 或模式 2)下,TIMx_CNT 和 TIMx_CCRx 始终在进行比较,(依据计数器的计数方向) 以确定是否符合 TIMx_CCRx ≤ TIMx_CNT 或者 TIMx_CNT ≤ TIMx_CCRx 。然而 为了与OCREF_CLR 的功能(在下一个 PWM 周期之前, ETR 信号上的一个外部事件能够清除 OCxREF) 一致,OCxREF 信号只能在下述条件下产生:

当比较的结果改变

当输出比较模式(TIMx_CCMRx 寄存器中的 OCxM 位)从“冻结”(无比较,OCxM='000')切换到

某个 PWM 模式(OCxM='110'或'111')。这样在运行中可以通过软件强置 PWM 输出。

根据 TIMx_CR1寄存器中 CMS位的状态,定时器能够产生边沿对齐的 PWM信号或中央对齐的 PWM信号。

PWM 边沿对齐模式

  • 向上计数配置

当 TIMx_CR1 寄存器中的 DIR 位为低的时候执行向上计数。

下面是一个 PWM 模式 1 的例子。当 TIMx_CNT<TIMx_CCRx 时 PWM 信号参考 OCxREF 为高,否则为低。如果 TIMx_CCRx 中的比较值大于自动重装载值(TIMx_ARR),则 OCxREF 保持为'1'。

如果比较值为 0,则 OCxREF 保持为'0' 。下图为 TIMx_ARR=8 时边沿对齐的 PWM 波形实例。边沿对齐的 PWM 波形(ARR=8)如下:

  • 向下计数的配置

当 TIMx_CR1 寄存器的 DIR 位为高时执行向下计数。在 PWM 模式 1 ,当TIMx_CNT>TIMx_CCRx 时参考信 号 OCxREF 为低,否 则为高。 如果TIMx_CCRx 中的比较值大于 TIMx_ARR 中的自动重装载值,则 OCxREF 保持为'1'。该模式下不 能产生 0%的 PWM 波形。

PWM 中央对齐模式

当 TIMx_CR1 寄存器中的 CMS 位不为'00'时,为中央对齐模式(所有其他的配置对 OCxREF/OCx 信号都有相同的作用)。根据不同的 CMS 位设置,比较标志可以在计数器向上计数时被置'1'、在计数器向下计数时被置'1'、或在计数器向上和向下计数时被置'1' 。TIMx_CR1 寄存器中的计数方向位(DIR)由硬件更新,不要用软件修改它。

下图给出了一些中央对齐的 PWM 波形的例子

TIMx_ARR=8

PWM 模式 1

TIMx_CR1 寄存器中的 CMS=01,在中央对齐模式 1 时,当计数器向下计数时设置比较标志。

使用中央对齐模式的提示:

进入中央对齐模式时,使用当前的向上/向下计数配置;这就意味着计数器向上还是向下计数取决于 TIMx_CR1 寄存器中 DIR 位的当前值。此外,软件不能同时修改 DIR 和 CMS 位。

不推荐当运行在中央对齐模式时改写计数器,因为这会产生不可预知的结果。特别地: 如果写入计数器的值大于自动重加载的值(TIMx_CNT>TIMx_ARR),则方向不会被更新。 例如,如果计数器正在向上计数,它就会继续向上计数。如果将 0 或者 TIMx_ARR 的值写入计数器,方向被更新,但不产生更新事件 UEV。

使用中央对齐模式最保险的方法,就是在启动计数器之前产生一个软件更新(设置 TIMx_EGR 位中的 UG 位),不要在计数进行过程中修改计数器的值。

4 PWM

4.1 代码解析

1.头文件包含和全局变量定义

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "delay.h"
#include "w55mh32.h"USART_TypeDef *USART_TEST = USART1;

头文件:引入了标准库头文件和自定义头文件,delay.h可能用于延时功能,w55mh32.h可能包含硬件相关的定义。

全局变量:USART_TEST是一个指向USART_TypeDef类型的指针,被初始化为USART1,用于后续的串口操作。

2.函数声明

void              UART_Configuration(uint32_t bound);
void              TIM_Configuration(void);
void              RCC_ClkConfiguration(void);

声明了三个函数:

UART_Configuration():用于配置串口通信。

TIM_Configuration():用于配置定时器并输出 PWM 信号。

RCC_ClkConfiguration():用于配置系统时钟。

  1. main()函数
RCC_ClocksTypeDef clocks;
int               main(void)
{RCC_ClkConfiguration();delay_init();UART_Configuration(115200);RCC_GetClocksFreq(&clocks);printf("SYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhz\n",(float)clocks.SYSCLK_Frequency / 1000000, (float)clocks.HCLK_Frequency / 1000000,(float)clocks.PCLK1_Frequency / 1000000, (float)clocks.PCLK2_Frequency / 1000000, (float)clocks.ADCCLK_Frequency / 1000000);printf("TIM Out Test.\n");TIM_Configuration();while (1);
}

系统初始化:

调用RCC_ClkConfiguration()函数配置系统时钟。

调用delay_init()函数初始化延时功能。

调用UART_Configuration()函数配置串口通信,波特率设置为 115200。

调用RCC_GetClocksFreq()函数获取系统时钟频率信息。

信息输出:

通过printf()函数输出系统时钟频率信息,包括系统时钟(SYSCLK)、高级高性能总线时钟(HCLK)、低速外设总线时钟(PCLK1)、高速外设总线时钟(PCLK2)和 ADC 时钟(ADCCLK)。

输出提示信息 “TIM Out Test.”,表示开始定时器输出测试。

定时器配置:

调用TIM_Configuration()函数配置定时器并输出 PWM 信号。

主循环:

while (1);是一个无限循环,使程序停在这里,等待定时器输出 PWM 信号。

4.RCC_ClkConfiguration()函数

void RCC_ClkConfiguration(void)
{RCC_DeInit();RCC_HSEConfig(RCC_HSE_ON);while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);RCC_PLLCmd(DISABLE);RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);RCC_PLLCmd(ENABLE);while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);RCC_HCLKConfig(RCC_SYSCLK_Div1);RCC_PCLK1Config(RCC_HCLK_Div2);RCC_PCLK2Config(RCC_HCLK_Div1);RCC_LSICmd(ENABLE);while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);RCC_HSICmd(ENABLE);while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
}

时钟复位:

调用RCC_DeInit()函数将 RCC 寄存器复位为默认值。

外部高速时钟(HSE)配置:调用RCC_HSEConfig()函数使能外部高速时钟(HSE)。

通过while循环等待 HSE 准备好(RCC_FLAG_HSERDY标志置位)。

锁相环(PLL)配置:

调用RCC_PLLCmd()函数禁用 PLL。

调用RCC_PLLConfig()函数配置 PLL,将 HSE 作为 PLL 的输入时钟源,PLL 乘法因子设置为 9。

调用RCC_PLLCmd()函数使能 PLL。

通过while循环等待 PLL 准备好(RCC_FLAG_PLLRDY标志置位)。

系统时钟配置:

调用RCC_SYSCLKConfig()函数将 PLL 输出作为系统时钟。

总线时钟配置:

调用RCC_HCLKConfig()函数将系统时钟(SYSCLK)直接作为高级高性能总线时钟(HCLK)。

调用RCC_PCLK1Config()函数将 HCLK 分频 2 作为低速外设总线时钟(PCLK1)。

调用RCC_PCLK2Config()函数将 HCLK 直接作为高速外设总线时钟(PCLK2)。

低速内部时钟(LSI)和高速内部时钟(HSI)配置:

调用RCC_LSICm()函数使能低速内部时钟(LSI),并等待 LSI 准备好(RCC_FLAG_LSIRDY标志置位)。

调用RCC_HSICmd()函数使能高速内部时钟(HSI),并等待 HSI 准备好(RCC_FLAG_HSIRDY标志置位)。

  1. TIM_Configuration()函数
void TIM_Configuration(void)
{
    GPIO_InitTypeDef        GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef       TIM_OCInitStructure;    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);                        //Enable Timer 3 Clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); //Enable GPIO peripherals and AFIO multiplexing function module clocks    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7; //TIM_CH2
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);    //Timer TIM3 initialization
    TIM_TimeBaseStructure.TIM_Period        = 99;
    TIM_TimeBaseStructure.TIM_Prescaler     = clocks.PCLK1_Frequency / 1000000 - 1;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);    //Initialize TIM3 Channel2 PWM mode
    TIM_OCInitStructure.TIM_OCMode       = TIM_OCMode_PWM2;
    TIM_OCInitStructure.TIM_OutputState  = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_Pulse        = 99 / 2;
    TIM_OCInitStructure.TIM_OCPolarity   = TIM_OCPolarity_Low;
    TIM_OCInitStructure.TIM_OCNPolarity  = TIM_OCNPolarity_Low;
    TIM_OCInitStructure.TIM_OCIdleState  = TIM_OCIdleState_Set;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
    TIM_OC2Init(TIM3, &TIM_OCInitStructure);    TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM3, ENABLE);    TIM_Cmd(TIM3, ENABLE);
    TIM_CtrlPWMOutputs(TIM3, ENABLE); //Open the advanced timer
}

时钟使能:

调用RCC_APB1PeriphClockCmd()函数使能定时器 3(TIM3)的时钟。

调用RCC_APB2PeriphClockCmd()函数使能 GPIOA 和 AFIO(复用功能模块)的时钟。

GPIO 配置:

将GPIOA的Pin 7配置为复用推挽输出模式,用于输出 TIM3 的通道 2(TIM_CH2)的 PWM 信号。

配置 GPIO 的速度为 50MHz。

定时器基本参数配置:

定义TIM_TimeBaseInitTypeDef类型的结构体TIM_TimeBaseStructure,用于配置定时器的基本参数。

TIM_Period设置为 99,表示定时器的自动重载值。

TIM_Prescaler根据PCLK1的频率进行设置,将定时器的时钟频率进行分频。

TIM_ClockDivision设置为TIM_CKD_DIV1,表示时钟分频因子为 1。

TIM_CounterMode设置为TIM_CounterMode_Up,表示定时器采用向上计数模式。

调用TIM_TimeBaseInit()函数根据上述参数初始化 TIM3。

定时器输出比较(PWM)配置:

定义TIM_OCInitTypeDef类型的结构体TIM_OCInitStructure,用于配置定时器的输出比较(PWM)参数。

TIM_OCMode设置为TIM_OCMode_PWM2,表示采用 PWM 模式 2。

TIM_OutputState和TIM_OutputNState都设置为TIM_OutputState_Enable,表示使能输出和互补输出。

TIM_Pulse设置为99 / 2,表示 PWM 信号的脉冲宽度。

TIM_OCPolarity和TIM_OCNPolarity都设置为TIM_OCPolarity_Low,表示输出极性为低。

TIM_OCIdleState设置为TIM_OCIdleState_Set,TIM_OCNIdleState设置为TIM_OCIdleState_Reset,表示空闲状态下的输出电平。

调用TIM_OC2Init()函数根据上述参数初始化 TIM3 的通道 2。

预装载寄存器配置:

调用TIM_OC2PreloadConfig()函数使能 TIM3 通道 2 的预装载寄存器。

调用TIM_ARRPreloadConfig()函数使能 TIM3 的自动重载寄存器的预装载功能。

定时器使能:

调用TIM_Cmd()函数使能 TIM3。

调用TIM_CtrlPWMOutputs()函数使能高级定时器的 PWM 输出。

  1. UART_Configuration()函数
void UART_Configuration(uint32_t bound)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);    USART_InitStructure.USART_BaudRate            = bound;
    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;
    USART_InitStructure.USART_Parity              = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;    USART_Init(USART_TEST, &USART_InitStructure);
    USART_Cmd(USART_TEST, ENABLE);
}

时钟使能:

调用RCC_APB2PeriphClockCmd()函数使能 USART1 和 GPIOA 的时钟。

GPIO 配置:

将GPIOA的Pin 9配置为复用推挽输出模式,用于 USART1 的发送功能。

将GPIOA的Pin 10配置为浮空输入模式,用于 USART1 的接收功能。

配置 GPIO 的速度为 50MHz。

USART 配置:

定义USART_InitTypeDef类型的结构体USART_InitStructure,用于配置 USART 的基本参数。

USART_BaudRate根据传入的参数bound设置波特率。

USART_WordLength设置为USART_WordLength_8b,表示数据位为 8 位。

USART_StopBits设置为USART_StopBits_1,表示停止位为 1 位。

USART_Parity设置为USART_Parity_No,表示无校验位。

USART_HardwareFlowControl设置为USART_HardwareFlowControl_None,表示无硬件流控制。

USART_Mode设置为USART_Mode_Rx | USART_Mode_Tx,表示支持收发模式。

调用USART_Init()函数根据上述参数初始化 USART1。

调用USART_Cmd()函数使能 USART1。

7. SER_PutChar()和fputc()函数

int SER_PutChar(int ch)
{
    while (!USART_GetFlagStatus(USART_TEST, USART_FLAG_TC));
    USART_SendData(USART_TEST, (uint8_t)ch);    return ch;
}int fputc(int c, FILE *f)
{
    if (c == '\n')
    {
        SER_PutChar('\r');
    }
    return (SER_PutChar(c));
}

SER_PutChar()函数用于将一个字符发送到串口,通过USART_GetFlagStatus()函数检查串口发送完成标志,等待发送完成后,调用USART_SendData()函数发送字符。

fputc()函数重定向了printf()函数的输出,将字符通过串口发送出去,当遇到换行符\n时,先调用SER_PutChar('\r')函数发送回车符\r。

4.2下载验证

如果想查看PWM输出的占空比,可以在循环里加这段代码:

 uint16_t pwm_value = TIM_GetCapture2(TIM3);
float duty_cycle = (float)pwm_value / 99 * 100;
printf("PWM Duty Cycle: %.2f%%\n", duty_cycle);
delay_ms(1000);

这样可以打印出PWM的占空比:

5 更新中断

5.1 代码解析

1. main()函数:初始化与启动

in main(void) {
    delay_init();          // 延时初始化(sysTick)
    UART_Configuration(115200);  // 串口配置(115200波特率)
    TIM_Configuration();   // 定时器TIM3配置    // 打印系统时钟
    printf("SYSCLK: %3.1fMhz...\n", (float)clocks.SYSCLK_Frequency / 1000000);    while (1);  // 主循环(空,依赖中断)
}

2. UART_Configuration():串口初始化

void UART_Configuration(uint32_t bound) {
    // 使能USART1、GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);    // 配置TX(PA9):复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);    // 配置RX(PA10):浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);    // 串口参数:115200波特率,8位数据,1位停止位
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);  // 使能串口
}

3. TIM_Configuration():定时器 TIM3 配置

void TIM_Configuration(void) {
    // 使能TIM3时钟(APB1总线)
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);    // 定时器参数:
    TIM_TimeBaseStructure.TIM_Period = 9999;  // 自动重载值(0~9999,共10000个周期)
    // 预分频器:PCLK1频率/1MHz - 1(例如PCLK1=36MHz → 36-1=35)
    TIM_TimeBaseStructure.TIM_Prescaler = (clocks.PCLK1_Frequency / 1000000) - 1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  // 初始化定时器    // 使能更新中断
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);    // 中断配置(NVIC):
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  // TIM3中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  // 抢占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  // 子优先级3
    NVIC_Init(&NVIC_InitStructure);  // 使能中断    TIM_Cmd(TIM3, ENABLE);  // 启动定时器
}

4. 中断处理函数:TIM3_IRQHandler()

void TIM3_IRQHandler(void) {
    if (TIM_GetITStatus(TIM3, TIM_IT_Update)) {  // 检查更新中断标志
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  // 清除中断标志
        printf("%s\n", __FUNCTION__);  // 打印函数名("TIM3_IRQHandler")
    }
}

该代码演示了 W55MH32 定时器的基本用法:配置 TIM3 的更新中断,周期性触发并通过串口输出信息。核心流程:定时器初始化(预分频器、周期)→ 启用中断 → 中断处理(打印信息)。适用于需要周期性任务的场景(如定时采样、心跳信号)。

5.2 下载验证

6 TIM_CalibrationLsi

6.1 代码解析

1. 全局变量

uint8_t  TIM5_CAPTURE_STA = 0; // 输入捕获状态(位7:完成标志,位6:上升沿标志,位0-5:溢出次数)
uint16_t TIM5_CAPTURE_VAL;     // 捕获值(TIM5计数器值)

2. main()函数:初始化与主循环

int main(void) {
    RCC_ClkConfiguration();       // 系统时钟配置(HSE→PLL→72MHz)
    delay_init();                  // 延时初始化(SysTick)
    UART_Configuration(115200);    // 串口配置(115200波特率)
    TIM_Configuration();          // TIM5输入捕获配置(LSI测量)    // 主循环:处理捕获结果
    while (1) {
        if (TIM5_CAPTURE_STA & 0x80) { // 捕获完成标志
            // 计算总时间:溢出次数×65536 + 捕获值
            temp = (TIM5_CAPTURE_STA & 0x3F) * 65536 + TIM5_CAPTURE_VAL;
            printf("LSI周期: %d μs\nLSI频率: %f Hz\n", temp, 1000000.0 / temp);
            TIM5_CAPTURE_STA = 0; // 重置状态,准备下次捕获
        }
    }
}

3. TIM_Configuration():定时器输入捕获配置

void TIM_Configuration(void) {
    // 使能TIM5和AFIO时钟(用于引脚重映射)
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);    // 重映射:LSI → TIM5_CH4(无需外部引脚)
    GPIO_PinRemapConfig(GPIO_Remap_TIM5CH4_LSI, ENABLE);    // 时基配置:
    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;                  // 最大计数值(65535)
    // 预分频器:PCLK1×2 / 1MHz - 1(TIMx时钟=PCLK1×2)
    TIM_TimeBaseStructure.TIM_Prescaler = (clocks.PCLK1_Frequency * 2 / 1000000) - 1;
    TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);    // 输入捕获配置(通道4,上升沿捕获):
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  // 上升沿捕获
    TIM_ICInit(TIM5, &TIM_ICInitStructure);    // 中断配置:更新(溢出)+ 捕获中断
    NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
    NVIC_Init(&NVIC_InitStructure);
    TIM_ITConfig(TIM5, TIM_IT_Update | TIM_IT_CC4, ENABLE);    TIM_Cmd(TIM5, ENABLE);  // 启动定时器
}

4. 中断处理函数:TIM5_IRQHandler()

void TIM5_IRQHandler(void) {
    if (! (TIM5_CAPTURE_STA & 0x80)) { // 未完成捕获
        // 处理更新中断(定时器溢出)
        if (TIM_GetITStatus(TIM5, TIM_IT_Update)) {
            if (TIM5_CAPTURE_STA & 0x40) { // 已捕获上升沿,溢出计数
                if ((TIM5_CAPTURE_STA & 0x3F) == 0x3F) { // 溢出32次(超时)
                    TIM5_CAPTURE_STA |= 0x80; // 标记失败
                } else {
                    TIM5_CAPTURE_STA++; // 溢出次数+1
                }
            }
        }        // 处理捕获中断(CH4上升沿)
        if (TIM_GetITStatus(TIM5, TIM_IT_CC4)) {
            if (TIM5_CAPTURE_STA & 0x40) { // 已捕获上升沿,现在捕获下降沿(假设LSI是方波)
                TIM5_CAPTURE_VAL = TIM_GetCapture4(TIM5); // 读取捕获值
                TIM5_CAPTURE_STA |= 0x80; // 标记完成
            } else { // 首次捕获上升沿
                TIM5_CAPTURE_STA = 0x40; // 标记已捕获上升沿
                TIM_SetCounter(TIM5, 0); // 计数器清零
            }
        }
    }
    TIM_ClearITPendingBit(TIM5, TIM_IT_CC4 | TIM_IT_Update); // 清除中断标志
}

5. 系统时钟配置:RCC_ClkConfiguration()

void RCC_ClkConfiguration(void) {
    // 初始化系统时钟:HSE(8MHz) → PLL×9 → SYSCLK=72MHz
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);    // 总线分频:
    RCC_HCLKConfig(RCC_SYSCLK_Div1);   // HCLK=72MHz
    RCC_PCLK1Config(RCC_HCLK_Div2);    // PCLK1=36MHz(TIM5属于APB1)
    RCC_PCLK2Config(RCC_HCLK_Div1);    // PCLK2=72MHz    RCC_LSICmd(ENABLE); // 启用LSI(内部低速时钟,~32kHz)
}

此代码是 W55MH32 定时器高级应用的典型示例,展示了如何利用硬件特性测量内部信号,适用于嵌入式系统调试和时钟校准场景。

6.2 下载验证

7 TIM_InputCapture

7.1 代码解析

1. 全局变量

uint8_t  TIM3_CAPTURE_STA = 0; // 输入捕获状态(位7:完成,位6:上升沿标志,位0-5:溢出次数)
uint16_t TIM3_CAPTURE_VAL;     // 捕获值(TIM3计数器值)

2. main()函数:初始化与主循环

int main(void) {
    RCC_ClkConfiguration();       // 系统时钟配置(72MHz)
    UART_Configuration(115200);    // 串口初始化
    TIM_Configuration();          // TIM3输入捕获配置    while (1) {
        if (TIM3_CAPTURE_STA & 0x80) { // 捕获完成
            // 计算总时间:溢出次数×65536 + 捕获值(单位:μs)
            temp = (TIM3_CAPTURE_STA & 0x3F) * 65536 + TIM3_CAPTURE_VAL;
            printf("HIGH:%d us\r\n", temp); // 打印高电平时间
            TIM3_CAPTURE_STA = 0; // 重置状态,准备下次捕获
        }
    }
}

3. TIM_Configuration():定时器输入捕获配置

void TIM_Configuration(void) {
    // 使能TIM3、GPIOA、AFIO时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);    // 配置GPIOA7为输入(TIM3_CH2)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 下拉输入(根据信号调整)
    GPIO_Init(GPIOA, &GPIO_InitStructure);    // 时基配置:
    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;      // 最大计数值(65535)
    TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;   // 预分频器(72MHz/72=1MHz → 计数周期1μs)
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);    // 输入捕获配置(通道2,上升沿捕获):
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // 上升沿捕获
    TIM_ICInit(TIM3, &TIM_ICInitStructure);    // 中断配置:更新(溢出)+ 捕获中断
    NVIC_Init(&NVIC_InitStructure);
    TIM_ITConfig(TIM3, TIM_IT_Update | TIM_IT_CC2, ENABLE);    TIM_Cmd(TIM3, ENABLE); // 启动定时器
}

4. 中断处理函数:TIM3_IRQHandler()

void TIM3_IRQHandler(void) {
    if (! (TIM3_CAPTURE_STA & 0x80)) { // 未完成捕获
        // 处理溢出中断
        if (TIM_GetITStatus(TIM3, TIM_IT_Update)) {
            if (TIM3_CAPTURE_STA & 0x40) { // 已捕获上升沿,统计溢出
                if (TIM3_CAPTURE_STA & 0x3F == 0x3F) { // 溢出32次(超时)
                    TIM3_CAPTURE_STA |= 0x80; // 标记失败
                } else {
                    TIM3_CAPTURE_STA++; // 溢出次数+1
                }
            }
        }        // 处理捕获中断(CH2上升沿/下降沿)
        if (TIM_GetITStatus(TIM3, TIM_IT_CC2)) {
            if (TIM3_CAPTURE_STA & 0x40) { // 捕获下降沿(高电平结束)
                TIM3_CAPTURE_VAL = TIM_GetCapture2(TIM3); // 读取捕获值
                TIM3_CAPTURE_STA |= 0x80; // 标记完成
                TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Rising); // 切回上升沿捕获
            } else { // 捕获上升沿(高电平开始)
                TIM3_CAPTURE_STA = 0x40; // 标记上升沿
                TIM_SetCounter(TIM3, 0); // 计数器清零
                TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Falling); // 切换为下降沿捕获
            }
        }
    }
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC2 | TIM_IT_Update); // 清除中断标志
}

5. 系统时钟配置

void RCC_ClkConfiguration(void) {
    // HSE(8MHz) → PLL×9 → SYSCLK=72MHz
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);    // 总线分频:HCLK=72MHz, PCLK1=36MHz, PCLK2=72MHz
}

此代码是 W55MH32 定时器输入捕获的典型应用,展示了如何通过硬件中断高效测量外部信号,适用于需要高精度时间测量的嵌入式系统。

7.2 下载验证

8 TIM_Tim9

8.1 代码解析

1. 头文件与全局变量

#include "w55mh32.h"  // STM32硬件抽象层(寄存器定义)
USART_TypeDef *USART_TEST = USART1;  // 串口外设指针(USART1)

2. main()函数:初始化与启动

int main(void) {
    delay_init();          // 延时初始化(sysTick)
    UART_Configuration(115200);  // 串口配置(115200波特率)
    TIM_Configuration();   // 定时器TIM9配置    // 打印系统时钟
    printf("SYSCLK: %3.1fMhz...\n", (float)clocks.SYSCLK_Frequency / 1000000);    while (1);  // 主循环(空,依赖中断)
}

3. UART_Configuration():串口初始化

void UART_Configuration(uint32_t bound) {
    // 使能USART1、GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);    // 配置TX(PA9):复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);    // 配置RX(PA10):浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);    // 串口参数:115200波特率,8位数据,1位停止位
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);  // 使能串口
}

4. TIM_Configuration():定时器 TIM9 配置

void TIM_Configuration(void) {
    // 使能TIM9时钟(APB2总线)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);    // 定时器参数:
    TIM_TimeBaseStructure.TIM_Period = 9999;  // 自动重载值(0~9999,共10000个周期)
    // 预分频器:PCLK2频率/10000 - 1(例如PCLK2=72MHz → 72000000/10000 - 1=7199)
    TIM_TimeBaseStructure.TIM_Prescaler = (clocks.PCLK2_Frequency / 10000) - 1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式    TIM_TimeBaseInit(TIM9, &TIM_TimeBaseStructure);  // 初始化定时器    // 使能更新中断
    TIM_ITConfig(TIM9, TIM_IT_Update, ENABLE);    // 中断配置(NVIC):
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_BRK_TIM9_IRQn;  // TIM9中断通道(与TIM1共享中断向量)
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  // 抢占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  // 子优先级3
    NVIC_Init(&NVIC_InitStructure);  // 使能中断    TIM_Cmd(TIM9, ENABLE);  // 启动定时器
}

5. 中断处理函数:TIM1_BRK_TIM9_IRQHandler()

void TIM1_BRK_TIM9_IRQHandler(void) {
    if (TIM_GetITStatus(TIM9, TIM_IT_Update)) {  // 检查更新中断标志
        TIM_ClearITPendingBit(TIM9, TIM_IT_Update);  // 清除中断标志
        printf("%s\n", __FUNCTION__);  // 打印函数名("TIM1_BRK_TIM9_IRQHandler")
    }
}

6. printf()重定向:串口输出

int fputc(int c, FILE *f) {
    if (c == '\n') SER_PutChar('\r');  // 换行时添加回车
    SER_PutChar(c);  // 通过串口发送字符
    return c;
}

该代码演示了 W55MH32 定时器 TIM9 的基本用法:配置更新中断,周期性触发并通过串口输出信息。核心流程:定时器初始化(预分频器、周期)→ 启用中断 → 中断处理(打印信息)。适用于需要周期性任务的场景(如定时采样、心跳信号)。

8.2 下载验证

WIZnet 是一家无晶圆厂半导体公司,成立于 1998 年。产品包括互联网处理器 iMCU™,它采用 TOE(TCP/IP 卸载引擎)技术,基于独特的专利全硬连线 TCP/IP。iMCU™ 面向各种应用中的嵌入式互联网设备。

WIZnet 在全球拥有 70 多家分销商,在香港、韩国、美国设有办事处,提供技术支持和产品营销。

香港办事处管理的区域包括:澳大利亚、印度、土耳其、亚洲(韩国和日本除外)。

http://www.xdnf.cn/news/615187.html

相关文章:

  • [原理理解] 超分使用到的RAM模型和LLAVA模型
  • Rules and Monetization
  • 5.2.3 使用配置文件方式整合MyBatis
  • 谷歌移动端排名和电脑端差距大?做SEO优化要选哪个?
  • Q网络(Q-Network)简介
  • Claude 4 系列 Opus 4 与 Sonnet 4正式发布:Claude 4新特性都有哪些?
  • AI独立游戏素材生成实操
  • LVGL(lv_textarea文本框控件)
  • Spring-面试题(76)
  • PTA刷题笔记2
  • AI智能体工具调研分享(未完待续)
  • 养生指南:五维打造健康新方式
  • Coze工作流文生图实战应用-哪吒表情包制作
  • LEED认证是什么?LEED认证难吗?LEED认证需要准备的资料
  • qt出现launching debugger,运行失败
  • 河道管网排口在线监测系统解决方案
  • 多路径可靠传输协议(比如 MPTCP)为什么低效
  • MIGO委外(外协)采购订单过账的增强
  • 如何选择和应用WAF技术:核心原理、应用场景与优劣势解析
  • 【接口设计文档】:在线聊天平台(Online-Chat)
  • IEC 61156-5:2020 标准技术解析与应用综述
  • 肠道微生物组研究的特有数据库
  • [C]基础15.C语言内存函数
  • centos原系统安装了Python3.7.9兼用在安装一个python3.8
  • 全面解析EDI RECADV报文:结构组成、业务应用与关键注意事项
  • Java中的集合(持续更新)
  • 如何使用WordPress区块(以及如何创建自定义区块)?
  • 常见算法题目2 - 给定一个字符串,找出其中最长的不重复子串
  • C++ std::find() 函数全解析
  • 在 Android 开发中判断用户是否开启了“允许安装未知来源应用(Install Unknown Apps)”权限