关于STM32精准采频率的实现

  • Post author:
  • Post category:其他


博主这次做训练题遇到了采频率的问题,做单项并网问题,需要实时了解频率的相关信息。

尝试直接用他们提供的

输入捕获

,发现并不是很好用,琢磨了半天,实现了自己的部分采用。

这里就不一步一步的分析了,估计看的情况也比较少。

直接上手,不过,博主是从正点原子那里直接得到的库里面查找的信息。

一般定时器的配置

#pwm_in_mode.h文件

这里介绍了两个配置函数

#ifndef __TIMER_H
#define __TIMER_H
#include "stm32f4xx.h"

void TIM2_CH2_Cap_Init(void);
void TIM2_IRQHandler(void);

#endif

看自己的爱好,我这里把一般的**(u16 arr,u16 psc)**省略到里面去了,大家可以直接改掉也行,加在函数头里面传参。

#pwm_in_mode.c文件

有几种模式,大家可以直接抄过去

##时间设定初始化

TIM_ICInitTypeDef  TIM_ICInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);	

TIM_TimeBaseStructure.TIM_Prescaler=84-1;                       
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; 
TIM_TimeBaseStructure.TIM_Period=0xffffffff;//对应下面                         
TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

##引脚初始化

GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //GPIOA1		
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure); 	
GPIO_PinAFConfig(GPIOA,GPIO_PinSource1,GPIO_AF_TIM2);

##中断优先级

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0x03;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	
NVIC_Init(&NVIC_InitStructure);	

##使能和其他配置

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; 
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;	
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;	 
TIM_ICInit(TIM2,&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 0x0;//	

TIM_PWMIConfig(TIM2,&TIM_ICInitStructure);

/* Select the TIM4 Input Trigger: TI2FP2 */
TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);

 /* Select the slave Mode: Reset Mode */
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);

/* TIM enable counter */
TIM_Cmd(TIM2,ENABLE);
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);

#中断函数处理

这里就可以计算出周期和时间了,也可以直接复制过去。

void TIM2_IRQHandler(void)
{ 
	TIM_ClearITPendingBit(TIM2, TIM_IT_CC2); //Çå±ê־λ 
	
	IC2Value=TIM_GetCapture2(TIM2);
	IC1Value=TIM_GetCapture1(TIM2);
	
	if(IC2Value!=0){
		DutyCycle=(float)IC1Value*100/IC2Value;
		Frequency =(float)1000000/IC2Value;//对应上面的1Mhz
	}
	else{
		DutyCycle=0;
		Frequency=0;
	}
}

#显示和现象对比

OLED_Refresh_Gram();
if(print_mode==0)
{		
   OLED_ShowString(0,0,"MeasureResult:",16);
   OLED_ShowString(0,16,"IC2Value:",16);
   OLED_ShowNum(72,16,IC2Value,7,16);
   OLED_ShowString(0,32,"DutyCycle:",16);
   OLED_ShowFloatNum(80,32,DutyCycle,7,16); 
   OLED_ShowString(0,48,"Frequency:",16);
   OLED_ShowFloatNum(80,48,Frequency,7,16);
}

aaa

#精度与误差

这里定时器读到的IC1Value和IC2Value精度的限制,博主试过,最小可识别刻度在0.002hz,暂时还是够用的。

z'z'z

如果做的过程中没能实现,可以直接下载参考我的.c文件,这里是

文件链接



注意,博主的单片机型号是STM32F4系列的,时钟配置的TIM2是168M,如果不懂时钟的计算可以参考我前面的文章有讲解。

很多正在学习的小伙伴经常私信博主,想要全部的工程文件,这里是整个工程的

文件链接

,然后采频率只是一部分,有涉及,主题功能还是其他的,不是单一采频率。



版权声明:本文为klaus_x原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。