电子产业一站式赋能平台

PCB联盟网

搜索
查看: 25|回复: 0
收起左侧

STM32实现等精度测频

[复制链接]

454

主题

454

帖子

2396

积分

三级会员

Rank: 3Rank: 3

积分
2396
发表于 2020-3-17 23:21:00 | 显示全部楼层 |阅读模式
上一章介绍了利用STM32的TIM的捕获功能实现频率测量的方法,但测量误差受被测信号频率的影响,不适合测量频率变化较大的 。本章将介绍等精度测频的方法以及STM32的实现。

  •     STM32硬件电路板及仿真器(以STM32F072C8单片机为例)
  •     Keil v5以上版本(MDK-ARM)

    基本原理
    首先看一张图:

    50j043olh5c64048945230.png

    50j043olh5c64048945230.png

    传统的测频方式,闸门放时间是固定的,闸门时间内被测信号的计数个数Nx不一定是整数个,因此会有一定的误差,且误差与被测信号频率有关。而等精度测频的方法,闸门时间不是固定的,而是被测信号的整数倍。 因此消除了对被测信号计数的±1误差,其误差只与标准信号的计数个数Ns的±1误差有关。可以看出,闸门时间越长,标准频率Fs越大,Ns的计数值越大,±1误差的影响就小。在相同的闸门时间内,被测信号的频率Fx=Nx*Fs/Ns。

    STM32的实现
    实现等精度测频用到两个定时器,其中一个定时器用于产生闸门时间,另外一个用于捕获被测信号和标准信号计数。
    实现步骤:
    TIM1设置约1秒的闸门时间。TIM3捕获到被测信号上升沿后,将TIM1计数器清零。闸门时间开始,TIM3开始捕获计数同时本身计数器也开始计数。闸门时间到后,标志置位。TIM3检测到标志置位且捕获到上升沿后,记录当前捕获计数的值Nx和本身计数器的计数值Ns。计算被测信号频率Fx=Nx*Fs/Ns,其中Fs为定时器时钟频率48MHz。[/ol]
    STM32CubeMX的TIM配置如下:

    gfkcpzrrpdu64048945330.jpg

    gfkcpzrrpdu64048945330.jpg

    TIM1作为产生闸门时间的定时器,其计数周期设置为47999,时钟为系统时钟,1000分频。则溢出周期即闸门时间为1秒,打开溢出中断:

    sbcb1is1eyj64048945430.png

    sbcb1is1eyj64048945430.png

    TIM3作为捕获被测信号的定时器,其配置如下,通道1设置为捕获模式,捕获上升沿,定时周期设置为最大65535,时钟为系统时钟,不分频。打开中断(TIM3捕获和溢出为同一个中断)。

    iasacpombgt64048945530.png

    iasacpombgt64048945530.png

    hguccb04syy64048945630.jpg

    hguccb04syy64048945630.jpg



    程序实现:
    按照之前介绍的步骤设置其它外设,并生成代码。初始化后,启动TIM1和TIM3中断。
  •   HAL_TIM_Base_Start_IT(&htim1);  HAL_TIM_Base_Start_IT(&htim3);  HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);编写中断回调函数。
  • #define Fs 48000000L  //定时器时钟频率uint32_t TIM3_Cnt_Value[2];//定时器3捕获值uint32_t TIM3_Over_Cnt=0;//定时器3溢出次数uint32_t TIM1_Over_Flag=0;//定时器1溢出标志uint32_t Ns,Nx;//标志信号计数值  被测信号计数值double Fx;//被测频率
    //定时器溢出中断 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
      if(htim->Instance == TIM1)  {    TIM1_Over_Flag = 1;  }  if(htim->Instance == TIM3)  {    TIM3_Over_Cnt++;    if(TIM3_Over_Cnt==0xffffffff)TIM3_Over_Cnt=0xfffffffe;  }
    }
    //定时器捕获中断void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){  if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)  {    if(TIM1_Over_Flag == 0)    {      __HAL_TIM_SET_COUNTER(&htim1,0);//TIM1清零 开始闸门时间      TIM3_Cnt_Value[0] = __HAL_TIM_GET_COUNTER(&htim3);      Nx++;    }    else if(TIM1_Over_Flag == 1)//闸门时间到    {      Nx++;      TIM3_Cnt_Value[1] = __HAL_TIM_GET_COUNTER(&htim3);      Ns = (TIM3_Over_Cnt16) + TIM3_Cnt_Value[1] - TIM3_Cnt_Value[0];//计算标准信号的计数值      TIM1_Over_Flag = 2;//一次测量完成 标志置位    }  }}//计算被测频率void CalcFx(void){  if(TIM1_Over_Flag == 2)  {    Fx = (double)Nx * Fs / Ns;//计算频率    Nx=0; //计数清零    TIM1_Over_Flag = 0;//标志清零,可以开始下一次测量  }}
    在主函数中调用CalcFx()函数即可获取被测信号的频率。
    以上即为利用STM32定时器实现等精度测频的全部内容,STM32定时器的功能还有很多,如触发ADC采样、编码器模式等。不再一一做介绍,下一章开始介绍STM32串口的使用方法,敬请期待。
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表