STM32输入捕获详解:PWM频率测量最全面笔记

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频率

输入捕获频率测量(我测我自己)

作者:菠萝单片机

物联沃分享整理
物联沃-IOTWORD物联网 » STM32输入捕获详解:PWM频率测量最全面笔记

发表回复