STM32标准库-输入捕获
一、输入捕获1.简介
IC(Input Capture)输入捕获输入
捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数
每个高级定时器和通用定时器都拥有4个输入捕获通道
可配置为PWMI模式,同时测量频率和占空比
可配合主从触发模式,实现硬件全自动测量
2.频率测量
测频法适合测量高频信号,测周法适合测量低频信号。测频法要求信号频率要稍微高一些。那对于测周法就要求信号频率低一些了,低频信号周期比较长,计次就会比较多,有助于减小误差。
对应图上,当待测信号频率小于中介频率时,测周法误差更小,选用测周法更合适。当待测信号频率大于中间频率时,测频法误差更小,选用测频法更合适。
3.输入捕获通道
4.主从触发模式
主从触发模式就是主模式、从模式和触发源选择这三个功能的简称。
其中主模式可以将定时器内部的信号映射到TRGO引脚。用于触发别的外设。所以这部分叫做主模式。
从模式,就是接收其他外设或者自身外设的一些信号,用于控制自身定时器的运行,也就是被别的信号控制,所以这部分叫从模式。
触发源选择就是选择从模式的触发信号源的,你可以认为它是从模式的一部分。触发源选择指定的一个信号,得到TRGI,TRGI去触发从模式,从模式可以在这个列表里选择一项操作来自动执行。
5.输入捕获基本结构
6.PWMI基本结构
配置为PWMI模式,同时测量频率和占空比。这个PWM模式就是PWM的输入模式,是专门为测量PWM频率和占空比设计的。
PWM模式和主从触发模式设计的非常巧妙,把这两个功能结合起来测量频率占空比,就是硬件全自动执行。软件不需要进行任何干预,也不需要进行中断,需要测量的时候直接读取CCR计算器,极大的减轻了软件的压力。
二、输入捕获模式测频率
1.接线图
2.代码
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
PWM_Init(); //PWM初始化
IC_Init(); //输入捕获初始化
/*显示静态字符串*/
OLED_ShowString(1, 1, "Freq:00000Hz"); //1行1列显示字符串Freq:00000Hz
/*使用PWM模块提供输入捕获的测试信号*/
PWM_SetPrescaler(720 - 1); //PWM频率Freq = 72M / (PSC + 1) / 100
PWM_SetCompare1(50); //PWM占空比Duty = CCR / 100
while (1)
{
OLED_ShowNum(1, 6, IC_GetFreq(), 5); //不断刷新显示输入捕获测得的频率
}
}
IC.c
#include "stm32f10x.h" // Device header
/**
* 函 数:输入捕获初始化
* 参 数:无
* 返 回 值:无
*/
void IC_Init(void)
{
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //开启TIM3的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA6引脚初始化为上拉输入
/*配置时钟源*/
TIM_InternalClockConfig(TIM3); //选择TIM3为内部时钟,若不调用此函数,TIM默认也为内部时钟
/*时基单元初始化*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM3的时基单元
/*输入捕获初始化*/
TIM_ICInitTypeDef TIM_ICInitStructure; //定义结构体变量
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择配置定时器通道1
TIM_ICInitStructure.TIM_ICFilter = 0xF; //输入滤波器参数,可以过滤信号抖动
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //极性,选择为上升沿触发捕获
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //捕获预分频,选择不分频,每次信号都触发捕获
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //输入信号交叉,选择直通,不交叉
TIM_ICInit(TIM3, &TIM_ICInitStructure); //将结构体变量交给TIM_ICInit,配置TIM3的输入捕获通道
/*选择触发源及从模式*/
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); //触发源选择TI1FP1
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); //从模式选择复位
//即TI1产生上升沿时,会触发CNT归零
/*TIM使能*/
TIM_Cmd(TIM3, ENABLE); //使能TIM3,定时器开始运行
}
/**
* 函 数:获取输入捕获的频率
* 参 数:无
* 返 回 值:捕获得到的频率
*/
uint32_t IC_GetFreq(void)
{
return 1000000 / (TIM_GetCapture1(TIM3) + 1); //测周法得到频率fx = fc / N,这里不执行+1的操作也可
}
IC.c
#ifndef __IC_H
#define __IC_H
void IC_Init(void);
uint32_t IC_GetFreq(void);
#endif
3.相关API
1. void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
功能:使能或禁用 APB1 总线上的外设时钟
参数:
RCC_APB1Periph
:选择 APB1 外设(x 为外设枚举值)
可选值(部分):
RCC_APB1Periph_TIM2:TIM2 定时器
RCC_APB1Periph_TIM3:TIM3 定时器(输入捕获用)
RCC_APB1Periph_I2C1:I2C1 接口
NewState
:时钟使能状态
可选值:
ENABLE:使能时钟
DISABLE:禁用时钟
返回值:无
2. void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
功能:初始化 GPIO 引脚的模式、速度等参数
参数:
GPIOx
:选择 GPIO 端口(x 为端口字母)
可选值:
GPIOA、GPIOB、GPIOC等(如 PA6 对应GPIOA)
GPIO_InitStruct
:指向 GPIO 配置结构体的指针
结构体成员(部分):
GPIO_Mode
:引脚模式
可选值:
GPIO_Mode_IPU:上拉输入(输入捕获用)
GPIO_Mode_AF_PP:复用推挽输出
GPIO_Pin
:引脚号
可选值:
GPIO_Pin_0~GPIO_Pin_15(如 PA6 对应GPIO_Pin_6)
GPIO_Speed
:输出速度(输入模式无效)
可选值:
GPIO_Speed_10MHz、GPIO_Speed_50MHz
返回值:无
3. void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
功能:选择定时器的时钟源为内部时钟(默认配置)
参数:
TIMx
:选择定时器(x 为定时器编号)
可选值:
TIM2、TIM3(输入捕获用)、TIM4等
返回值:无
4. void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
功能:配置定时器的时基参数(计数周期、分频等)
参数:
TIMx
:选择定时器
可选值:
TIM3(输入捕获用)、TIM2、TIM4等
TIM_TimeBaseInitStruct
:指向时基配置结构体的指针
结构体成员(部分):
TIM_Period
:自动重装值(ARR)
可选值:
0~65535(16 位计数器,如65535对应最大周期)
TIM_Prescaler
:预分频值(PSC)
可选值:
0~65535(如71对应 72 分频,计数器时钟 1MHz)
TIM_CounterMode
:计数模式
可选值:
TIM_CounterMode_Up:向上计数(输入捕获用)
TIM_CounterMode_Down:向下计数
返回值:无
5. void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
功能:初始化定时器的输入捕获通道参数
参数:
TIMx
:选择定时器
可选值:
TIM3(输入捕获用)、TIM2、TIM4等
TIM_ICInitStruct
:指向输入捕获配置结构体的指针
结构体成员(部分):
TIM_Channel
:捕获通道
可选值:
TIM_Channel_1:通道 1(输入捕获用)
TIM_Channel_2~TIM_Channel_4
TIM_ICPolarity
:捕获极性
可选值:
TIM_ICPolarity_Rising:上升沿捕获(输入捕获用)
TIM_ICPolarity_Falling:下降沿捕获
TIM_ICFilter
:输入滤波器参数
可选值:
0x0~0xF(如0xF表示最强滤波,抗干扰)
返回值:无
6. void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TS);
功能:选择定时器从模式的触发源
参数:
TIMx
:选择定时器
可选值:
TIM3(输入捕获用)、TIM2、TIM4等
TIM_TS
:触发源选择
可选值(输入捕获相关):
TIM_TS_TI1FP1:使用通道 1 的滤波后信号(输入捕获用)
TIM_TS_TI2FP2:使用通道 2 的滤波后信号
返回值:无
7. void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);
功能:配置定时器的从模式行为(如复位、门控)
参数:
TIMx
:选择定时器
可选值:
TIM3(输入捕获用)、TIM2、TIM4等
TIM_SlaveMode
:从模式类型
可选值:
TIM_SlaveMode_Reset:复位模式(输入捕获用,触发时计数器归零)
TIM_SlaveMode_Gated:门控模式(触发有效时计数器运行)
返回值:无
8. void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
功能:启动或停止定时器计数
参数:
TIMx
:选择定时器
可选值:
TIM3(输入捕获用)、TIM2、TIM4等
NewState
:定时器使能状态
可选值:
ENABLE:启动定时器(输入捕获用)
DISABLE:停止定时器
返回值:无
9. uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
功能:获取定时器通道 1 的捕获值(CCR1)
参数:
TIMx
:选择定时器
可选值:
TIM3(输入捕获用)、TIM2、TIM4等
返回值:
通道 1 的捕获寄存器值(0~65535,对应两次上升沿间的计数值)
现象:测量波形的输入口是PA6,用一根线把PA0和PA6连在一起,这样就能测量自己PWM模块产生波形的频率。
三、PWMI模式测频率占空比
1.接线图
2.代码
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
PWM_Init(); //PWM初始化
IC_Init(); //输入捕获初始化
/*显示静态字符串*/
OLED_ShowString(1, 1, "Freq:00000Hz"); //1行1列显示字符串Freq:00000Hz
OLED_ShowString(2, 1, "Duty:00%"); //2行1列显示字符串Duty:00%
/*使用PWM模块提供输入捕获的测试信号*/
PWM_SetPrescaler(720 - 1); //PWM频率Freq = 72M / (PSC + 1) / 100
PWM_SetCompare1(50); //PWM占空比Duty = CCR / 100
while (1)
{
OLED_ShowNum(1, 6, IC_GetFreq(), 5); //不断刷新显示输入捕获测得的频率
OLED_ShowNum(2, 6, IC_GetDuty(), 2); //不断刷新显示输入捕获测得的占空比
}
}
IC.c
#include "stm32f10x.h" // Device header
/**
* 函 数:输入捕获初始化
* 参 数:无
* 返 回 值:无
*/
void IC_Init(void)
{
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //开启TIM3的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA6引脚初始化为上拉输入
/*配置时钟源*/
TIM_InternalClockConfig(TIM3); //选择TIM3为内部时钟,若不调用此函数,TIM默认也为内部时钟
/*时基单元初始化*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM3的时基单元
/*PWMI模式初始化*/
TIM_ICInitTypeDef TIM_ICInitStructure; //定义结构体变量
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择配置定时器通道1
TIM_ICInitStructure.TIM_ICFilter = 0xF; //输入滤波器参数,可以过滤信号抖动
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //极性,选择为上升沿触发捕获
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //捕获预分频,选择不分频,每次信号都触发捕获
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //输入信号交叉,选择直通,不交叉
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure); //将结构体变量交给TIM_PWMIConfig,配置TIM3的输入捕获通道
//此函数同时会把另一个通道配置为相反的配置,实现PWMI模式
/*选择触发源及从模式*/
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); //触发源选择TI1FP1
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); //从模式选择复位
//即TI1产生上升沿时,会触发CNT归零
/*TIM使能*/
TIM_Cmd(TIM3, ENABLE); //使能TIM3,定时器开始运行
}
/**
* 函 数:获取输入捕获的频率
* 参 数:无
* 返 回 值:捕获得到的频率
*/
uint32_t IC_GetFreq(void)
{
return 1000000 / (TIM_GetCapture1(TIM3) + 1); //测周法得到频率fx = fc / N,这里不执行+1的操作也可
}
/**
* 函 数:获取输入捕获的占空比
* 参 数:无
* 返 回 值:捕获得到的占空比
*/
uint32_t IC_GetDuty(void)
{
return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1); //占空比Duty = CCR2 / CCR1 * 100,这里不执行+1的操作也可
}
IC.h
#ifndef __IC_H
#define __IC_H
void IC_Init(void);
uint32_t IC_GetFreq(void);
uint32_t IC_GetDuty(void);
#endif
A
现象:
硬件连接:
PWM 输出(PA8) → 输入捕获引脚(PA6)
OLED 显示屏通过 I2C 接口连接(通常为 PB6/PB7)
参数配置:
PWM 频率:72MHz / (720) / 100 = 1kHz
PWM 占空比:50 / 100 = 50%
输入捕获配置:
TIM3 通道 1(PA6)配置为上升沿捕获,用于测量频率和占空比
从模式设为复位模式,确保每次上升沿触发计数器归零
2. 实时显示效果
OLED 显示内容:
Freq:00000Hz
Duty:00%
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_50242782/article/details/148483343
STM32 标准库输入捕获可测量信号频率、脉宽、占空比,用于编码器计数、电机测速等场景。
页:
[1]