STM32cubemx定时外部模式测量10M以上频率

这篇具有很好参考价值的文章主要介绍了STM32cubemx定时外部模式测量10M以上频率。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

STM32cubemx定时外部模式测量10M以上频率

本文讲解利用定时器的外部时钟功能,巧妙测量高频外部信号频率。范围可以到高达30M以上。

所需工具:

  • 开发板:STM32F103RCT6
  • STM32CubeMX
  • IDE: Keil-MDK

原理讲解

定时器的时钟

我们在正常使用TIM定时器的时候,在cubemx里面的时钟树里,随便点击配置,就可以选择好定时器的时钟。比如下面这个情况:

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

通过时钟树,给挂在APB2时钟上的定时器,提供了72M的时钟。内部是如何产生时钟的呢,我们这里不用关心,不在本文讨论范围,只要知道有一个72M的时钟输入给了定时器TIM作为时钟源。

形象一点说,是一个72M、占空比50%、高电平3.3V、低电平0V的PWM输入给了定时器。每当定时器检测到PWM的上升沿时,就会在CNT计数值寄存器中加一。

下面我们举例说明,有一个1k的内部时钟,输入给定时器。如下图

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

当TIM检测到时钟的上升沿的时候,CNT寄存器就会加一。我们知道,当CNT计算到ARR寄存器里面存放的自动重装载值的时候,就会归零。如果ARR为1000。那么CNT的计数值成如下关系:

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

因为内部时钟是1khz,CNT寄存器每1ms增加1,当计数到1000时,满足ARR的值,就会重新开始装载。

很好,现在开动我们的小脑筋。假如我们并不知道内部时钟是多少。我们可以如何通过CNT得知它的频率呢?

读者可以在这打住,想一下这个问题应该如何解决。后面会揭晓答案。

我们可以先将ARR值,设置的足够大,比如65536吧,避免计数值达到ARR后,重新装载从0计数。我们可以每1秒去读取CNT的值,读取出当前的值后,把CNT寄存器清零,重新开始计数。可以想象,每隔1秒读出来的CNT就是1秒内,定时器收到的内部时钟上升沿,上升沿的个数不就是时钟频率嘛!(呕吼~~狂喜)当前例子下,可以想象每次读取出来都是1000。

有了这个思路,我们不就可以测量定时器时钟源的频率吗?要是这个时钟源可以选择外部信号就好了,通过IO口引脚输入给定时器作为时钟源。欸!巧了,定时器还真有外部时钟引脚!

定时器的外部时钟

下图是从参考手册中,截取的定时器框图:

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

TIMX_EXR就是外部时钟引脚,如果你看到这个框图犯嘀咕,好麻烦啊,其他都是什么乱七八糟的方框、旁边的ITR0、TRC是干什么的?不用担心,我们来对图进行一下化简:

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

定时器引出一个引脚,这个引脚对应着一个IO口,我们把外部的PWM信号,输入给这个引脚:TIMx_EXR。pwm信号输入到上升沿检测中后,再连接CNT寄存器,对每个上升沿进行计数加一。

现在我们把ARR设置为65536,ETR引脚外接60k的PWM信号。每1秒去读取CNT寄存器的计数数值,读取完成后清空。可以想象,每次读取出来CNT都是60000,对应着这一秒内,CNT检测到60k个上升沿,PWM频率为60k。

可是!如果频率超过65536hz,CNT计数值打到ARR后自动清零,我们不就读不到数据了嘛?欲知后事如何,且听下节分说。

突破频率

CNT达到ARR后,确实会更新,从零计数。不过,会产生定时器中断嘛。我们可以定义一个变量COUNT,当中断产生时,变量就加一,这个变量便表明,记录了多少个轮回,有多少个ARR。

假设:ARR为50k,外部输入PWM频率为10.001M。我们每1秒读取时,会读取到COUNT为2000,CNT寄存器值为1000。那么可以推算出来PWM频率为:
A R R ∗ C O U N T + C N T = 50000 ∗ 2000 + 1000 = 10.001 M ARR*COUNT+CNT=50000*2000+1000=10.001M ARRCOUNT+CNT=500002000+1000=10.001M
需要注意的是,每次读取后,不光要清空CNT寄存器,还需要清空COUNT变量。

工程建立

时钟树

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

定时器配置

本例程使用到两个定时器。首先是定时器2,时钟源选择外部时钟。

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

可以看到PA0便是定时器2对应的外部时钟引脚,我们后面只需要把外部PWM信号,连接到PA0,就可以测量频率了。

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

开启定时器2的中断,用来在计数值超过65536时,产生更新中断,在中断中对变量进行加一,表明此时计数了一个周期。

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

定时器3用来产生1s的中断,每隔一秒在中断中读取当前频率。

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

串口配置

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

代码生成

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

代码编写

串口重定向

在usart.c靠末尾的地方,编写下面函数

#include <stdio.h>

int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}

int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

在main.c中,包含头文件:

#include "stdio.h"

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

脉冲计数

首先定义用来计数的变量,变量含义在注释中说明。

uint32_t FQ; // 用来存放频率

uint16_t CNT_2 = 0; // 超出65536位后 用这个记录超过的次数
uint16_t CNT_1 = 0; // 0-65536内用这个记录

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

接着开启定时器2和3。

HAL_TIM_Base_Start_IT(&htim3); // 启动定时器3进行1S定时

HAL_TIM_Base_Start_IT(&htim2); // 启动定时器2进行外部脉冲计数

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

因为定时器2、3开启有先后顺序,所以第一次测量到的频率不能使用

接下来便是本文的重要部分,读取计数值:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim == (&htim3)) // 定时器中断1S触发一次
    {
        CNT_1 = __HAL_TIM_GET_COUNTER(&htim2); // 读取CNT计数值
        //		CNT_1 = TIM2->CNT;// 读取CNT寄存器这样也可以
        FQ = CNT_1 + CNT_2 * (__HAL_TIM_GET_AUTORELOAD(&htim2) + 1); // 获取频率值
        __HAL_TIM_SET_COUNTER(&htim2, 0);// 设置CNT为0
        printf("cnt:%u\n", FQ); // 打印频率值   1S打印一次
        CNT_1 = 0;  
        CNT_2 = 0; 
    }
    if (htim == (&htim2)) // 计数值计满,产生更新中断
    {
        CNT_2++; // 记满后,+1,标志多了一个满量程数
    }
}

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

此处的频率计算公式如下:
F Q = C N T 1 + C N T 2 ∗ ( 65535 + 1 ) FQ=CNT_1+CNT_2*(65535+1) FQ=CNT1+CNT2(65535+1)

__HAL_TIM_GET_AUTORELOAD(&htim2)读取的是TIM2的ARR寄存器值,因为计数都是从0开始,所以要加一。比如ARR为999,从0计算到999,实际计算了999+1次。

硬件连接

引脚 连接对象 释义
PA0 信号发生器的正极 TIM2的外部时钟引脚
GND 信号发生器的负极 供地

因为我的开发板板载ch340,这里并不需要外接ch340串口助手。

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

运行结果

信号发生器产生12M的方波信号,0-3.3V。串口信息如下:

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

可以看到,cnt成功测量出来了外接信号的频率,误差0.004%。

实际上,因为定时器内部的边沿检测部分存在,定时不光可以测量PWM信号的频率,还可以直接测量正弦、三角波等频率,幅度也不一定要0-3.3V!

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

比如我测量一个1M,1V-2V的三角波:

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件

正如前面所提到的,刚开始运行时,前两个数据是不能用的,需要扔掉,后续测量出来信号频率是999957hz,误差0.0043%。

如下是我测试出来的,能测量频率的不同波形、不同幅度的信号。

  • 方波(8M以内的极限值,再往上,高电平尽量高,低电平尽量低)
    • 高电平1.6——3V(3.3是上限,建议用3V以内)
    • 低电平-200mv——1.3v。
  • 正弦(1M以内)
    • 高电平1.7V——3V
    • 低电平-200mv——1.3v
  • 三角(1k以内)
    • 高电平1.7V——3V
    • 低电平-200mv——1.3v

下表是我用H750测试出来的表单,H7的测试精度略高于F1

频率 误差
1k 0
10k 0
1M 22
10M 212
15M 317
我的信号发生器发不出更高的 ————

练习

  1. 复现本文例程,测量不同幅值频率下,方波、正弦等波形的信号频率。
  2. 该方法的测量范围高,但是测量时间长,有没有办法略微牺牲精度,换取更快的频率测量?
  3. 外部计数本质是测量外部的上升沿个数,CNT达到ARR值时,会产生更新中断,这个功能能否在其他场景下起作用呢?ARR是可以动态更改的。

后记

本文章收录于:

唐承乾的电赛小站

本文为系列文章中的冰山一角,欢迎进入小站查看。

配套程序:

STM32cubemx定时外部模式测量10M以上频率例程 gitee

STM32cubemx定时外部模式测量10M以上频率,冬令营,电赛模块,stm32,单片机,嵌入式硬件文章来源地址https://www.toymoban.com/news/detail-516189.html

到了这里,关于STM32cubemx定时外部模式测量10M以上频率的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32 CubeMX 定时器(普通模式和PWM模式)

    定时器打开与关闭 开启PWM通道 设置PWM,占空比 方式1 方式2 值越大灯越亮

    2024年02月15日
    浏览(38)
  • STM32 学习笔记(六)定时器中断:内部时钟模式,外部时钟模式

    定时器是功能最强大,内容最复杂的32结构。 之前51用过的功能,定时产生中断。 输出比较,常用于产生 PWM 波形,驱动电机等。 输入捕获,测量方波频率。 编码器,读取正交编码器的波形。 最大定时时间:72M/65536/65536=中断频率,中断频率取倒数是最大定时时间。 定时器可

    2024年02月08日
    浏览(58)
  • STM32CUBEMX 待机模式最简单的RTC定时唤醒(低功耗电池产品必备)

    看到很多技术帖子讲述RTC定时唤醒功能的时候,老是需要去读取当前时间,再设定下一个闹钟唤醒时间,无形中多了很多变量和操作。所以我决定分享一种简单的RTC定时唤醒方法,适合于不需要实现具体时间获取的场合,仅实现RTC定时唤醒的功能。 电池类便携式产品一般都要

    2024年02月03日
    浏览(46)
  • 初出茅庐的小李博客之STM32CubeMx配置定时器的编码器模式

    上次文章写了编码器是如何工作的,今天就来用STM32F103C8T6的TIM3的通道1跟通道2编写一个编码器识别程序。 话不多说,上教程! 选择外部高速时钟源HSE 选择中断模式触发下降沿有效 默认是上拉输入 添加用户标签为SWITCH 使能NVIC配置 选择编码器模式 分频值设置为2-1 计数值设

    2024年02月12日
    浏览(43)
  • 【STM32学习】——定时器输入捕获(IC)&PWMI模式&频率测量方法&主从触发模式&IC模式测频&/PWMI模式测频率及占空比

    声明:学习笔记根据b站江科大自化协stm32入门教程编辑,仅供学习交流使用! 注意:读完大约需要15分钟,但会收获满满!! 输入捕获部分一共两个实操案例程序: 输入捕获模式测频率、PWMI模式测频率和占空比。 测频法利用之前的外设就可实现,如对射式红外传

    2024年02月16日
    浏览(47)
  • STM32 HAL库 STM32CubeMx -- 外部中断

    中断,是指处理机处理程序运行中出现的紧急事件的整个过程。程序运行过程中,系统外部、系统内部或者现行程序本身若出现紧急事件,处理机立即中止现行程序的运行,自动转入相应的处理程序(中断服务程序),待处理完后,再返回原来的程序运行,这整个过程称为程序

    2024年02月08日
    浏览(47)
  • 最详细STM32,cubeMX外部中断

    这篇文章将详细介绍 cubeMX外部中断的配置,实现过程。 实验开发板:STM32F103C8T6。 所需软件:keil5 , cubeMX 。 实验目的:外部中断的意义,cubeMX配置和实现 等 。 对于外部中断的基础知识,可以参考我之前的文章:STM32 EXTI外部中断 选择芯片。 配置仿真。(如果不配置,程序

    2024年02月19日
    浏览(41)
  • STM32CubeMX学习三 之外部中断

    记录一下STM32CubeMX的学习笔记,同时分享给初学的小白,希望一起进步。 如何使用STM32CubeMX以及工程创建在之前的博客有提到,这里就直接从外部中断讲起。 编译环境:KEIL 代码生成:STM32CubeMX 库:HAL MCU:STM32F072 假设你的cubeMX工程已经建好,这里我们配置KEY1、KEY2、KEY3三个按

    2023年04月08日
    浏览(41)
  • STM32开发(9)----CubeMX配置外部中断

    本章介绍使用STM32CubeMX对引脚的外部中断进行配置,介绍了中断架构体系,外部中断/事件控制器(EXTI),嵌套向量中断控制器(NIVC),并通过实验展示配置后的效果。 中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理

    2024年02月15日
    浏览(48)
  • STM32CubeMX——定时器配置

    本文将会以STM32F103C8T6为例配置定时器2定时5 ms SMT32F1系列共有8个定时器: 基本定时器(TIM6、TIM7) 通用定时器(TIM2、TIM3、TIM4、TIM5) 高级定时器(TIM1、TIM8) 16位向上、向下、向上/下自动装载计数器 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为 1~6553

    2023年04月10日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包