我是靠谱客的博主 坚强季节,最近开发中收集的这篇文章主要介绍STM32利用外部中断和定时器测量信号频率,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

摘要

利用定时器产生PWM波。然后利用32的外部中断和定时器来测量32输出的波形 硬件:STM32F103C8T6核心板、示波器、串口调试助手 所用到的的引脚为PA8和PA0。

测量方案

在第一次外部中断(上升沿触发)到之时,开启定时器,同时计数器清零。然后等待第二次中断到来,在第二次外部中断(上升沿触发)到之时,获取计数器的计数值,同时关闭计数器。因为知道了计数器计数一个数的时间,所以在第二次外部中断(上升沿触发)到之时,获取计数器的计数值,通过这个值就知道一个脉冲的时间周期。时间周期的倒数就是外部信号的频率。

外部中断和定时器测量频率

在配置定时器时最重要的就是配置定时器的预分频系数和重装载值。定时器的本质就是一个计数器,计数到我们设定的值后就会溢出,也就是重新从0开始开始计数。设置预分频系数就是设置计数器的频率,假设为71,F1的系统时钟为72M,经过72分频,给计数器的时钟频率就是1M,周期就是1/1M=1us。也是就1us计一个数。那么计几个数呢?这就要看重装载值ARR,这里我们设置为0XFFFF,也就是计数65536个数,就是计满整个寄存器的值。为什么要分频系数为72,重装载值为0XFFFF?这里给出详细的分析过程。
1 为什么要分频系数为72
F1的系统时钟为72M,F1的系统时钟为72M,如果不分频的话,提供给定时器的时钟就直接是72MHZ。72MHz是个什么概念?72MHz它对应的周期就是(1/72000000)秒,也就是计数器从0计数到最大值65535,只需要花费(65535/72000000)秒≈1ms。这句话的意思就是如果你不分频,计数器最大只能定时1ms。那么你的定时器每隔1ms就会溢出一次。如果经过72分频,给计数器的时钟频率就是1M,周期就是1/1M=1us,也是就1us计一个数。换句话就是可以采样的波形频率为1M,提高了采样频率。另一方面也是容易计算,计一个数1us,计count个数就是count个us,频率就是1000000/count(HZ)。
2 为什么要重装载值为0XFFFF
最大采样间隔是跟定时器的中断间隔相关的,定时器产生溢出中断后计数值CNT会自动清0,定时器的中断间隔由分频系数Prescaler和自动重装载寄存器Period决定,分频系数前面已经确定,那最大采样间隔只需要考虑自动重装载寄存器Period的设置,比如频分析系数71,自动重装寄存器值65535,则中断间隔=65536/72000000/72=65.536ms,即最大采样间隔65.536ms,如果65.536ms内没有检测到一个脉冲,则这么设定间隔是不合理的,必须想办法牺牲最小的采样时间1us(扩大分频系数)或者扩大自动重装寄存器值(16位<65535)来增加定时器中断间隔,也可以编写自己的应用函数来计算溢出的定时时间。
一般来说我们使用外部中断是不需要用到定时器的,看原子和野火的外部中断实验也没有用到外部中断。但是现在不是利用外部中断简单的处理一件事,而是利用外部中断测量频率,而测频率就涉及到时间,而只要涉及到时间,就需要用到定时器了。测量外部信号的频率,就是测量PWM波对吧!如果我们测量到一个周期的时间,那么不就知道了信号的频率了吗?

具体代码如下:

void EXTI0_IRQHandler(void)
{
 if(EXTI_GetITStatus(EXTI_Line0)!= RESET)
 {
  EXTI_ClearITPendingBit(EXTI_Line0);//清除EXTI0线路挂起位 
  if(CaptureNumber == 0)//第1次上升沿触发
  {
   TIM_Cmd(TIM2,ENABLE);//使能定时器2
   TIM_SetCounter(TIM2,0); //清零计数器的值,因为一开始就开始计数了
   CaptureNumber++;
  }
  else if(CaptureNumber==1)//第2次上升沿触发
  {   
   TimeCntValue = TIM_GetCounter(TIM2);
   Capture = TimeCntValue;
   CaptureNumber = 0; 
   TIM_Cmd(TIM2,DISABLE);//使能定时器2    
  }
 } 
}
int main(void)
{ 
 float x;
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
 delay_init();
 uart_init(115200);
 TIM2_Init();
 TIM1_PWM_Init(7199,0);  //不分频,输出PWM频率=72000K/(7199+1)=10Khz
 EXTIA0_Init();
 while(1)
 {
  printf("Fre=%.2f kHzrn",1000000/Capture);
  delay_ms(1000); 
 }
}

当然你可能觉得这只是测量信号的一个周期脉冲不够准确,那么也可以测量100次脉冲的时间再除以100,就是一个脉冲的时间,然后再取倒数就可以算出频率,这种方法也是可以的。具体代码如下:

void EXTI0_IRQHandler(void)
{
 if(EXTI_GetITStatus(EXTI_Line0)!= RESET)
 {
  EXTI_ClearITPendingBit(EXTI_Line0);//清除EXTI0线路挂起位 
  if(CaptureNumber == 0)//第1次上升沿触发
  {
   TIM_Cmd(TIM2,ENABLE);//使能定时器2
   TIM_SetCounter(TIM2,0); //清零计数器的值,因为一开始就开始计数了
   CaptureNumber++;
  }
  else if(CaptureNumber>0&& CaptureNumber<100)
  { 
   TimeCntValue0 = TIM_GetCounter(TIM2);   
   CaptureNumber++;
   
  }
  else if(CaptureNumber==100)//第100次上升沿触发
  {   
   TimeCntValue = TIM_GetCounter(TIM2);
   Capture = TimeCntValue/100;
   CaptureNumber = 0; 
   TIM_Cmd(TIM2,DISABLE);//使能定时器2    
  }
 } 
}

int main(void)
{ 
 float x;
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
 delay_init(); 
 uart_init(115200);   
 TIM2_Init();
 TIM1_PWM_Init(7199,0);  //不分频,输出PWM频率=72000K/(7199+1)=10Khz
 EXTIA0_Init();
 while(1)
 {
  printf("Fre=%.2f kHzrn",1000000/Capture);
  delay_ms(1000); 
 }
}

最后

以上就是坚强季节为你收集整理的STM32利用外部中断和定时器测量信号频率的全部内容,希望文章能够帮你解决STM32利用外部中断和定时器测量信号频率所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部