2026/4/18 5:37:13
网站建设
项目流程
提供企业网站建设公司,wordpress文章直接转html代码,安阳县七中,番禺网站制作设计目录
一、先搞懂#xff1a;STM32F1 的定时器分类#xff08;tim.c 的支持范围#xff09;
二、stm32f10x_tim.c 文件核心组成拆解
2.1 头文件与模块定义
2.2 寄存器位掩码宏定义#xff08;最开头的一大片 #define#xff09;
2.3 静态辅助函数#xff08;文件中 4…目录一、先搞懂STM32F1 的定时器分类tim.c 的支持范围二、stm32f10x_tim.c 文件核心组成拆解2.1 头文件与模块定义2.2 寄存器位掩码宏定义最开头的一大片 #define2.3 静态辅助函数文件中 4 个 static 函数2.4 核心固件库函数tim.c 的核心按功能分类2.5 结构体初始化函数必用初学者踩坑点三、定时器核心概念必懂否则不会配置库函数3.1 预分频器PSC3.2 自动重装值ARR3.3 定时时间计算核心公式3.4 计数器模式四、tim.c 典型应用案例含完整标准库代码案例 1通用定时器定时中断TIM31ms 中断入门必学步骤 1头文件包含main.c步骤 2全局变量定义用于中断计数步骤 3TIM3 定时中断初始化函数调用 tim.c 库函数步骤 4TIM3 中断服务函数必须放在 stm32f10x_it.c或 main.c 末尾步骤 5main 函数调用案例 2通用定时器 PWM 输出TIM2_CH1PA01kHz PWM 调光步骤 1TIM2_CH1 PWM 初始化函数步骤 2main 函数中调节占空比案例 3通用定时器输入捕获TIM3_CH1PA6测外部脉冲高电平时间步骤 1全局变量定义存储捕获值步骤 2TIM3_CH1 输入捕获初始化函数步骤 3TIM3 中断服务函数处理捕获事件步骤 4main 函数中读取高电平时间五、高级定时器 TIM1 的特殊点初学者踩坑点六、tim.c 使用核心技巧初学者必看七、总结stm32f10x_tim.c是STM32F10x 系列标准外设库中定时器外设的核心驱动文件ST 官方封装了定时器所有底层寄存器操作提供了易用的固件库函数让开发者无需直接操作寄存器位就能实现定时器的定时、PWM、输入捕获、编码器接口等功能。本文从初学者视角出发先讲STM32F1 定时器基础认知→再拆解tim.c 文件核心组成→讲透定时器核心概念→最后给出3 个最常用的典型应用案例含完整标准库代码所有案例均与tim.c中的库函数一一对应可直接复制测试。一、先搞懂STM32F1 的定时器分类tim.c 的支持范围STM32F10x 系列有8 个定时器分为 3 类tim.c中的函数对不同定时器有差异化支持函数内通过assert_param断言做了参数校验误用会编译报错先明确分类和差异是学习的基础定时器类型具体定时器挂载总线核心功能时钟频率tim.c 特殊支持基本定时器TIM6/TIM7APB1仅定时中断无 IO 口、无 PWM / 捕获最大 72MHzAPB1 预分频 1 时仅支持时基配置、定时中断、基本寄存器操作通用定时器TIM2/TIM3/TIM4/TIM5APB1定时中断、PWM 输出、输入捕获、编码器接口、主从触发最大 72MHz支持除刹车 / 死区外的所有定时器功能高级定时器TIM1/TIM8APB2通用定时器所有功能 互补 PWM 刹车 / 死区 / 故障保护72MHz额外支持TIM_BDTRConfig死区 / 刹车、TIM_CtrlPWMOutputs主输出使能关键时钟知识点APB1 总线最大时钟为 36MHzAPB2 为 72MHz若 APB1 预分频器配置为1通用 / 基本定时器的时钟 APB1 时钟36MHz若 APB1 预分频器 **1**定时器时钟 APB1 时钟 ×2最终还是 72MHz高级定时器挂载 APB2时钟直接为 72MHz所有定时器的计数器时钟需经过预分频器PSC分频后得到是定时 / PWM 的核心参数。二、stm32f10x_tim.c 文件核心组成拆解整个文件约 2000 行按标准库规范组织所有代码围绕定时器寄存器操作封装初学者无需逐行看懂只需掌握核心函数和宏定义的作用以下是文件的核心结构和关键部分解析2.1 头文件与模块定义#include stm32f10x_tim.h #include stm32f10x_rcc.h依赖stm32f10x_tim.h定义了定时器的结构体如TIM_TimeBaseInitTypeDef、枚举常量如定时模式、PWM 模式、外设基地址如TIM1_BASE依赖stm32f10x_rcc.h定时器外设的时钟使能 / 复位函数如RCC_APB1PeriphClockCmd操作外设的第一步必须开时钟。2.2 寄存器位掩码宏定义最开头的一大片 #define这部分是寄存器位操作的封装比如c运行#define CR1_CEN_Set ((uint16_t)0x0001) // CR1寄存器的CEN位计数器使能置1值 #define CR1_CEN_Reset ((uint16_t)0x03FE) // CR1寄存器的CEN位清0值 #define CR1_CounterMode_Mask ((uint16_t)0x038F) // 计数器模式位的掩码核心作用操作寄存器某一位 / 某几位时不影响其他位。置 1 某一位寄存器 | 置1宏如TIMx-CR1 | CR1_CEN_Set;使能计数器清 0 某一位寄存器 清0宏如TIMx-CR1 CR1_CEN_Reset;关闭计数器修改某几位先寄存器 掩码宏清 0 对应位再寄存器 | 配置值置新值。初学者无需记忆库函数已经帮我们完成了所有位操作只需调用库函数即可。2.3 静态辅助函数文件中 4 个 static 函数static void TI1_Config(...); static void TI2_Config(...); static void TI3_Config(...); static void TI4_Config(...);是tim.c内部专用函数用户不能直接调用核心功能配置定时器的输入捕获通道TI1-TI4包括捕获极性、滤波、映射关系等被上层函数TIM_ICInit()、TIM_PWMIConfig()调用隐藏了输入捕获的底层配置细节。2.4 核心固件库函数tim.c 的核心按功能分类这是我们实际开发中直接调用的函数tim.c将其按定时器功能做了分类以下是初学者最常用的函数分类 核心函数说明其他冷门函数可在需要时查阅 STM32 标准库手册功能分类核心函数作用说明初始化 / 复位TIM_DeInit(TIMx)复位定时器所有寄存器到默认值时基配置TIM_TimeBaseInit(TIMx, init)配置定时器核心时基参数预分频、自动重装、计数模式TIM_TimeBaseStructInit(init)给时基结构体赋默认值避免未初始化的随机值导致配置错误PWM / 输出比较TIM_OC1Init(TIMx, ocinit)配置通道 1 为输出比较 / PWM 模式OC2/OC3/OC4 对应通道 2-4TIM_OCStructInit(ocinit)给 PWM 结构体赋默认值TIM_SetCompare1(TIMx, val)修 PWM 通道 1 的比较值调节占空比OC2-OC4 对应通道 2-4TIM_CtrlPWMOutputs(TIMx, ENABLE)高级定时器专用使能 PWM 主输出必须调用否则无 PWM 输出输入捕获TIM_ICInit(TIMx, icinit)配置定时器输入捕获模式TIM_ICStructInit(icinit)给输入捕获结构体赋默认值TIM_GetCapture1(TIMx)获取通道 1 的捕获值IC2-IC4 对应通道 2-4中断 / 标志位TIM_ITConfig(TIMx, TIM_IT_XXX, ENABLE)使能定时器指定中断更新中断、捕获中断等TIM_GetITStatus(TIMx, TIM_IT_XXX)检查指定中断是否发生中断服务函数中用TIM_ClearITPendingBit(TIMx, TIM_IT_XXX)清除中断挂起标志中断服务函数中必须调用否则反复进入中断TIM_GetFlagStatus(TIMx, FLAG)检查定时器标志位轮询模式用TIM_ClearFlag(TIMx, FLAG)清除定时器标志位轮询模式用定时器控制TIM_Cmd(TIMx, ENABLE)使能 / 禁用定时器计数器核心函数配置完成后必须调用才会工作寄存器操作TIM_SetCounter(TIMx, val)设置定时器计数器初始值TIM_GetCounter(TIMx)获取定时器当前计数值2.5 结构体初始化函数必用初学者踩坑点tim.c提供了 4 个结构体初始化函数TIM_TimeBaseStructInit(); // 时基结构体 TIM_OCStructInit(); // PWM/输出比较结构体 TIM_ICStructInit(); // 输入捕获结构体 TIM_BDTRStructInit(); // 高级定时器死区/刹车结构体核心作用给结构体的所有成员赋安全的默认值避免因结构体成员未初始化随机值导致定时器配置异常。初学者必须遵守先调用结构体初始化函数再修改需要的参数无需修改的参数用默认值即可。三、定时器核心概念必懂否则不会配置库函数调用tim.c的库函数前必须理解 3 个核心概念这是定时器配置的基础也是TIM_TimeBaseInit时基配置的核心参数3.1 预分频器PSC寄存器TIMx-PSC库函数参数TIM_TimeBaseInitTypeDef.TIM_Prescaler作用将定时器的时钟源如 72MHz分频得到计数器时钟特性16 位无符号数取值范围0~65535实际分频系数为PSC1因为分频系数不能为 0例PSC71 → 分频系数 72 → 72MHz 时钟分频后为 1MHz计数器每 1μs 加 1。3.2 自动重装值ARR寄存器TIMx-ARR库函数参数TIM_TimeBaseInitTypeDef.TIM_Period作用定时器计数器的最大值计数器计数到该值时会触发更新事件溢出 / 下溢并重新开始计数特性16 位无符号数取值范围0~65535实际计数周期为ARR1计数器从 0 开始计数例ARR999 → 计数器从 0 计数到 999共 1000 个计数周期。3.3 定时时间计算核心公式定时器向上计数模式最常用的定时时间更新事件触发间隔公式TTclk(PSC1)×(ARR1)T定时时间单位秒 (s)PSC预分频器值ARR自动重装值Tclk定时器时钟频率单位HzF1 通用 / 基本 / 高级定时器最大均为 72MHz。简化常用单位若Tclk72MHz72000000HzPSC71 → 计数器时钟 1MHz1μs / 计数则定时时间 T(ms)(ARR1)×1μs×1000例ARR999 → T1000×1μs1msARR4999 → T5ms。若需 10ms 定时PSC719分频 100 倍计数器时钟 100kHz10μs / 计数ARR999 → T1000×10μs10ms。3.4 计数器模式库函数参数TIM_TimeBaseInitTypeDef.TIM_CounterMode最常用向上计数其他模式按需使用TIM_CounterMode_Up向上计数从 0→ARR溢出触发更新事件→ 定时中断、PWM 均用此模式TIM_CounterMode_Down向下计数从 ARR→0下溢触发更新事件TIM_CounterMode_CenterAligned1/2/3中心对齐向上 向下用于高精度 PWM。四、tim.c 典型应用案例含完整标准库代码以下 3 个案例是 STM32F1 定时器最常用的场景覆盖定时中断、PWM 输出、输入捕获基于STM32F103C8T6最小系统板使用标准库 V3.5所有代码均调用tim.c中的库函数注释详细初学者可直接复制测试。案例 1通用定时器定时中断TIM31ms 中断入门必学需求使用 TIM3通用定时器配置 1ms 定时中断在中断服务函数中翻转 LEDPB5实现 LED 每秒闪烁1ms 中断 ×1000 次 1s。核心函数TIM_TimeBaseInit、TIM_ITConfig、TIM_Cmd、TIM_ClearITPendingBit。定时器时钟72MHzPSC71ARR999 → 1ms 定时符合上述公式。步骤 1头文件包含main.c#include stm32f10x.h #include stm32f10x_tim.h #include stm32f10x_gpio.h #include misc.h // NVIC中断配置头文件步骤 2全局变量定义用于中断计数u16 g_tim3_cnt 0; // TIM3中断计数变量步骤 3TIM3 定时中断初始化函数调用 tim.c 库函数void TIM3_Init_1ms(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; // 时基结构体 NVIC_InitTypeDef NVIC_InitStruct; // 中断优先级结构体 // 1. 使能时钟TIM3在APB1GPIOB在APB2 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 2. 配置PB5为推挽输出LED GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin GPIO_Pin_5; GPIO_InitStruct.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOB, GPIO_InitStruct); GPIO_SetBits(GPIOB, GPIO_Pin_5); // 初始LED灭 // 3. 配置TIM3时基参数调用tim.c的TIM_TimeBaseStructInit TIM_TimeBaseStructInit(TIM_TimeBaseInitStruct); // 先赋默认值 TIM_TimeBaseInitStruct.TIM_Prescaler 71; // 预分频器71分频系数72 TIM_TimeBaseInitStruct.TIM_Period 999; // 自动重装值999 TIM_TimeBaseInitStruct.TIM_CounterMode TIM_CounterMode_Up; // 向上计数 TIM_TimeBaseInit(TIM3, TIM_TimeBaseInitStruct); // 调用tim.c的时基配置函数 // 4. 使能TIM3更新中断更新中断计数器溢出调用tim.c的TIM_ITConfig TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // 5. 配置NVIC中断优先级TIM3中断 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 分组22位抢占2位响应 NVIC_InitStruct.NVIC_IRQChannel TIM3_IRQn; // TIM3中断通道 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority 2; // 抢占优先级2 NVIC_InitStruct.NVIC_IRQChannelSubPriority 2; // 响应优先级2 NVIC_InitStruct.NVIC_IRQChannelCmd ENABLE; // 使能中断通道 NVIC_Init(NVIC_InitStruct); // 6. 使能TIM3计数器调用tim.c的TIM_Cmd核心 TIM_Cmd(TIM3, ENABLE); }步骤 4TIM3 中断服务函数必须放在 stm32f10x_it.c或 main.c 末尾void TIM3_IRQHandler(void) { // 检查TIM3更新中断是否发生调用tim.c的TIM_GetITStatus if(TIM_GetITStatus(TIM3, TIM_IT_Update) ! RESET) { g_tim3_cnt; // 中断计数 if(g_tim3_cnt 1000) // 1ms×10001s { g_tim3_cnt 0; GPIO_WriteBit(GPIOB, GPIO_Pin_5, !GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_5)); // 翻转LED } TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // 清中断标志调用tim.c必须 } }步骤 5main 函数调用int main(void) { TIM3_Init_1ms(); // 初始化TIM3 1ms中断 while(1) { // 主循环无需操作中断自动处理 } }案例 2通用定时器 PWM 输出TIM2_CH1PA01kHz PWM 调光需求使用 TIM2_CH1PA0通用定时器输出 1kHz PWM 波占空比可调用于 LED 调光PA0 接 LED。核心函数TIM_OC1Init、TIM_OC1PreloadConfig、TIM_SetCompare1、TIM_ARRPreloadConfig。参数计算72MHz 时钟PSC71ARR99 → 计数器时钟 1MHzPWM 频率 1MHz/(991)10kHz修正PSC7199ARR9 → 72MHz/(71991)10kHz10kHz/(91)1kHz准确 1kHz PWM。步骤 1TIM2_CH1 PWM 初始化函数void TIM2_PWM_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_OCInitTypeDef TIM_OCInitStruct; GPIO_InitTypeDef GPIO_InitStruct; // 1. 使能时钟TIM2(APB1)、GPIOA(APB2) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 复用功能时钟必须 // 2. 配置PA0为**复用推挽输出**TIM2_CH1 PWM输出关键普通推挽不行 GPIO_InitStruct.GPIO_Pin GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP; // 复用推挽定时器控制IO口 GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStruct); // 3. 配置TIM2时基参数1kHz PWM TIM_TimeBaseStructInit(TIM_TimeBaseInitStruct); TIM_TimeBaseInitStruct.TIM_Prescaler 7199; // 预分频7199分频系数7200 → 72MHz/720010kHz TIM_TimeBaseInitStruct.TIM_Period 9; // 自动重装9 → 10kHz/(91)1kHz TIM_TimeBaseInitStruct.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM_TimeBaseInitStruct); // 4. 配置TIM2_CH1为PWM模式调用tim.c的TIM_OCStructInit TIM_OCStructInit(TIM_OCInitStruct); // 先赋默认值 TIM_OCInitStruct.TIM_OCMode TIM_OCMode_PWM1; // PWM模式1最常用 /* PWM1模式规则向上计数时CNT CCR1 → 输出有效电平CNT ≥ CCR1 → 无效 */ TIM_OCInitStruct.TIM_OCPolarity TIM_OCPolarity_High; // 有效电平为高 TIM_OCInitStruct.TIM_OutputState TIM_OutputState_Enable; // 使能输出 TIM_OCInitStruct.TIM_Pulse 4; // 初始比较值4 → 占空比4/(91)40% TIM_OC1Init(TIM2, TIM_OCInitStruct); // 配置通道1调用tim.c的OC1Init // 5. 使能**预装载功能**关键PWM占空比平滑调节 TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); // 使能CCR1预装载 TIM_ARRPreloadConfig(TIM2, ENABLE); // 使能ARR预装载 // 6. 使能TIM2计数器 TIM_Cmd(TIM2, ENABLE); }步骤 2main 函数中调节占空比int main(void) { u16 pwm_val 0; u8 dir 1; TIM2_PWM_Init(); // 初始化PWM while(1) { // 占空比从0→100%→0循环实现LED呼吸灯 if(dir) pwm_val; else pwm_val--; if(pwm_val 9) dir 0; if(pwm_val 0) dir 1; TIM_SetCompare1(TIM2, pwm_val); // 调用tim.c的函数修改比较值调节占空比 for(u32 i0; i30000; i); // 简单延时 } }PWM 关键知识点复用推挽输出定时器 PWM 输出的 IO 口必须配置为GPIO_Mode_AF_PP并使能 AFIO 时钟PWM 模式 1最常用向上计数时CNT CCRx输出有效电平反之无效预装载功能使能后TIM_SetCompare1修改的 CCR1 值会在更新事件时生效避免 PWM 波出现毛刺占空比计算占空比 CCRx / (ARR1) × 100%本案例 ARR9CCRx0→0%CCRx9→100%。案例 3通用定时器输入捕获TIM3_CH1PA6测外部脉冲高电平时间需求使用 TIM3_CH1PA6配置输入捕获捕获外部脉冲的高电平时间如按键按下时间、传感器脉冲宽度核心是上升沿捕获开始下降沿捕获结束通过两次捕获值计算时间。核心函数TIM_ICInit、TIM_GetCapture1、TIM_ICPolarityConfig。参数配置72MHz 时钟PSC71 → 计数器时钟 1MHz1μs / 计数捕获值差 ×1μs 即为高电平时间。步骤 1全局变量定义存储捕获值u8 g_capture_flag 0; // 捕获标志0-未捕获1-捕获到上升沿2-捕获到下降沿 u16 g_capture_val1 0; // 上升沿捕获值 u16 g_capture_val2 0; // 下降沿捕获值 u32 g_high_time 0; // 高电平时间μs步骤 2TIM3_CH1 输入捕获初始化函数void TIM3_IC_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_ICInitTypeDef TIM_ICInitStruct; GPIO_InitTypeDef GPIO_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; // 1. 使能时钟TIM3(APB1)、GPIOA(APB2)、AFIO(APB2) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); // 2. 配置PA6为**上拉输入**TIM3_CH1输入捕获外部脉冲接PA6 GPIO_InitStruct.GPIO_Pin GPIO_Pin_6; GPIO_InitStruct.GPIO_Mode GPIO_Mode_IPU; // 上拉输入无信号时为高 GPIO_Init(GPIOA, GPIO_InitStruct); // 3. 配置TIM3时基参数1μs/计数 TIM_TimeBaseStructInit(TIM_TimeBaseInitStruct); TIM_TimeBaseInitStruct.TIM_Prescaler 71; // 72MHz/721MHz TIM_TimeBaseInitStruct.TIM_Period 65535; // 自动重装最大值避免溢出 TIM_TimeBaseInitStruct.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, TIM_TimeBaseInitStruct); // 4. 配置TIM3_CH1为输入捕获模式调用tim.c的TIM_ICStructInit TIM_ICStructInit(TIM_ICInitStruct); TIM_ICInitStruct.TIM_Channel TIM_Channel_1; // 通道1 TIM_ICInitStruct.TIM_ICPolarity TIM_ICPolarity_Rising; // 初始上升沿捕获 TIM_ICInitStruct.TIM_ICSelection TIM_ICSelection_DirectTI; // 直接映射TI1→IC1 TIM_ICInitStruct.TIM_ICPrescaler TIM_ICPSC_DIV1; // 无预分频每个脉冲都捕获 TIM_ICInitStruct.TIM_ICFilter 0x03; // 滤波值3减小干扰 TIM_ICInit(TIM3, TIM_ICInitStruct); // 5. 使能TIM3捕获中断通道1 TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); // 6. 配置NVIC中断优先级 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStruct.NVIC_IRQChannel TIM3_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority 2; NVIC_InitStruct.NVIC_IRQChannelSubPriority 3; NVIC_InitStruct.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStruct); // 7. 使能TIM3计数器 TIM_Cmd(TIM3, ENABLE); }步骤 3TIM3 中断服务函数处理捕获事件void TIM3_IRQHandler(void) { // 检查通道1捕获中断是否发生 if(TIM_GetITStatus(TIM3, TIM_IT_CC1) ! RESET) { if(g_capture_flag 0) // 第一次捕获上升沿 { g_capture_val1 TIM_GetCapture1(TIM3); // 读取上升沿捕获值tim.c TIM_SetCounter(TIM3, 0); // 计数器清0重新开始计数 // 切换捕获极性为下降沿准备捕获结束 TIM_IC1PolarityConfig(TIM3, TIM_ICPolarity_Falling); g_capture_flag 1; // 标记为已捕获上升沿 } else if(g_capture_flag 1) // 第二次捕获下降沿 { g_capture_val2 TIM_GetCapture1(TIM3); // 读取下降沿捕获值 g_high_time g_capture_val2; // 计算高电平时间1μs×值 // 切换捕获极性为上升沿准备下一次捕获 TIM_IC1PolarityConfig(TIM3, TIM_ICPolarity_Rising); g_capture_flag 2; // 标记为捕获完成 } TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); // 清捕获中断标志 } }步骤 4main 函数中读取高电平时间int main(void) { TIM3_IC_Init(); // 初始化输入捕获 while(1) { if(g_capture_flag 2) // 捕获完成 { // g_high_time 即为高电平时间单位μs // 可在此处做后续处理如串口打印、判断等 g_capture_flag 0; // 重置标志准备下一次捕获 } } }输入捕获关键知识点输入捕获 IO 口配置为上拉 / 下拉输入避免外部无信号时的电平抖动捕获滤波TIM_ICFilter设置滤波值0~15值越大滤波效果越好适合干扰大的场景极性切换通过TIM_IC1PolarityConfig切换捕获极性上升 / 下降沿实现脉冲宽度捕获计数器清 0捕获上升沿后清 0 计数器简化高电平时间计算无需处理计数器溢出。五、高级定时器 TIM1 的特殊点初学者踩坑点若使用TIM1/TIM8高级定时器输出 PWM除了上述通用定时器的配置步骤必须多调用一个函数否则无 PWM 输出TIM_CtrlPWMOutputs(TIM1, ENABLE); // 调用tim.c的函数使能TIM1主输出原因高级定时器带有刹车 / 死区 / 故障保护功能PWM 输出默认被禁止必须通过TIM_CtrlPWMOutputs使能主输出MOE 位才能让 PWM 波从 IO 口输出。六、tim.c 使用核心技巧初学者必看先开时钟再配置操作任何外设的第一步都是使能时钟定时器时钟分 APB1TIM2-7和 APB2TIM1/8结构体先初始化再修改必须先调用TIM_XXXStructInit再修改需要的参数避免随机值导致配置异常最后使能计数器所有配置完成后必须调用TIM_Cmd(TIMx, ENABLE)定时器才会开始工作中断服务函数必清标志无论是更新中断还是捕获中断必须调用TIM_ClearITPendingBit清标志否则会反复进入中断PWM 输出必配复用推挽定时器 PWM 输出的 IO 口必须配置为GPIO_Mode_AF_PP并使能 AFIO 时钟输入捕获必配输入模式输入捕获的 IO 口必须配置为GPIO_Mode_IPU/IPD上拉 / 下拉输入不能用推挽输出。七、总结stm32f10x_tim.c是 STM32F1 定时器的标准库驱动核心ST 官方将复杂的寄存器位操作封装为易用的库函数初学者无需关注底层寄存器只需掌握3 个核心概念PSC/ARR/ 定时时间和核心库函数的调用就能实现定时器的所有功能。本文的 3 个典型案例覆盖了定时器90% 的实际应用场景定时中断是嵌入式系统的基础用于定时任务如串口发送、数据采集、LED 闪烁PWM 输出用于电机调速、LED 调光、舵机控制等输入捕获用于测量外部脉冲的频率、周期、宽度如红外接收、超声波测距、按键消抖。掌握这些内容后再学习高级定时器的死区 / 刹车、编码器接口等功能就能全面掌握 STM32F1 的定时器使用。