高级定时器PWM输入模式的配置方法

描述

MCU微课堂

CKS32F107xx TIM(三)

第四十八期 2024.11.08

PWM输入捕获

上节课我们介绍了高级定时器互补PWM输出的配置方法,这节课我们将向大家介绍高级定时器的另一个常见应用——PWM输入模式。在本节课中,我们将先围绕输入捕获模式展开,并重点描述PWM输入模式和涉及的寄存器,最后通过一个实验例程去介绍PWM输入模式的配置方法。

输入捕获模式简介

1、普通输入模式

除基本定时器外,其余定时器的部分通道都可以对输入信号的上升沿、下降沿或者双边沿进行捕获,并且计数器CNT的值会被锁存到捕获/比较寄存器CCR中。当我们需要同时捕获PWM波的频率和占空比时,仅需要测出一个周期中高电平和低电平持续的时间即可。我们可尝试如下步骤:首先将定时器的某一通道初始设置为上升沿捕获,当发生第一次捕获到上升沿的中断,以此中断时刻作为一个起点,读取CCR中值为Value1,此时将捕获模式设置为下降沿捕获,在发生第二次中断的时候,捕获到了下降沿,读取CCR中值为Value2,那么Value2和Value1之间的差值,就是一个周期中高电平持续的时间,然后我们在中断中又将捕获的方式设置为上升沿捕获,那么在第三次产生中断的时候,读取CCR中值为Value3,那么Value3和Value2之间的差值就是一个周期中低电平的时间。至此,PWM波的频率可由Value3和Value1之间的差值计算出,正占空比则可通过高电平占整个周期的比值获得。如下图1所示:

mcu

图1 普通输入捕获概览图

2、PWM输入模式

PWM输入模式是普通输入模式的一种特例,以输入通道TI1为例,PWM信号进入该通道后,信号被分成TI1FP1和TI1FP2两路,最终分别映射到了IC1和IC2捕获通道,其中一个捕获上升沿,另一个捕获下降沿。这样用户可以在中断中去读上升沿和下降沿对应寄存器中的计数,从而得出周期和占空比。并且用户在设计之初,需要先选定哪一路为触发信号以及触发极性,一旦选定某一路为触发信号则对应的即为周期,另一路则对应为占空比,两路捕获极性也是相反的,并且因为是PWM输入捕获的缘故,当其中一路配置完成,另一路由硬件自动配置,无需软件来配置。图2为PWM输入模式时序图。

mcu

图2 PWM输入模式时序图

其中,IC1捕获通道计算两次都是上升沿的时间,即周期T;而IC2通道则计算一次下降沿和之前上升沿之差,这样得到高电平时长,从而可以求得周期T和占空比。需要注意的是,PWM输入模式需要占用两个捕获寄存器,且只有TI1FP1和TI2FP2连接到了从模式控制器(使用PWM输入捕获时,需要配置从模式控制器为复位模式),所以只能使用定时器的通道1或通道2。

寄存器和输入捕获结构体概述

1、捕获/比较寄存器CCMR

关于CCMR寄存器,上节课我们介绍了输出比较模式,这节课我们来介绍下输入捕获模式,该寄存器的各位描述图如下:

mcu

图3 CCMR1寄存器各位描述图

该16位寄存器CCMR的下层对应输入捕获(上层对应输出比较),其中CCMR1用于捕获通道1和2的控制,CCMR2用于捕获通道3和4的控制。下图为低8位详细描述图,用于捕获通道1。

mcu

图4 CCMR1寄存器低7位描述图

参数CC1S,用于输入捕获/输出比较通道的引脚选择,若我们设置CCIS[1:0] = 01,表明CC1通道(对应定时器的通道1)被配置为输入,IC1映射在TI1上。

参数IC1PSC,配置为00时,表明每1个边沿触发1次捕获。

参数IC1F,用来设置TI1输入采样频率和数字滤波器长度,本课中我们不做滤波处理。

2、捕获/比较使能寄存器CCER

在本课中我们仅用到低2位CC1E和CC1P,由于我们需要在中断中处理捕获的数据,所以配置CC1E为1,CC1P配置为不反相,故设置为0。CCER低2位图如下描述。

mcu

图5 CCMR1寄存器低7位描述图

3、输入捕获结构体TIM_ICInitTypeDef

可配合TIM_PWMIConfig函数完成定时器输入通道各参数的初始化配置。输入捕获结构体的各参数定义如下:

typedef struct

{

uint16_t TIM_Channel;
uint16_t TIM_ICPolarity;
uint16_t TIM_ICSelection;
uint16_t TIM_ICPrescaler;
uint16_t TIM_ICFilter; 

} TIM_ICInitTypeDef;

1)参数TIM_Channel:设定CCMRx寄存器CCxS位,用于捕获通道ICx选择。

2)参数TIM_ICPolarity:设定CCER寄存器CCxP位和CCxNP位,用于输入捕获边沿触发选择。

3)参数TIM_ICSelection:设定CCRMx寄存器的CCxS[1:0]位,用于输入通道选择,输入通道共有三个来源,分别为:TIM_ICSelection_DirectTI、TIM_ICSelection_IndirectTI或TIM_ICSelection_TRC。若为普通输入模式,4个通道均能使用;若为PWM输入模式,只能使用通道1和2。输入通道和捕获通道的映射关系详见下图。

mcu

图6 输入通道和捕获通道的映射关系

4)参数TIM_ ICPrescaler:设定CCMRx寄存器的ICxPSC[1:0]位的值,用来设置输入捕获分频系数,有1、2、4、8分频可选。这里我们需要捕获输入信号的每个有效边沿,故设置为1分频即可。

5)参数TIM_ ICFilter:设定CCMRx寄存器ICxF[3:0]位,用于设置输入捕获滤波器。

本课中我们配置的示例代码如下:

TIM_ICInitTypeDef        TIM_ICInitStructure;

TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;

TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

TIM_ICInitStructure.TIM_ICFilter = 0x0;

TIM_PWMIConfig(TIM1, &TIM_ICInitStructure);

上述代码中,我们设置定时器的通道1为上升沿捕获,且输入通道1(TI1)与捕获通道1(IC1)为直接映射,不分频,不使用滤波器。 

PWM模式输入配置实验

本实验配置高级定时器的通道1,即PA8,用于捕获信号发生器输出PWM信号,最后通过串口调试助手打印捕获到的PWM的频率和占空比。主要的编程要点如下。

1、高级定时器引脚初始化

由于TIM1_CH1是连接在PA8上,这里需要开启GPIOA时钟,并配置引脚为浮空输入,我们配置的代码如下:

void TIM1_GPIO_Configuration(void)

{

  GPIO_InitTypeDef      GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

}

2、高级定时器中断优先级设置

之前的课程中让我们对中断优先级已经有了深入了解,这里因为我们只有一个捕获/比较中断源,所以优先级随便设置,我们配置的代码如下:

void TIM1_NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);  

NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

3、高级定时器PWM输入模式配置

我们主要对时基和输入捕获结构体初始化,配置代码如下:

void TIM1_Input_Capture_Mode_Configuration(void)

{

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

TIM_ICInitTypeDef        TIM_ICInitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);

     /* Time Base Configuration */

TIM_TimeBaseStructure.TIM_Period = 65535-1;

TIM_TimeBaseStructure.TIM_Prescaler = 72-1;

TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;  

TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;  

TIM_TimeBaseStructure.TIM_RepetitionCounter=0;

TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

/* PWM Input Capture Configuration */

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;

    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

    TIM_ICInitStructure.TIM_ICFilter = 0x0;

    TIM_PWMIConfig(TIM1, &TIM_ICInitStructure);

TIM_SelectInputTrigger(TIM1, TIM_TS_TI1FP1);  

    TIM_SelectSlaveMode(TIM1, TIM_SlaveMode_Reset);

    TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable);

    TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);

TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);

    TIM_Cmd(TIM1, ENABLE);

}

从上述示例代码来看,我们首先将TIM1_CH1的捕获计数器设置为1us计数一次,重装载值为65535,所以可以捕获的时间精度为1us,最低可捕获的频率为15.3Hz。其次,我们选择TIM1的通道1(TI1)作为PWM信号输入,并选择TI1FP1为触发信号(输入的信号被分为TI1FP1和TI1FP2),因此IC1捕获PWM信号周期,IC2捕获PWM信号占空比。而且由于PWM输入模式下,当捕获开始时,需要将CNT复位,所以我们需要配置定时器以从模式工作在复位模式下,最后使能捕获中断和高级定时器。

4、高级定时器中断服务函数配置

在函数TIM1_CC_IRQHandler中,如果是第一个上升沿中断,计数器CNT会被复位,锁存到CCR1寄存器的值是0,CCR2寄存器的值也是0,无法计算频率和占空比。当第二次上升沿到来的时候,CCR1和CCR2捕获到的才是有效的值。其中CCR1对应的是周期,CCR2对应的是占空比。我们配置的代码如下:

void TIM1_CC_IRQHandler(void)

{

    TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);

    IC1Value = TIM_GetCapture1(TIM1);

    IC2Value = TIM_GetCapture2(TIM1);

if (IC1Value != 0)

    {

      DutyCycle = (float)((IC2Value+1) * 100) / (IC1Value+1);

      Frequency = (72000000/((72-1)+1))/(float)(IC1Value+1);

  printf("占空比:%0.2f%%   频率:%0.2fHz ", DutyCycle, Frequency);

     }

     else

     {

       DutyCycle = 0;

       Frequency = 0;

     }

}

5、主函数配置

main函数就是对上述函数的调用,配置示例如下: 

int main(void)

{   

CKS_USART_Init();

printf("CKS Timer Input Capture Demo start running... ");

TIM1_GPIO_Configuration();

TIM1_NVIC_Configuration();

    TIM1_Input_Capture_Mode_Configuration();

while(1){}

}

至此,我们配置已完成。

6、下载验证

我们将编译好的程序下载至CKS32F107xx开发板,信号发生器和PWM输入引脚PA8通过杜邦线连接,USB转TTL模块分别与UART1—PA9和电脑相连,然后打开串口调试助手,查看打印信息。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分