STM32单片机-输入捕获、FFT测频

这篇具有很好参考价值的文章主要介绍了STM32单片机-输入捕获、FFT测频。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本内容介绍基于STM32F103VET6的一个实际工程中添加采集A相电压信号或B相电流信号频率的功能,分别通过输入捕获与FFT实现,均测试可用。紫色文字是超链接,点击自动跳转至相关博文。持续更新,原创不易!

目录:

一、硬件连接
1、电压信号处理电路仿真
2、单片机连接
二、程序部分
1、通过STM32输入捕获
1)定时器配置
2)定时溢出与输入捕获中断
2、通过FFT实现
1)概述
2)数据采集
3)功能介绍
3、屏显驱动介绍
附录
1:测频法计算频率

一、硬件连接

1、电压信号处理电路仿真

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图1.1.1 Proteus仿真图(使用教程)

2、单片机连接

主控MCU:STM32F103ZET6(STM32的介绍),LM293输出连接在PB0上检测电压信号的频率,如图1.1.1与图1.2.1所示。

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图1.2.1 原理图截图

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图1.2.2 管脚功能截图

如图1.2.2所示,注意其中的TIM3_CH2N是PWM捕获比较输出,TIM3_CH3才是输入捕获。

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图1.2.3 内部高级控制定时器框图

二、程序部分

这里通过STM32输入捕获或FFT转换两种方式实现频率的测量,在实际工程中都已实现。STM32输入捕获信号幅度小于2V时,单片机检测不到跳变沿,需硬件对信号适当处理(如图1.1.1)。

PB0/ADC8也可用ADC读信号电压值,ADC值为0时进行记录,再次为0就相当于经过了半个周期。计算两次ADC为0的时间差,就可以计算出信号的频率,这种方法不会受限于信号幅度的限制。

1、通过STM32输入捕获

下面的程序采集PB0口(图1.2.1)的电压信号,因频率较低,且要求继电器出口时间小于35mS,采用测周法计算频率。给出主要部分定时器配置与定时器中断程序。因上升沿示波器测试并不陡峭(图1.1.1仿真图也可看出),故取一周波两次下降沿。

注意:后期的处理程序必须捕获到两个下降沿的前提下,才能作相应的处理。采集程序未完成,此时处理会出错。

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图2.1.1 示波器信号

1)定时器配置

void adc_TIM_Init(void)
{
   TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //定时器
   GPIO_InitTypeDef GPIO_InitStructure; //端口
   TIM_ICInitTypeDef TIM_ICInitStructure; //输入捕获
   
   //初始化GPIO口
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空输入模式
   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
   GPIO_Init(GPIOB,&GPIO_InitStructure);
   GPIO_SetBits(GPIOB,GPIO_Pin_0);
   
   //使能时钟
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //TIM3
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
   
   //初始化TIM3定时
   TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
   TIM_TimeBaseStructure.TIM_Prescaler = 17; //1MHz计数脉冲 1uS
   TIM_TimeBaseStructure.TIM_Period = 65535;
   TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
   TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
   TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
   
   //初始化TIM3 Channel3输入捕获IC(Input Capture)
   TIM_ICInitStructure.TIM_Channel=TIM_Channel_3;
   TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Falling; //下降沿捕获
   TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI; //管脚与寄存器一一对应
   TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1; //有下降沿就捕获,不分频
   TIM_ICInitStructure.TIM_ICFilter=0x00; //不打开输入捕获滤波器
   TIM_ICInit(TIM3,&TIM_ICInitStructure);

   TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时中断
   TIM_ITConfig(TIM3,TIM_IT_CC3,ENABLE); //允许CC3捕获中断
   TIM_Cmd(TIM3,ENABLE);
…………
}

------------------------------

2)定时溢出与输入捕获中断

void TIM3_IRQHandler(void) //TIM3
{
   static u8 CapStatus=0;
//捕获状态,CapStatus=0未捕获到第1个下降沿,CapStatus=1捕获到第1个下降沿
   static u8 TIM3_CH3_Capture=0; //总的计数次数
   u32 FrequencyTemp=0;
   
   if(TIM_GetITStatus(TIM3,TIM_IT_Update)) //TIM3定时溢出更新中断
   {
      TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
      if(CapStatus)
         TIM3_CH3_Capture++;
   }
   
   if(TIM_GetITStatus(TIM3,TIM_IT_CC3)) //RB0输入捕获中断
   {
      TIM_ClearITPendingBit(TIM3,TIM_IT_CC3); //清除中断标志位
      if(!CapStatus)
      {
         CapStatus=1;
         TIM_SetCounter(TIM3,0); //计数器清零
      }
      else if(CapStatus) //已经捕获到第1个下降沿
      {
         CapStatus=0;
         FrequencyTemp=TIM_GetCapture3(TIM3)+TIM3_CH3_Capture*65536;//计算两个下降沿总计数
         TIM3_CH3_Capture=0; //溢出次数清零
         TIM_SetCounter(TIM3,0); //计数器清零
         FrequencyValue=400000000/FrequencyTemp;//计算频率,比如5000,单位0.01Hz
      }
   }
}

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图2.1.2 继保频率设置

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图2.1.3 实际测量值

2、通过FFT实现

1)概述

下面是采集PC1口(图1.2.1)的小通道电流信号,计算频率,其固件具ST官方DSP库实现FFT,测试固件移步:FFT(具ST官方DSP库实现)。

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图2.2.1 实际测量值

------------------------------

2)数据采集

使用STM32F103自带的12位ADC进行数据采集,定时器触发ADC采集,DMA搬运,定时器时间自行设置,采样频率已知。此部分相关内容移步:ADC转换汇总(采样原理、取平均、精度等)。

------------------------------

3)功能介绍

通过FFT可以准确测量电压值、电流值;互感器二次值精确到小数点后2位无压力,电流范围大,硬件增加大小通道、程序分别采集;涌流二次谐波含量最多,故可实现二次谐波制动,谐波的相关介绍移步:电力-涌流抑制与谐波。

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

三段式保护移步:继电保护原理1.1-电流、方向保护,反时限移步:继电保护原理1.2-反时限过流保护,重合闸移步:继电保护原理4-自动重合闸之第五章、自动重合闸

-----------------

已实现FFT的控制板:

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图2.2.2 主控板正面

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图2.2.3 主控板反面

-----------------

GSM短信功能介绍移步:SIM7600CE模块(GSM/GPRS)调试。

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图2.2.4 4G短信试验板

-----------------

GPRS数据功能介绍移步:STM32-GPRS模块连接系统主站,可以采用映翰通工业数据终端做透明传输。

-----------------

以太网功能板,本方案基于W5500,详细的介绍移步:网络知识汇总(基于W5500以太网)。

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图2.2.5 以太网主控板

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图2.2.6 以太网接口板

3、屏显驱动介绍

移步:12864液晶显示原理(C代码)。

stm32输入捕获测频率,单片机、PLC、PLD,单片机,输入捕获、FFT测频

图2.3.1 英文显示

附录

1:测频法计算频率

网上找的资料,不保证正确性,没有实际测试过,仅供参考。

通过在一定时间内检测跳边沿的个数可计算出频率:频率 = 上升沿或下降沿个数/统计时间。
方法1:利用外部中断统计跳边沿个数,配置一个定时器每隔一定时间对频率进行计算。部分代码如下。
void exti_init(void)  //外部中断初始化函数
{
    GPIO_InitTypeDef GPIO_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
       
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOC,&GPIO_InitStructure);
 
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);
//选择GPIO引脚用作外部中段线路
//此处一定要记住给端口管脚加上中断外部线路
 
    EXTI_InitStructure.EXTI_Line=EXTI_Line2;
    EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;  //下降沿进中断
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure); 


    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  
    NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //打开EXTI2的全局中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //设置优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;   
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //使能
    NVIC_Init(&NVIC_InitStructure);
}
外部中断函数:
void EXTI2_IRQHandler(void)    
{
    if(EXTI_GetITStatus(EXTI_Line2)==SET)
    {
        EXTI_ClearITPendingBit(EXTI_Line0);//清中断
        if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)==Bit_RESET)    //确定沿
        {
            cnt++;
        } 
    }
}
定时器中断函数:
void TIM3_IRQHandler(void)   
{

    frequent=cnt; //定时器设置时间为1s时
    cnt=0;  //清零计数cnt
    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);    //清标志位
}
方法2:采用定时器外部计数的方法,另外一个定时器负责每隔一段时间计算频率,部分代码如下。
void time_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM2_TimeBaseInitStructure;  
    TIM_TimeBaseInitTypeDef TIM3_TimeBaseInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除TIM2中断标志位
    TIM2_TimeBaseInitStructure.TIM_Period = 0xFFFF;//设置自动重装载值
    TIM2_TimeBaseInitStructure.TIM_Prescaler = 0;//设置分频
    TIM2_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
    TIM2_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
    TIM_TimeBaseInit(TIM2,&TIM2_TimeBaseInitStructure);
  
    TIM_ETRClockMode1Config(TIM2, TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted, 0x00);  //设置为采用外部时钟计数,可设定滤波参数消除信号干扰
    TIM_Cmd(TIM2,ENABLE); 
    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
    TIM3_TimeBaseInitStructure.TIM_Period = 999;
    TIM3_TimeBaseInitStructure.TIM_Prescaler = 3599;
    TIM3_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
    TIM3_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3,&TIM3_TimeBaseInitStructure);
    TIM_Cmd(TIM3,ENABLE);
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE );
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
定时器中断函数:
void TIM3_IRQHandler(void)  
{
    static u8 i;
    static u32 frequent_sum;
    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);   //清中断

    if(i<19)
    {
        cnt += TIM_GetCounter(TIM2);  //,获取计数器的值,累加减少误差
        TIM_SetCounter(TIM2,0);    //计数器清零
        i++;
    }
    else
    {
        cnt += TIM_GetCounter(TIM2);
        TIM_SetCounter(TIM2,0);
        cnt += cnt*0.000025; //根据实际情况修改系数线性补偿
        frequent = cnt;
        i = 0;
        cnt = 0;
    }
}

首先要有一个具体目标,那些所有你认为必须前置的知识,都可以在完成目标的过程中学到。觉得不错,动动发财的小手点个赞哦!文章来源地址https://www.toymoban.com/news/detail-586193.html

到了这里,关于STM32单片机-输入捕获、FFT测频的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • stm32单片机开关输入控制蜂鸣器参考代码(附PROTEUS电路图)

    说明:这个buzzer的额定电压需要改为3V,否则不会叫,源代码几乎是完全一样的

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

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

    2024年02月16日
    浏览(47)
  • STM32单片机(一)STM32简介

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月10日
    浏览(60)
  • STM32单片机(二)STM32环境搭建

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月10日
    浏览(63)
  • STM32单片机开发-01 STM32介绍

    通过野火开发板学习单片机 从内核上分有Cortex-M0、M3、M4 和M7 F1 代表了基础型,基于Cortex-M3 内核,主频为72MHZ F4 代表了高性能,基于Cortex-M4 内核,主频180M。 数据手册:用于芯片选型和设计原理图 参考手册:用于编程时查阅 Icode总线 – 该总线讲M3内核的指令总线与闪存指令

    2024年01月21日
    浏览(63)
  • 【STM32】STM32单片机结构及部件原理

    STM32是目前比较常见并且多功能的单片机,要想学习STM32,首先要去了解它的基本构成部分以及各部分的原理。 单片机型号:正点原子STM32F103ZET6 目录 STM32内部结构总览图: 2.内部结构解析         1.内核 :STM32F103ZET6采用的是 ARM Cortex-M3 处理器,内核可以理解为单片机 处

    2023年04月08日
    浏览(51)
  • STM32单片机学习3--STM32控制键盘

    单片机型号:STM32F103C8T6 开发环境:Keil5 4种输入模式 上拉输入模式:在默认状态下(GPIO引脚无输入),读取得的GPIO引脚数据为1,高电平(与Vdd相连的为上拉电阻); 下拉输入模式:在默认状态下(GPIO引脚无输入),读取得的GPIO引脚数据为0,低电平(与Vss相连的为下拉电

    2024年02月10日
    浏览(60)
  • GD32单片机和STM32单片机的对比分析

    GD32单片机和STM32单片机都是基于Arm Cortex-M3/M4内核的32位通用微控制器,广泛应用于各种嵌入式系统和物联网领域。两者之间有很多相似之处,但也有一些不同之处,本文将从以下几个方面对比分析两者的特点、优势和开发成本。 GD32单片机采用的是二代的M3/M4内核,而STM32单片

    2024年02月16日
    浏览(63)
  • STM32单片机学习4--STM32控制八段码

    数码管:实际上是多个LED按照一定顺序排列,并加上遮罩所构成的元件。 八段码一般会引出9个引脚,其中7个引脚显示数字(或某些字母),1个显示小数点,1个作为片选端。 根据连接方式的不同,数码管分为 共阳 和 共阴 。 共阳在这端输出低电平时点亮,高电平时会熄灭

    2024年01月23日
    浏览(49)
  • 【单片机】STM32单片机的各个定时器的定时中断程序,标准库,STM32F103

    高级定时器和普通定时器的区别(https://zhuanlan.zhihu.com/p/557896041): TIM1是高级定时器,使用的时钟总线是RCC_APB2Periph_TIM1,和普通定时器不一样。 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用

    2024年02月07日
    浏览(58)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包