2.2输入捕获
输入捕获简介
一个通道内 IC 跟OC 不能同时运行
频率测量
测频法: 可以自定一个闸门时间T 通常是1秒 ,对上升沿进行计次,每一个上升沿其实就相当于一个周期,那么有多少个计次就是频率
测周法: 两个上升沿内,用标准频率进行计次,得到计次N 核心思路就是周期的倒数就是频率 公式推导
T周期 = N/标准频率 而频率 = 1/T 带入就得到了 频率 = 1/(N/标注频率)=标准频率/N 记1个数的时间 其实就是 1/标准频率 那么记N个数字就是N/标准频率
测量法跟测周法都是非常重要的方法,那么在实际使用过程中,应该如何选择呢?
首先,测频法适合测量高频信号,测周法适合测量低频信号,拿测频法来说,如果在闸门时间内,没有出现高电平信号或是只出现几个上升沿,但不能就此认定频率就是0,在计次N 很少的时候,误差就会很大
而测周法需要低频信号,低频信号周期比较长,计次就会比较多,有助于减小误差,否则的话,比如标准频率为1MHz 待测信号频率太高,频率为500KHz在一个周期内就只能计一两个数,甚至一个都计不了,那我们也能认为信号无穷大吧
然后是测频法测量速度比较慢,因为是在闸门时间内进行计数,所以自带滤波,如果期间频率有变化,那么得到的其实是一段时间内的平均数值,相较而言,测周法只对一个周期进行计次,结果更新比较快,但是容易受到噪声的干扰
这里引入一个内容 如果高频信号用测频法 低频信号用测周法,那么高低的定义是什么,又该如何区分呢?
这就要靠中界频率的计算公式了
当待测信号大于中界频率的时候,选用测频法更合适,当待测信号小于中界频率的时候,用测周法更合适
输入捕获通道(详细)
引脚进来,这里有一个异或门引脚,他的执行逻辑是当三个引脚有一个引脚产生反转的时候,输出引脚就产生一次电平翻转
数字滤波器:以采样频率对信号进行连续采样,当采样个数连续都为高电平,数据才会有效
CNT 自动清0 硬件电路实现
这里可以看到TI1FP1 跟TI1F_ED都可以通向从模式控制器,从模式里面,就有可以完成CNT 自动清0 的电路
接下来我们就来看一下主从触发模式
主从触发模式
主从触发模式就是 主模式 触发源选择 从模式 三个结构的简称
主模式: 它可以将定时器内部的信号,映射到TRGO引脚,用于触发别的外设
从模式:接收其他外设,或是自身外设的信号,用于控制自身定时器的运行,也就是被别的信号控制
触发源选择:可以看作从模式的一部分,选择指定的信号,得到TRGI,从而触发从模式,。从模式可以选择一项去进行执行,例如这里想要对CNT 进行清零,就可以用到Reset(复位)完成操作,实现硬件全自动
输入捕获基本结构
PWMI 基本结构
这里上面的部分TI1FP1 配置为上升沿触发,触发捕获于清零CNT 正常地捕获周期,这时候,再来一路TI2FP2,配置为下降沿触发,通过交叉通道,去触发通道2的捕获单元,这时候会发生什么呢
看上图不难发现 最开始的时候 CCR1=CNT CNT清零 CNT 开始计数 当遇到下降沿触发CCR2 的捕获,所以这时候CCR2 的数值就是当前CNT 的数值,也就是高电平期间的计数数值,CCR2 捕获 ,并不会触发CNT清零,所以CNT 继续++直到下一次上升沿,继续下一轮 这时候 CCR1就是周期的计数,CCR2就是高电平的输出,有了这两个数值,就可以得出占空比了。
驱动函数配置过程
初始化函数
#include "stm32f10x.h" // Device header
// 输入捕获初始化函数
void IC_Init(void)
{
// 1. 初始化时钟并配置 GPIO 为上拉或浮空输入模式
// 开启 TIM3 和 GPIOA 的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 配置 GPIOA 的 Pin6 为上拉输入模式
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);
// 2. 配置时钟源为内部时钟
TIM_InternalClockConfig(TIM3);
// 3. 配置时基单元
// 设置 TIM3 的时基参数,计数器模式为向上计数,周期为 65535,预分频值为 71
TIM_TimeBaseInitTypeDef TIM_InitBaseStructure;
TIM_InitBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分频为不分频
TIM_InitBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_InitBaseStructure.TIM_Period = 65536 - 1; // 自动重装载值为 65535
TIM_InitBaseStructure.TIM_Prescaler = 72 - 1; // 预分频值为 71
TIM_InitBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_InitBaseStructure);
// 4. 初始化输入捕获单元
// 设置 TIM3 的通道 1 的输入捕获参数,滤波器值为 0xF,上升沿触发,直接输入捕获,不分频
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_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);
// 5. 配置触发输入源
// 设置 TIM3 的触发输入源为通道 1 的输入信号
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
// 6. 配置从模式为复位模式
// 设置 TIM3 的从模式为复位模式,当触发信号到来时,计数器复位
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
// 7. 使能 TIM3
TIM_Cmd(TIM3, ENABLE);
}
// 获取输入信号频率的函数
uint32_t IC_GetFreq(void)
{
// 根据捕获值计算输入信号频率,返回值为 1000000 / (捕获值 + 1)
return 1000000 / (TIM_GetCapture1(TIM3)+1);
}
主函数部分
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "PWM.h"
#include "Delay.h"
#include "IC.h"
// 主函数入口
int main(void){
OLED_Init();
PWM_Init();
IC_Init();
OLED_ShowString(1,1,"FReq:00000Hz");
// 设置 PWM 的预分频值,用于调整 PWM 频率
PWM_SetPrescaler(720 - 1); //Freq = 72MHz /(PSC+1)/100
// 设置 PWM 通道 1 的占空比
PWM_SetCompare1(50); //Duty = CCR /100
while(1){
// 在 OLED 显示屏第一行第六列显示通过输入捕获获取的频率值,显示宽度为 5 位数字
OLED_ShowNum(1,6,IC_GetFreq(),5);
}
}
实现效果 输入捕获测量PWM频率
输入捕获频率测量(我测我自己)