当前位置:   article > 正文

STM32定时器使用外部输入模式测量频率_stm32外部时钟+定时器测频率

stm32外部时钟+定时器测频率

STM32定时器使用外部输入模式测量频率

最近项目忙,发现好久没有更新了,有些预期要去写的博客也被搁置了。今天睡前写个简单的做个随笔。

  1. 硬件原理
    关于使用定时器测量电信号频率的方法有很多,这里主要介绍:
    (1)普通的外部输入(外部时钟源模式1);
    (2)ETR外部触发输入(外部时钟源模式2)。
    在这里插入图片描述
    这里的这两种都是将外部信号作为定时器的时钟源,因此使用这种方法去进行频率测量之后就会限定了该定时器的用法,所以在使用该方法之前务必排除该定时器没有做其他的用途。
    在测量的精确度而言,ETR外部触发输入的精度要比普通的外部输入高。但是由于项目中硬件工程师设计使用了只能作为定时器外设通道的PB6(Timer-CH1)。所以只能使用普通外部输入计数的方式去计算频率。

  2. 软件实现
    在程序中,开启了定时器3的计数模式,定时10ms进一次中断。定时器4设置为外部时钟源模式1。代码如下:

timer.c文件
(1)定时器3初始化函数

//=========================================================================
//			通用定时器3中断初始化
//			arr:自动重装值。
//			psc:时钟预分频数
//			定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//			Ft=定时器工作频率,单位:Mhz
//			这里使用的是定时器3!
//=========================================================================
void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  			//使能TIM3时钟

    TIM_TimeBaseInitStructure.TIM_Period = arr; 					//自动重装载值
    TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  					//定时器分频  只要此值不为1,则APBx=PLCKx*2再除以psc
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; 	//向上计数模式
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;

    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);				//初始化TIM3
    TIM_ClearFlag(TIM3, TIM_FLAG_Update);
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); 						//允许定时器3更新中断

    TIM_Cmd(TIM3,ENABLE); 											//使能定时器3

    NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; 					//定时器3中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; 		//抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=1; 				//子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

(2)定时器4初始化函数

//=========================================================================
//		定时器4	
//	    通道1
//		外部信号引脚脉冲检测		
//=========================================================================
void TIM4_Cap_Init(void) 
{
	GPIO_InitTypeDef GPIO_InitStructure;  
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  
  
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);    //使能TIM4时钟  
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); 	//使能GPIOB时钟
      
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6;              //PB6 清除之前设置    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;			//gpio模式设置为复用模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;			//设置为推挽
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;		//不上下拉
    GPIO_Init(GPIOB, &GPIO_InitStructure);  
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_TIM4);	//设置GPIO复用为中断定时器输入
      
    //初始化定时器4 TIM4     
    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;              //设定计数器自动重装值   
    TIM_TimeBaseStructure.TIM_Prescaler =0;             	//预分频器     
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim  
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 	 	//TIM向上计数模式  
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);         			//根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位  
	
	TIM_TIxExternalClockConfig(TIM4,TIM_TIxExternalCLK1Source_TI1,TIM_ICPolarity_Falling,03);	//设置为外部计数
	TIM_SetCounter(TIM4, 0);          
    TIM_Cmd(TIM4,ENABLE );                                  									//使能定时器4  

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

(3)定时器3中断服务函数

u16 CNT;
u16 Realy_CNT;
//=========================================================================
//
//				定时器3中断服务函数
//
//=========================================================================
void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) 					//溢出中断
    {
		CNT=TIM4->CNT;
		Frequency.Fre_100_ms_Flag = 1; 	
		Realy_CNT = (CNT);
		Frequency.Frequency_Sum = ((float)Realy_CNT)/10;			//khz   f=CNT/T(timer)(S) / 1000
		TIM4->CNT = 0;
		
		printf("脉冲频率为:%.2f KHz\r\n",Frequency.Frequency_Sum);
		
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  				//清除中断标志位
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

通过定时器3每10ms读取一次定时器4的计数值,然后算出频率,计算公式为:

f=Realy_CNT/T(timer)(S) / 1000 (khz)
注:Realy_CNT:定时器4的计数器的值
T(timer)(S):定时器3的定时器值,转换成单位“s”

 Written in:2022.06.12-00.59																																				 
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/1018226
推荐阅读
相关标签
  

闽ICP备14008679号