学习STM32 CubeMX实验13:使用定时器输入捕获获取PWM频率

一、工程配置

使用定时器5作为输入捕获定时器,将通道1(PA0)设置为输入捕获,设置预分频器和计数值,这里设置为1us计数一次,最大可以捕获周期为0xFFFFFFFFus的PWM,所以一般不需要考虑溢出的问题,使能自动重装载。

使能定时器中断,选择合适的优先级, 

 将引脚设置下拉,保证没有信号输入时保持电压的稳定,最大输出速度选择高。

 在这里在这里可以选择任意定时器输出PWM,便于检验输入捕获的准确性,将TIM14通道1设置为PWM输出,频率为100Hz,其他默认即可。

二、代码初始化和捕获实现

在主函数中开启定时器捕获和更新中断,更新中断本例未使用到,根据需求开启。开启TIM14通道1,用于输出PWM,这里设置占空比为32.7%。

初始化代码中,首先设置 为上升沿捕获,进入InputCap.flag==0,记录定时器计数值,并设置为下降沿捕获,随后等待PWM波形下降沿到来,再次记录定时器计数值,两次计数值的差值就为PWM正脉宽的时长。再将触发方式设置为上升沿触发,同样记录计数值,得到负脉宽的时长,就完成一次捕获。需要注意的是代码中的溢出,若第一次记录的计数值为4294967200,如果脉宽时长为100us,那么第二次的计数值就会溢出,变成5,因为计数值最大为4294967295,超过该值将重新从0开始计数,这时候计算出来的脉宽就会为负值。我们只需要判断两次计数值的大小,做简单的处理即可(InputCap.tim_n_l=InputCap.tim_n1+0xffffffff-InputCap.tim_n2;)。

//在tim.h文件中加入

//定义一个结构体
typedef struct
{
    uint32_t tim_n_h;
    uint32_t tim_n_l;
    uint32_t tim_n1;
    uint32_t tim_n2;
    uint32_t tim_n3;
    uint32_t T;//周期
    //uint16_t overflow;//溢出计数
    uint8_t flag;//捕获完成标志
}InputCapture;
extern InputCapture InputCap;


//在tim.c文件中实现捕获功能/

//重定义结构体
InputCapture InputCap;

//捕获中断(当发生上升/下降沿时进入该函数)
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if(htim==&htim5)
    {
        if(InputCap.flag==0)//上升沿
        {
            InputCap.flag=1;//记录索引
            InputCap.tim_n1=TIM5->CCR1;//获取计数值
            //切换为下降沿捕获
                        __HAL_TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);
        }
        else if(InputCap.flag==1)
        {
            InputCap.flag=2;//记录索引
            InputCap.tim_n2=TIM5->CCR1;//获取计数值
            
            //溢出
            if(InputCap.tim_n2<InputCap.tim_n1)
            {
                InputCap.tim_n_h=InputCap.tim_n2+0xffffffff-InputCap.tim_n1;
            }
            else
            {
                InputCap.tim_n_h=InputCap.tim_n2-InputCap.tim_n1;
            }
            
            //切换为上升沿捕获
            __HAL_TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
        }
        else if(InputCap.flag==2)
        {
            InputCap.flag=0;//记录索引
            InputCap.tim_n1=TIM5->CCR1;
            
            //溢出
            if(InputCap.tim_n2>InputCap.tim_n1)
            {
                InputCap.tim_n_l=InputCap.tim_n1+0xffffffff-InputCap.tim_n2;
            }
            else
            {
                InputCap.tim_n_l=InputCap.tim_n1-InputCap.tim_n2;
            }
            
            InputCap.T=InputCap.tim_n_l+InputCap.tim_n_h;
            
            //切换为上升沿捕获
            __HAL_TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
        }
    }
}

 之后,只要不关闭输入捕获功能,就可以持续捕获,可以在main函数中100ms输出一次捕获结果

while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      printf("%dus  %dus  %0.3f%%  %fHz\r\n",
            InputCap.tim_n_h,//高电平时长
            InputCap.tim_n_l,//低电平时长
            100.0*InputCap.tim_n_h/(InputCap.tim_n_h+InputCap.tim_n_l),//占空比
            1.0/((InputCap.tim_n_h+InputCap.tim_n_l)*0.000001)//频率
            );
      HAL_Delay(100);
  }

三、效果验证

把单片机的PA0(捕获)和PF9(PWM,也可以使用外部的波形发生器),连接起来,打开串口调试助手即可看到PWM相关信息,如正负脉宽,频率,占空比等。

下期一起学习使用定时器读取正交编码器的值,控制PWM的占空比 

作者:单片kun

物联沃分享整理
物联沃-IOTWORD物联网 » 学习STM32 CubeMX实验13:使用定时器输入捕获获取PWM频率

发表评论