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

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

### 设置 STM32 PWM 输出频率 对于 STM32 来说,PWM 频率定时器的时钟频率、预分频系数 (PSC) 和自动重装载寄存器 (ARR) 的值共同决定。具体计算公式如下: \[ \text{PWM Frequency} = \frac{\text{Timer Clock}}{(PSC + 1) \times (ARR + 1)} \] 其中 Timer Clock 是定时器输入时钟频率;PSC 是预分频系数;ARR 是自动重装载寄存器中的数值。 为了设置 STM32PWM 输出频率,在初始化配置阶段需指定这些参数。这里给出一段基于 HAL 库实现的例子来展示如何设定特定频率下的 PWM 输出: ```c // 假设目标频率为 50 Hz, TIM9 输入时钟假设为 84 MHz. void MX_TIM9_Init(void) { __HAL_RCC_TIM9_CLK_ENABLE(); // 启用 TIM9 时钟 TIM_HandleTypeDef htim9; htim9.Instance = TIM9; // 计算 PSC 和 ARR 的值以达到期望的频率 uint32_t timer_clock = 84e6; // 定时器时钟频率 float target_frequency = 50.0f; // 目标 PWM 频率 uint32_tpsc_value = ((timer_clock / target_frequency) - 1) / 65536; uint32_t arr_value = (((timer_clock / (pscaler_value + 1)) / target_frequency) - 1); TIM_OC_InitTypeDef sConfigOC; htim9.Init.Prescaler = psc_value; htim9.Init.CounterMode = TIM_COUNTERMODE_UP; htim9.Init.Period = arr_value; htim9.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_PWM_Init(&htim9) != HAL_OK){ Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; // 初始占空比可以自定义 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim9, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){ Error_Handler(); } } ``` 上述代码展示了通过修改 `Prescaler` 和 `Period` 参数来控制 PWM 形周期的方法[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值