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

发布者:龙腾少年最新更新时间:2022-02-14 来源: eefocus关键字:STM32  单片机  输入捕获 手机看文章 扫描二维码
随时随地手机看文章

一、硬件连接

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

图1.1.1

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

2、单片机连接

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

图1.2.1

图1.2.2

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

图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仿真图也可看出),故取一周波两次下降沿。

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

图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

      }

   }

}

图2.1.2

图2.1.3

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

2、通过FFT实现

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

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

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

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

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

图2.2.1

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

3、屏显驱动介绍

移步:12864液晶显示原理(C程序)。

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

附录1:测频法计算频率

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

通过在一定时间内检测跳边沿的个数可计算出频率 频率=上升沿或下降沿个数/统计时间。

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

方法1:利用外部中断统计跳边沿个数,配置一个定时器每隔一定时间对频率进行计算。部分代码如下。

void exti_init()  //外部中断初始化函数

{

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()    

{

if(EXTI_GetITStatus(EXTI_Line2)==SET)

{

    EXTI_ClearITPendingBit(EXTI_Line0);//清中断

if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)==Bit_RESET)    //确定沿

{

cnt++;

}

}

定时器中断函数

void TIM3_IRQHandler()   

{

frequent=cnt; //定时器设置时间为1s时

cnt=0;  //清零计数cnt

TIM_ClearITPendingBit(TIM3,TIM_IT_Update);    //清标志位

}

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

方法2:采用定时器外部计数的方法,另外一个定时器负责每隔一段时间计算频率,部分代码如下。

void time_init()

{

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()  

{

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;

}

}

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

关键字:STM32  单片机  输入捕获 引用地址:STM32单片机-输入捕获、FFT测频

上一篇:STM32单片机-资料查找
下一篇:STM32单片机-PWM波形输出

推荐阅读最新更新时间:2024-11-11 11:53

51单片机计数器计数数码管显示
#include reg52.h #define uint unsigned int #define uchar unsigned char uchar code smg_tab ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//{0x28,0x7e,0xa2,0x62,0x74,0x61,0x21,0x7a,0x20,0x60,0x30,0x25,0xa9,0x26,0xa1,0Xb1}; uchar code bit_tab ={0x7f,0xbf}; uchar Counts=0; uchar Display_Buffer ={0,0}; void _del
[单片机]
AVR单片机改造遥控车
利用玩具遥控车的高频发射电路和高频接收电路,结合单片机 进行数据传输,模拟两通道比例控制遥控器。 发射端用ATTINY24从TX的8号脚控制玩具遥控器的高频发射部分 接收端用ATTINY24从RX2的3号脚接收信号。然后PWM控制 遥控车的两个电机,一个由电位器反馈。另一个由测速 盘反馈。 数据结构 0 高电平100us,低电平300us 1 高电平200us,低电平200us 数据帧结构 16位为一个包起始2位(10),地址2位,数据10位,结束2位(01) 每5个包为一个循环 1号包 全0包,不含起始结束,用于接收端复位。 2,3号包 地址01号数据。 4,5号包 地址02号数据。 纠错采用重复校验,当收到两组数据
[单片机]
AVR<font color='red'>单片机</font>改造遥控车
51单片机串口发送和中断接收程序
#include reg52.h void leddisplay(); // 数码管显示 void delayms(unsigned int k); // 延时 n ms void USART_SEND(unsigned char dat); // 串口发送子程序 unsigned char data ledxs ={16,16,16,16,16,0,0,18}; // 数码管显示缓冲区 unsigned char code tab ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0,0x
[单片机]
单片机正弦波发生器设计
系统框图 该系统采用单片机作为数据处理及控制核心,由单片机完成人机界面、系统控制、信号的采集分析以及信号的处理和变换,采用按键输入,利用虚拟示波器显示波形的方案。将设计任务分解为按键电路、输出转换电路等模块。图3-2为系统的总体框图。 系统仿真 单击仿真界面左下方的开始按扭,仿真就开始了。具体仿真过程如下: (1)f=50HZ正弦波的调试结果 单片机源程序如下: #include reg52.h #define uchar unsigned char #define uint unsigned int #define DAdata P0 //DA数据端口 sbit DA_S1= P2^0; // 控制DAC0
[单片机]
<font color='red'>单片机</font>正弦波发生器设计
STM32 USB 之从0开始移植笔记
-----------------------------------动机----------------------------------- 写在前面的话:最近逛淘宝无意间发现RC522居然只要10元左右就可以包邮买到,真是太便宜了,就忍不住买了个回来玩玩。到货移植到我的板子上OK 后突然发现我的USB口紧张了,一个用来给板子供电一个插jlink 一个插入usb转串口给RC522下命令。就想着将板子供电和RC522传输用一个USB接口来实现。这就是这次折腾USB的来由~-~ ----------------------------------开始折腾USB----------------------------- 首
[单片机]
<font color='red'>STM32</font> USB 之从0开始移植笔记
单片机-stm32-使用cdc类实现vcp(虚拟串口)
本文所述内容基于STM32 HAL库完成 安装stm32CubeMx(ver4.26.0) 新建工程,选择stm32f412zg tx 配置RCC- HSE- crystal/Ceramic Resonnator 配置USB_OTG_FS- device only(disable Activate_VBUS) 配置MiddleWares- USB_DEVICE- communication device class(virtual Port com) 配置clock,input frequency设置为8Mhz 其他参数全部默认,生成代码 其中USBD_CDC_RegisterInterfac
[单片机]
<font color='red'>单片机</font>-stm32-使用cdc类实现vcp(虚拟串口)
基于单片机C805lF040的水温遥控遥测系统的设计
引言 温度遥控遥测是远程实现对温度的测量与控制,特别适合那些环境恶劣,测量人员不容易接近的场合,近年来在工农业生产中应用广泛。根据遥控遥测系统的特点,提出了对水温遥控遥测的设计方案。 温度遥控遥测系统主要由微处理器系统、测温模块、加热模块、通信模块、液位模块以及上位机软件等组成。系统构成如图1所示。 测温模块测量液体温度后,把温度数值发送给微处理器,当温度变化达到一定值后,加热模块开始加热,首先可以在设定的时间内,加热到设定的温度并稳定在该温度一段时间。系统通过两个通信模块实现遥测遥控,上位机设好温度参数后,通过通信模块传给远处的微处理器,微处理器按照上位机设定好的温度控制加热模块进行加
[单片机]
基于<font color='red'>单片机</font>C805lF040的水温遥控遥测系统的设计
stm32快速入门
stm32简单描述:stm32基于ARM cortex-m3(m4)架构。官方已经提供完备的片内私有外设及片内外设的函数库。非常有利于利用C语言开发。 准备工作: 1、仔细阅读以下资料的相关章节: 1)cortex-m3权威指南 这是本cortex-m3架构的经典书,通俗易懂。开始阅读可重点关注存储结构等。 2)零死角玩转STM32 很好的入门教程,注意里面相关内容: A、LibrariesCMSISCoreCM3startuparm下有些启动文件,对应不同芯片,注意选择。 3)cortex-m3汇编启动代码分析 4) stm32固件库详解 PPP代表任一外设。 头文年的
[单片机]

推荐帖子

射频放大器基础
射频放大器,根本上是我们射频系统中的正反馈系统,一般位于发射链路上。由于考虑无线传输的链路衰减,发射端需要辐射足够大的功率才能获得比较远的通信距离。因此,射频放大器主要负责将功率放大到足够大后馈送到天线上辐射出去,是通信系统中的核心器件。射频放大器,根本上是我们射频系统中的正反馈系统,一般位于发射链路上。由于考虑无线传输的链路衰减,发射端需要辐射足够大的功率才能获得比较远的通信距离。因此,射频放大器主要负责将功率放大到足够大后馈送到天线上辐射出去,是通信系统中的核心器件。
他们逼我做卧底 RF/无线
这种元件是什么名字
万能的坛友们,各位在设计PCB时,有没有遇到过需要板子上焊接,可以插香蕉插头的接线柱需求,那种接线柱叫什么名字,最小尺寸是什么?或者说是测试口,方便从信号源引线进去插接,平时不用,就标定时用的。这种元件是什么名字香蕉插座的插孔直径通常设计为4mm,以适配标准4mm香蕉插头 朋友,我想找在PCB焊接的标定口,方便插信号源的线,这个是面板安装的标定口 有没有在PCB上焊接的,方便信号源引线进去,但是不想用连接器,本身空间就不够。PCB上画一个接线柱的封装,
呜呼哀哉 模拟电子
又有新板到啦~~杰发AC7801X电机demo板来了,测评活动即将上线...
杰发AC7801X板子到啦~特别的漂亮~来给大家晒晒图~~活动会赶在国庆前发布,欢迎大家来参加呀呀呀~~更多的资料请点击这里:杰发简介合肥杰发科技有限公司(AutoChipsInc.)成立于2013年,是北京四维图新科技股份有限公司(股票代码:002405.SZ)全资子公司,下设上海途擎微电子有限公司。杰发科技专注于汽车电子芯片及相关系统的研发与设计,在合肥、深圳、上海、武汉设立有研发及市场销售中心。又有新板到啦~~杰发
okhxyyo 国产芯片交流
嵌入式线控驾驶系统开发过程中设计和测试考虑
由于有了基于模型的设计,使得开发大量的汽车嵌入式系统时,可以由模型自动生成最终编译的软件。不过,这项工作需要一个软件工程框架的支持。本文使用线控驾驶系统(steer-by-wiresystem)作为实例,给出了设计汽车嵌入式系统的过程、方法和测试工具的一个框架。近来,有报道称包括Denso、Motorola和Toyota在内的不同行业的多家公司都在产品代码方面取得了成功。这项技术正日益成为软件下一波演进发展中的一个重要组成部分。虽然总体而言,它对软件工程化过程的影响已为业界所了解,但却并没
6294316 汽车电子
解决对讲机盲区通信的方法
在超短波常规无线通信中,经常面临手持机通信距离短的问题。因为手持机受体积、重量和耗电等多方面制约,不可能大幅提高功率和使用高增益天线来扩大通信范围。通常解决这个问题是利用转发台来扩大手持机的通信距离。由于超短波是属于视距传播,只要将转发台置于高处,  在超短波常规无线通信中,经常面临手持机通信距离短的问题。因为手持机受体积、重量和耗电等多方面制约,不可能大幅提高功率和使用高增益天线来扩大通信范围。通常解决这个问题是利用转发台来扩大手持机的通信距离。由于超短波是属于视距传播,只要将转发
Jacktang RF/无线
提供FPGA PCIe PCI等解决方案
提供FPGAPCIePCI等解决方案,包括硬件软件windows驱动等,同时承接各种FPGA板卡开发QQ13141504提供FPGAPCIePCI等解决方案
tomdong074 FPGA/CPLD
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved