基于HAL库的STM32单定时器多路输入捕获测量PWM的频率和占空比实现(状态机方式实现)

2024-03-11 9991阅读

 写在前面

先回顾下定时器的单路捕获PWM

多路捕获PWM的频率和占空比(状态机实现)

我的思路:

状态图

配置

给出示例代码

测试效果


 写在前面

        先有了这篇文章实现了单定时器的多通道测量频率,以外部时钟的方式可测量任意频率的方波),奈何不能多路测试PWM波的频率,于是有了本文。

基于HAL库的STM32的单定时器的多路输入捕获测量脉冲频率(外部时钟实现)_昊月光华的博客-CSDN博客

先回顾下定时器的单路捕获PWM

对于定时器的单路捕获PWM的频率和脉冲,用cubemx配置:一个通道捕获上升沿,另一个通道捕获下降沿,Slave Mode 为Reset Mode .触发源为 TL1FP1  这可以很好地测量输入信号的周期和高电平时间,是使用定时器输入捕获的常用模式。(但仅限于定时器捕获单路PWM波)

在这种模式下:

1.上升沿到来时,触发中断,保存计数值到CCR1(假设通道1捕获上升沿的计数值),然后定时器的计数值清0(TIMx->CNT = 0)(这一点是关键)

2.下降沿到来时,保存计数值到CCR2(假设通道2捕获下降沿的计数值),定时器的计数值不会清0.

基于HAL库的STM32单定时器多路输入捕获测量PWM的频率和占空比实现(状态机方式实现) 第1张

PWM一个周期下映射到定时器的计数值 = 上升沿的计数值.(CCRx)

PWM的频率   =  定时器的频率(1M) / (捕获上升沿的计数值 -0)

PWM的占空比 = (下降沿的计数值 / 上升沿的计数值)

配置(以通道1上升沿直接捕获,通道2下降沿间接捕获)

基于HAL库的STM32单定时器多路输入捕获测量PWM的频率和占空比实现(状态机方式实现) 第2张

给出以上的实例代码

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    
    static u16 t = 0;
    static u16 d = 0;
    if(htim->Instance == TIM2)
    {
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
        {
            LEDDT[0]=1;
            t = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1)+1;
            freq = 1000000 / t;
            duty = (float)d/t*100;
            
        }
        
        else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
        {
              LEDDT[1]=2;
            d =  HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2)+1;
        }
        
        
    }
}

多路捕获PWM的频率和占空比(状态机实现)

我的思路:

  配置定时器的两个通道都为上升沿捕获,开启定时器对于通道的输入捕获中断。

状态图

基于HAL库的STM32单定时器多路输入捕获测量PWM的频率和占空比实现(状态机方式实现) 第3张

需要注意定时器的计数值有可能会溢出,所以要记录下溢出次数(在定时器的溢出更新中断中记录)

 PWM频率=  定时器频率/  两个上升沿之间的计数值

定时器频率 = 系统时钟 /预分频系数 = 1M

两个上升沿之间的计数值 = 第二次上升沿的计数值 +( 溢出次数 x 重装载值)- 第一次上升沿的计数值.

PWM占空比 =  有效计数值 / 两个上升沿的计数值

有效计数值(假设以高电平为有效电平) = 下降沿的计数值 + ( 溢出次数 x 重装载值)-上升沿的计数值

配置

设置定时器的两个通道(多通道)为上升沿捕获计数值,这意味着每次PWM波在上升沿都会进入中断,保留计数值到CCRx.

用cubemx配置的话,就是很简单的配置方式,系统时钟80m,预分配系数80-1, 定时器频率为1M,预装载为0xffff(65535)

基于HAL库的STM32单定时器多路输入捕获测量PWM的频率和占空比实现(状态机方式实现) 第4张

给出示例代码

TIM3的通道1和通道2

数据类型:

typedef struct mypwm{
    
    u32 firstrisingcnt;
    u32 secondrisingcnt;
    u32 fallingcnt;
    u32 validcnt; //有效计数值对应于脉宽
    float freq;
    float duty;
    u16 updatetimes;
    u8 state;
    
    
    
} pwms;

在溢出更新中断的回调函数中:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if(htim->Instance == TIM3)
    {
        
       mpwms[0].updatetimes++;
       mpwms[1].updatetimes++;
         //两路的更新计数值自加1,这里实际上可以用一个代替
        
        
    }
}

输入捕获的中断回调函数

void Inputcapturehandle(pwms * cpwm,u32 cnt,TIM_HandleTypeDef *htim,u32 ch)
{
    
     u32 temp = 0;
     switch(cpwm->state)
    {   
        case 0:     //测量上升沿
        {    
                //开启下次为下降沿采样
                __HAL_TIM_SET_CAPTUREPOLARITY(htim, ch, TIM_INPUTCHANNELPOLARITY_FALLING); 
                //溢出计数值置为0
                cpwm->updatetimes = 0;
               //捕获第一次计数值
                cpwm->firstrisingcnt =cnt;
                //更新状态
                cpwm->state = 1;
             
                break;
        }
         
        case 1:    //测量下降沿
        {
            //开启下一次为上升沿采样
         __HAL_TIM_SET_CAPTUREPOLARITY(htim, ch, TIM_INPUTCHANNELPOLARITY_RISING);      
         //捕获下降沿的计数值
        cpwm->fallingcnt = cnt;
         //计算有效计数值(考虑溢出)
        cpwm->validcnt =  (cpwm->updatetimes * htim->Instance->ARR)+ cpwm->fallingcnt-cpwm->firstrisingcnt;    
         //溢出计数置为0
        cpwm->updatetimes  =0;  
         //更新下一状态
        cpwm->state = 2;       
                break;     
            
         }
               
     
        case 2:  //再次测量上升沿
            {
                //捕获第二次上升沿的计数值
                cpwm->secondrisingcnt = cnt;
                //计算两个上升沿之间的计数值(考虑溢出)
                temp =  cpwm->secondrisingcnt + (cpwm->updatetimes * htim->Instance->ARR) - cpwm->firstrisingcnt;
                //溢出计数值置为0
                cpwm->updatetimes = 0;
                //计算频率 = 定时器频率/一个PWM波的两个上升沿的计数值
                cpwm->freq = 1e6/temp;
                //计算占空比
                cpwm->duty = cpwm->validcnt*1.0f / temp *100;
                //更新状态
                cpwm->state = 0;
                
                    
            }   
            break;  
            
        
    }
               
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    
   
 
     if(htim->Instance ==  TIM3)
    {
        if(htim->Channel ==  HAL_TIM_ACTIVE_CHANNEL_1)
        {
            
            //进入到自己的中断回调函数中执行
            Inputcapturehandle(&mpwms[0],TIM3->CCR1,htim,TIM_CHANNEL_1);
            
        }
        else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
        {
                 //进入到自己的中断回调函数中执行
           Inputcapturehandle(&mpwms[1],TIM3->CCR2,htim,TIM_CHANNEL_2);
        }
            
            
    }
        
        
}

测试效果

通过电位器控制输出PWM波的频率和占空比:输出格式为 频率 -占空比

基于HAL库的STM32单定时器多路输入捕获测量PWM的频率和占空比实现(状态机方式实现) 第5张


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]