
第九章 定时器:时基单元、PWM 与输入捕获
9.1 [定时器]时基单元
定时器简介
| 定时器类别 | 核心型号 | 核心功能 | 总线归属 | 适用场景 |
|---|---|---|---|---|
| 基本定时器 | TIM6/TIM7 | 仅基础向上计数、定时中断,支持 DAC 触发;无 IO 输出 / 捕获 / 比较 / PWM 功能 | APB1 | 简单定时、喂看门狗、DAC 触发 |
| 通用定时器 | TIM2/TIM3/TIM4/TIM5 | 向上 / 向下 / 中央对齐计数,支持 PWM 输出、输入捕获、编码器接口 | APB1 | PWM 驱动、脉冲测量、编码器测速、常规定时 |
| 高级定时器 | TIM1/TIM8 | 含通用定时器所有功能,新增死区控制、互补输出、刹车 / 断路、三相 PWM | APB2 | 工业电机驱动、大功率变频器、硬件保护场景 |

时基单元的基本结构

上计数、下计数和中心对齐

时钟的来源


寄存器预加载

- 核心结构:寄存器分为影子寄存器(软件写入目标)和活动寄存器(硬件实际生效的寄存器)
- 写入与生效流程:
- 软件直接写入 → 影子寄存器(暂存新值,不立即影响硬件计数)
- 当更新事件(update)发生时 → 影子寄存器的值加载到活动寄存器 → 新配置正式生效
- 设计意义:
- 避免计数中途修改寄存器导致的计数紊乱
- 保证定时器行为的同步性与稳定性,防止中间状态干扰
- 典型场景:修改 ARR/PSC 等关键寄存器时,新值会在下一个更新周期才生效,确保计数周期完整
9.2 [定时器]自制延迟函数

获取单片机的当前时间

实现延迟函数
App_Delay
void App_Delay(uint32_t ms);
void App_Delay(uint32_t ms)
{
uint32_t expireTime = currentTick + ms;
// 完整的非阻塞延时循环:等待当前时间超过到期时间
while(currentTick < expireTime);
}
初始化时基单元
App_TIM3_TimeBaseInit
void App_TIM3_TimeBaseInit(void);
void App_TIM3_TimeBaseInit(void)
{
// #1. 开启定时器3的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// #2. 配置时基单元的参数
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_Prescaler = 71; // 预分频值
TIM_TimeBaseInitStruct.TIM_Period = 999; // 自动重装载值
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; // 重复计数器(高级定时器特有)
// 初始化TIM3的时基单元
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
// #3. 闭合时基单元的开关
TIM_Cmd(TIM3, ENABLE);
// #4. 使能Update中断
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
// #5. 配置NVIC模块
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
配置中断
TIM3_IRQHandler
void TIM3_IRQHandler(void);
void TIM3_IRQHandler(void)
{
if(TIM_GetFlagStatus(TIM3, TIM_FLAG_Update) == SET)
{
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
currentTick++;
}
}
编写中断响应函数
此处需要取消注释startup_文件中的systeminit,否则闪烁时间约为4.5s
完整实验代码
#include "stm32f10x.h"
volatile uint32_t currentTick = 0; // 用来记录当前时间,单位是ms
void App_Delay(uint32_t ms);
void App_TIM3_TimeBaseInit(void);
void App_OnBoardLED_Init(void);
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
App_TIM3_TimeBaseInit();
App_OnBoardLED_Init();
while(1)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
App_Delay(500);
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
App_Delay(500);
}
}
void App_Delay(uint32_t ms)
{
uint32_t expireTime = currentTick + ms;
// 完整的非阻塞延时循环:等待当前时间超过到期时间
while(currentTick < expireTime);
}
void App_TIM3_TimeBaseInit(void)
{
// #1. 开启定时器3的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// #2. 配置时基单元的参数
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_Prescaler = 71; // 预分频值
TIM_TimeBaseInitStruct.TIM_Period = 999; // 自动重装载值
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; // 重复计数器(高级定时器特有)
// 初始化TIM3的时基单元
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
// #3. 闭合时基单元的开关
TIM_Cmd(TIM3, ENABLE);
// #4. 使能Update中断
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
// #5. 配置NVIC模块
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
void TIM3_IRQHandler(void)
{
if(TIM_GetFlagStatus(TIM3, TIM_FLAG_Update) == SET)
{
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
currentTick++;
}
}
void App_OnBoardLED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
}
9.3 [定时器]输出比较
输出比较简介
当定时器的计数器(CNT)值与捕获 / 比较寄存器(CCR)的值相等时,自动执行预设的输出动作(如电平翻转、置高 / 置低)或触发中断 / DMA 请求。
基本工作原理(PWM)


8种工作模式


互补输出

极性选择

9.4 [定时器]呼吸灯实验
呼吸灯原理

初始化IO引脚


注意第一排上的排针要在同一排上

长脚为正极

配置时基单元

配置输出比较的参数
需要手动加载 自动重装寄存器ARR,预分频器PSC和重复计数器RCR 自动加载。

改变PWM占空比
需要手动加载 比较寄存器x CCRx

完整实验代码
#include "stm32f10x.h"
#include "delay.h" // 用于获取当前时间t
#include "math.h" // 引入正弦函数
void App_PWM_Init(void);
int main(void)
{
App_PWM_Init();
while(1)
{
float t = GetTick() * 1.0e-3f;
float duty = 0.5*(sin(2*3.14*t) + 1);
uint16_t ccr1 = duty * 1000;
TIM_SetCompare1(TIM1, ccr1);
}
}
void App_PWM_Init(void)
{
// #1. 初始化IO引脚 PA8 PB13
GPIO_InitTypeDef GPIO_InitStruct;
// PA8
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// PB13
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// #2. 配置时基单元
// #2.1 开启TIM1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
// #2.2 配置时基单元的参数
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 999;
TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);
// #2.3 开启ARR的预加载
TIM_ARRPreloadConfig(TIM1, ENABLE);
// #2.4 闭合时基单元的开关
TIM_Cmd(TIM1, ENABLE);
// #3. 初始化输出比较
// #3.1 初始化输出比较通道1的参数
TIM_OCInitTypeDef TIM_OCInitStruct;
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_Pulse = 0;
TIM_OC1Init(TIM1, &TIM_OCInitStruct);
// #3.2 闭合MOE总开关
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_CCPreloadControl(TIM1, ENABLE);
}
9.5 [定时器]输入捕获
输入捕获的基本原理

输入捕获的内部结构

输入滤波
输入滤波:滤除输入信号的噪音

边沿检测
检测输入信号的变化边沿(上升沿 / 下降沿)
信号选择
复用器(TRC,直接,间接)

分频器

9.6 [定时器]超声波测距实验
HCSR-04模块的使用方法


搭建电路


梳理思路


初始化时基单元


初始化输入捕获
TIM_ICInit
// @参数:初始化输入捕获
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
编程

完整实验代码
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
void App_USART1_Init(void);
void App_HCSR04_Init(void);
int main(void)
{
App_USART1_Init();
App_HCSR04_Init();
while(1)
{
// #1. 向CNT写0
TIM_SetCounter(TIM1, 0);
// #2. 清除cc1和cc2标志位
TIM_ClearFlag(TIM1, TIM_FLAG_CC1);
TIM_ClearFlag(TIM1, TIM_FLAG_CC2);
// #3. 开启定时器
TIM_Cmd(TIM1, ENABLE);
// #4. 向TRIG引脚发送10us的脉冲
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
DelayUs(10); // 延迟10us
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
// #5. 等待测量完成
while (TIM_GetFlagStatus(TIM1, TIM_FLAG_CC1) == RESET);
while (TIM_GetFlagStatus(TIM1, TIM_FLAG_CC2) == RESET);
// #6. 关闭定时器
TIM_Cmd(TIM1, DISABLE);
uint16_t ccr1 = TIM_GetCapture1(TIM1);
uint16_t ccr2 = TIM_GetCapture2(TIM1);
float distance = (ccr2 - ccr1) * 1.0e-6f * 340.0f / 2;
My_USART_Printf(USART1, "distance = %.4f\r\n", distance);
Delay(100);
}
}
void App_USART1_Init(void)
{
// #1. 初始化IO引脚
GPIO_InitTypeDef GPIO_InitStruct;
// PA9 AF_PP
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// PA10 IPU
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// #2. 初始化USART1
// #2.1 开启USART1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// #2.2 初始化USART1的参数
USART_InitTypeDef USART_InitStruct;
USART_InitStruct.USART_BaudRate = 115200;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &USART_InitStruct);
// #2.3 闭合总开关
USART_Cmd(USART1, ENABLE);
}
void App_HCSR04_Init(void)
{
// #1. 初始化时基单元
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 65535;
TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);
// #2. 初始化输入捕获
// #2.1. 初始化IO引脚 PA8 IPD
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// #2.2. 初始化输入捕获的通道1
TIM_ICInitTypeDef TIM_ICInitStruct;
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
TIM_ICInitStruct.TIM_ICFilter = 0;
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInit(TIM1, &TIM_ICInitStruct);
// #2.3 初始化输入捕获的通道2
TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
TIM_ICInitStruct.TIM_ICFilter = 0;
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_IndirectTI;
TIM_ICInit(TIM1, &TIM_ICInitStruct);
// #3. 初始化Trig引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
}
9.7 [定时器]从模式控制器
从模式控制器的概念


8种从模式

8种主模式

定时器同时启停案例

定时器级联案例

9.8 [定时器]PWM参数测量原理
PWM信号:周期恒定,占空比可调节
参考手册的定时器结构框图


输入捕获节点的名字

TRGI的来源

PWM参数测量原理

9.9 [定时器]PWM参数测量实验
实验原理

产生PWM信号

呼吸灯实验
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
#include <math.h>
void App_USART1_Init(void);
void App_TIM3_Init(void);
int main(void)
{
App_USART1_Init();
App_TIM3_Init();
while (1)
{
float t = GetTick() * 1.0e-3f;
float duty = 0.5 * (sin(2 * 3.14 * t) + 1);
uint16_t ccrl = duty * 999;
TIM_SetCompare1(TIM3, ccrl);
}
}
void App_USART1_Init(void)
{
// #1. 初始化IO引脚 PA9 AF_PP
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// #2.2 配置USART1的参数
USART_InitTypeDef USART_InitStruct = {0};
USART_InitStruct.USART_BaudRate = 115200;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Tx;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &USART_InitStruct);
// #2.3 闭合总开关
USART_Cmd(USART1, ENABLE);
}
void App_TIM3_Init(void)
{
// #1. 初始化时基单元
// #1.1 开启TIM3的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// #1.2 配置时基单元的参数
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct = {0};
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 999;
TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
// #1.3 开启ARR的预加载
TIM_ARRPreloadConfig(TIM3, ENABLE);
// #1.4 闭合时基单元的总开关
TIM_Cmd(TIM3, ENABLE);
// #2. 初始化输出比较的通道1
// #2.1 初始化PA6
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// #2.2 配置OC1的参数
TIM_OCInitTypeDef TIM_OCInitStruct = {0};
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_OutputState = ENABLE;
TIM_OCInitStruct.TIM_Pulse = 0;
TIM_OC1Init(TIM3, &TIM_OCInitStruct);
// #2.3 使能MOE
TIM_CtrlPWMOutputs(TIM3, ENABLE);
// #2.4 使能CCRx的预加载
TIM_CCPreloadControl(TIM3, ENABLE);
}
初始化时基单元
TIM1

初始化输入捕获
初始化从模式控制器
测量PWM参数
完整实验代码
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
#include <math.h>
void App_USART1_Init(void);
void App_TIM3_Init(void);
void App_TIM1_Init(void);
int main(void)
{
App_USART1_Init();
App_TIM3_Init();
App_TIM1_Init();
TIM_SetCompare1(TIM3, 200); // 200/1000,即20%占空比
while (1)
{
// #1. 清除Trigger标志位
TIM_ClearFlag(TIM1, TIM_FLAG_Trigger);
// #2. 等待Trigger标志位从0变为1
while(TIM_GetFlagStatus(TIM1, TIM_FLAG_Trigger) == RESET);
// #3. 计算
uint16_t ccr1 = TIM_GetCapture1(TIM1);
uint16_t ccr2 = TIM_GetCapture2(TIM1);
float period = ccr1 * 1.0e-6f * 1.0e3f;
float duty = ((float)ccr2) / ccr1 * 100.0f;
My_USART_Printf(USART1, "周期=%.3fms, 占空比=%.2f%%\r\n", period, duty);
Delay(100);
}
}
void App_USART1_Init(void)
{
// #1. 初始化IO引脚 PA9 AF_PP
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// #2.2 配置USART1的参数
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
USART_InitTypeDef USART_InitStruct = {0};
USART_InitStruct.USART_BaudRate = 115200;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Tx;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &USART_InitStruct);
// #2.3 闭合总开关
USART_Cmd(USART1, ENABLE);
}
void App_TIM3_Init(void)
{
// #1. 初始化时基单元
// #1.1 开启TIM3的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// #1.2 配置时基单元的参数
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct = {0};
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 999;
TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
// #1.3 开启ARR的预加载
TIM_ARRPreloadConfig(TIM3, ENABLE);
// #1.4 闭合时基单元的总开关
TIM_Cmd(TIM3, ENABLE);
// #2. 初始化输出比较的通道1
// #2.1 初始化PA6
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// #2.2 配置OC1的参数
TIM_OCInitTypeDef TIM_OCInitStruct = {0};
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_OutputState = ENABLE;
TIM_OCInitStruct.TIM_Pulse = 0;
TIM_OC1Init(TIM3, &TIM_OCInitStruct);
// #2.3 使能MOE
TIM_CtrlPWMOutputs(TIM3, ENABLE);
// #2.4 使能CCRx的预加载
TIM_CCPreloadControl(TIM3, ENABLE);
}
void App_TIM1_Init(void)
{
// #1. 配置时基单元
// #1.1 开启定时器1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
// #1.2 配置时基单元的参数
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct = {0};
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 65535;
TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);
// #1.3 开启ARR的预加载
TIM_ARRPreloadConfig(TIM1, ENABLE);
// #1.4 闭合时基单元的总开关
TIM_Cmd(TIM1, ENABLE);
// #2. 初始化输入捕获
// #2.1 初始化PA8引脚 IPD
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// #2.2 初始化输入捕获通道1
TIM_ICInitTypeDef TIM_ICInitStruct = {0};
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
TIM_ICInitStruct.TIM_ICFilter = 0;
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInit(TIM1, &TIM_ICInitStruct);
// #2.3 初始化输入捕获通道2
TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
TIM_ICInitStruct.TIM_ICFilter = 0;
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_IndirectTI;
TIM_ICInit(TIM1, &TIM_ICInitStruct);
// #3. 初始化从模式控制器
TIM_SelectInputTrigger(TIM1, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM1, TIM_SlaveMode_Reset);
}
本文由 FormerlyXZ 创作, 采用CC BY-NC-SA 4.0 许可协议。
转载请注明出处,禁止商业使用。
评论
评论由 Giscus提供。首次评论需要在评论框里登录一次 GitHub(与页头的站点登录互相独立,这是浏览器安全限制), 之后当前浏览器会记住,不用反复登录;评论框里可以直接粘贴图片、拖入 PDF 等附件(GitHub 会帮你存好)。
