TIM

定时器同步

CKS32F107xx系列部分定时器在内部是相连的,可用于定时器同步或链接,方便用户配置不同的同步模式,以便在电机控制、数据采集和PWM信号生成等应用中,实现复杂的时间序列和多通道的同步操作。本节课我们将围绕定时器同步功能概述展开,并以其中一种功能为例——将定时器2给定时器3当预分频器,最终级联同步PWM输出。

依据《CKS32F107xx参考手册》的从模式控制寄存器相关章节得知,并非任意两个定时器都能任意级联,硬件方面是固定的,若某个产品中没有相应的定时器,则对应的触发信号ITRx也不存在。如下表1所示。

1.png

表1 普通输入捕获概览图

如下图1所示,TIM2更新事件的输出信号TRGO1可以连接到TIM3的内部触发信号线ITR1(可由表1查阅得知),作为TIM3 的时钟输入。

2.png

图1 主从定时器示例

要使TIM2和TIM3级联同步输出PWM波形,我们还会用到控制寄存器2(TIMx_CR2)和从模式控制寄存器(TIMx_SMCR)。接下来我们简单介绍下这两个寄存器。

首先是控制寄存器2(TIMx_CR2),该寄存器的各位描述如下图所示:

3.png

4.png

图2 TIMx_CR2

关于该寄存器的详细说明,请参照《CKS32F107xx参考手册》。这里我们用到的是主模式选择位域MMS,此部分由3位组成。共有8种模式可供选择,因为我们使用的是更新模式,所以必须设置为010。

接下来我们介绍从模式控制寄存器(TIMx_SMCR),该寄存器的各位描述如下图所示:

5.png

6.png

 图3 TIMx_SMCR

在该寄存器中,我们用到了SMS和TS位域,均由3位组成,各有8种不同模式组合。其中SMS控制从模式选择,这里我们配置成100,选择门控模式,确保从定时器的开始和结束都是由主定时器的输出信号控制。TS控制触发选择,根据表1描述得知,我们必须配置成001。

定时器级联同步输出PWM配置操作

通过上述对定时器功能的描述,下面我们要实现TIM2发生事件更新时发送触发信号驱动TIM3计数,并使能两个定时器在PWM1模式下由定时器通道1输出PWM波形。编程的要点如下所示。

1、配置PA0和PA6引脚为复用输出功能

我们调用如下函数实现:

void TIM_GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);


  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_6;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

}

2、TIM2配置为主定时器

TIM2配置为PWM1模式输出,使能主从模式,并选择更新事件作为触发输出,主要代码如下:

void TIM2_Master_Mode_Configuration(void)

{

  TIM_TimeBaseInitTypeDef      TIM2_TimeBaseStructure;

TIM_OCInitTypeDef           TIM2_OCInitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);


/* Time Base Configuration */

  TIM2_TimeBaseStructure.TIM_Prescaler = 8;

  TIM2_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM2_TimeBaseStructure.TIM_Period = 79;

  TIM2_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseInit(TIM2, &TIM2_TimeBaseStructure);


/* TIM2 Channel 1 Configuration in PWM1 mode */

  TIM2_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

  TIM2_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

  TIM2_OCInitStructure.TIM_Pulse = 40 ;

  TIM2_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  TIM_OC1Init(TIM2, &TIM2_OCInitStructure);

  TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);


/* Master Mode selection */

  TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

}

从上述代码可得知,TIM2CLK固定为72MHz,TIM2预分频为8,因此主定时器TIM2计数器时钟频率为8MHz频率,则TIM2频率=TIM2计数器时钟/(TIM2_Period + 1)=100KHz,占空比为TIM2_CCR1/(TIM2_ARR + 1) = 50%。

3、TIM3配置为从定时器

TIM3配置为门控模式,并选择ITR1作为输入,主要代码如下:

void TIM3_Slave_Mode_Configuration(void)
{  
    TIM_TimeBaseInitTypeDef  TIM3_TimeBaseStructure;  
    TIM_OCInitTypeDef      TIM3_OCInitStructure;  
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  
    /* Time Base Configuration */  
    TIM3_TimeBaseStructure.TIM_Prescaler = 0;  
    TIM3_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
    TIM3_TimeBaseStructure.TIM_Period = 4;  
    TIM3_TimeBaseStructure.TIM_ClockDivision = 0;  
    TIM_TimeBaseInit(TIM3, &TIM3_TimeBaseStructure); 
    /* TIM3 Channel 1 Configuration in PWM1 mode */  
    TIM3_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;  
    TIM3_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  
    TIM3_OCInitStructure.TIM_Pulse = 2;  
    TIM3_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  
    TIM_OC1Init(TIM3, &TIM3_OCInitStructure);  
    /* Slave Mode selection: TIM3 */  
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);  
    TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1);
}

从上述代码可得知,从定时器TIM3频率为(TIM2 frequency)/ (TIM3 period + 1)=20kHz,占空比为TIM3_CCR1/(TIM3_ARR + 1) = 40%。

4、主函数

初始化主从定时器,最终实现级联同步PWM输出,主要代码如下:

int main(void)

{

  TIM_GPIO_Configuration();

  TIM3_Slave_Mode_Configuration();

  TIM2_Master_Mode_Configuration();

  TIM_Cmd(TIM2, ENABLE); /* Enable TIM2 Counter */

  TIM_Cmd(TIM3, ENABLE);  /* Enable TIM3 Counter */


  while(1)

  {

  }

}

至此,用示波器测量PA0和PA6引脚的波形(注意共地);下载程序,调节示波器,可在示波器看到有PWM波形输出,如下图4所示:

7.png


图4 PWM波形输出

相关阅读:

MCU微课堂|CKS32F107xx TIM(一)

MCU微课堂 | CKS32F107xx TIM(二)

MCU微课堂 | CKS32F107xx TIM(三)

来源:中科芯MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 14

相关阅读:

MCU微课堂|CKS32F107xx TIM(一)

MCU微课堂 | CKS32F107xx TIM(二)

PWM输入捕获

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

输入捕获模式简介

1、普通输入模式

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

1.png

图1 普通输入捕获概览图

2、PWM输入模式

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

2.png

图2 PWM输入模式时序图

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

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

1、捕获/比较寄存器CCMR

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

3.png

图3 CCMR1寄存器各位描述图

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

4.png

图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位图如下描述。 5.png

图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。输入通道和捕获通道的映射关系详见下图。

6.png

图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\n", DutyCycle, Frequency);

     }

     else

     {

       DutyCycle = 0;

       Frequency = 0;

     }

}

5、主函数配置

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

int main(void)

{   

CKS_USART_Init();

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


TIM1_GPIO_Configuration();

TIM1_NVIC_Configuration();

    TIM1_Input_Capture_Mode_Configuration();


while(1){}

}

至此,我们配置已完成。

6、下载验证

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

来源:中科芯MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 27

相关阅读:MCU微课堂|CKS32F107xx TIM(一)

PWM模式简介

从上节课的定时器分类图中我们了解到,互补输出是高级定时器(TIM1、TIM8)所独有的,它可以输出两路互补信号。而在本节课中我们将通过一个简单的例程去介绍如何配置互补PWM输出,同时为了演示在电机控制领域的入门应用,该例程也增加了刹车和死区插入的功能。因此,接下来我们将先对PWM模式、互补输出、死区插入、刹车功能这四个概念作简要介绍,然后通过一个实验例程来演示PWM输出配置方法。

比较输出是通过比较计数器CNT和捕获/比较寄存器CCR的关系,来对输出电平进行置1、置0或翻转的操作,而PWM模式输出的是一种脉冲宽度可调的方波信号,同时也是定时器(高级和通用)比较输出模式中较为常用的一种,我们可以通过捕获/比较模式寄存器CCMRx的位OCxM[2:0]来配置输出。表1罗列了PWM1和PWM2的区别,并通过PWM1边沿对齐的波形示例图来简述下PWM输出的原理。

1.png

表1 PWM1和PWM2模式区别

2.png

图1 边沿对齐的PWM1波形(TIMx_ARR=8)

如上图所示,当CNT < CCR时,参考信号OCxREF输出为高,则通道OCx输出1;当CCR <= CNT <= ARR时,参考信号OCxREF输出为低,则通道OCx输出0。并且当计数器CNT与比较寄存器CCR值匹配时,比较中断寄存器CCxIF位会自动由硬件置 1;而CNT计数达到ARR的值时,会产生上溢事件,并且自动清零,然后重新向上计数,如此循环往复。因此,我们可以通过修改ARR和CCR的值来灵活调整PWM波形的频率和占空比。

定时器产生PWM 输出,除了上节课提到的ARR、PSC、CNT,不得不提的还有捕获/比较模式寄存器CCMR。该寄存器共有两个,CCMR1(控制输出通道1和2)和CCMR2(控制输出通道3和4),且上面一层对应比较输出,下面一层对应输入捕获,输入捕获模式将在下节课中介绍。由于本节课介绍的是互补PWM输出,所以模式设置位OCxM[2:0],必须设置为110/111,对应PWM1/PWM2,两者区别是极性相反。下图是CCMR1寄存器各位描述图,具体请参照CKS32F107xx参考手册。

3.png

图2 CCMR1寄存器各位描述图

互补输出和死区插入简介

接下来将先通过捕获/比较通道的输出概览图来展现输出控制过程。

4.png

图3 捕获/比较通道的输出部分(通道CH1~CH3)

如上图,红框中是CNT和CCR比较,输出参考信号OCxREF,衔接上文。绿框表明参考信号OCxREF在经过死区发生器之后会产生两路带死区的互补信号OCx_DT和OCxN_DT,并且需要特别说明下,高级定时器(TIM1、TIM8)只有通道CH1~CH3才有互补信号。蓝框是输出控制电路,若没有死区控制,则进入的信号即为OCxREF,且进入的信号会被分成极性相反的两路,并由寄存器CCER的位CCxP和CCxNP控制极性,由CxE和CCxNP位使能输出。若增加了刹车功能,则寄存器BDTR的位MOE、OSSI和OSSR将共同影响输出信号。

关于死区插入,其中一个较为典型的应用就是半桥驱动电路,比如上个时态MOS管M1导通,MOS管M2截止,下一时态需要M1截止,M2导通,由于工艺限制MOS管的关闭不能忽略不计,这就会导致M1和M2有同时导通的时间,进而损坏电路,所以可将M1关闭后等待一段时间再打开M2,这段时间可称为死区时间。死区时间是通过寄存器BDTR的位DTG[7:0]来配置,死区时间的大小需要根据输出通道相连接的器件特性来调整。下图为带死区插入的互补输出图,相信这样能大家有个更为直观的了解。

5.png

图4 带死区插入的互不输出

刹车功能简介

电路控制电机转动出现异常时,若用软件来关闭信号输出,出于软件延时的影响,可能带来不必要的后果。在此工况下,高级定时器中的刹车功能能发挥特定优势,用户只要将检测端连接到TIMx_BKIN引脚,当检测到非正常态,由硬件电路立刻关闭信号输出,电机即可停止转动。刹车功能是一种硬件保护保护,用户需要配置刹车和死区寄存器BDTR,该寄存器各位描述如下:

6.png

7.png

图5 BDTR寄存器各位描述图

互补PWM输出配置实验

本实验以高级定时器TIM1为例,并参照CKS32F107xx数据手册的引脚定义章节,分配了OC1(PA8)、OC1N(PB13)和BKIN(PB12)引脚。若我们在工程中选择BKIN引脚高电平有效,那么当BKIN引脚被置高时,两路互补PWM信号立刻停止输出。主要的编程要点如下。 

1、开启GPIO时钟,配置引脚

要使用GPIOA、GPIOB的相关引脚,需要开启端口时钟,调用的函数为:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

因为要将普通GPIO复用到定时器的相关引脚,所以要配置GPIO工作模式,示例代码如下,以PA8配置为例,PB13和PB12配置雷同:

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

2、TIM1时基结构体设置

鉴于前一章节已详述过,这里仅做代码演示,针对TIM1时基初始化示例代码格式如下: 

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Prescaler= 8;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;  
TIM_TimeBaseStructure.TIM_Period=7;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;  
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

根据前文定时时间的描述,当TIM1工作时钟配置为72MHz时,那么示例代码中配置的中断次时间为:(8+1)*(7+1) / 72000000 = 1us,则PWM输出的频率为1MHz。

3、TIM1输出比较结构体设置

通过配置TIM1_CCMR1的相关位来设置TIM1_CH1的PWM模式。在库函数中,PWM通道设置是通过函数TIM_OC1Init()~TIM_OC4Init()来设置的,不同通道的设置函数不一样,使用时需要注意区分,这里我们选用CH1通道和CH1N通道,选用的库函数如下:

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

输出比较结构体在库函数中对应名称为TIM_OCInitTypeDef,下面是结构体的定义:

typedef struct
{
    uint16_t TIM_OCMode;
    uint16_t TIM_OutputState;uint16_t TIM_OutputNState;
    uint16_t TIM_Pulse;uint16_t TIM_OCPolarity;
    uint16_t TIM_OCNPolarity;uint16_t TIM_OCIdleState;
    uint16_t TIM_OCNIdleState;
} TIM_OCInitTypeDef;

参数TIM_OCMode是用来设置比较输出模式,这里我们选用PWM1模式。

参数TIM_OutputState和TIM_OutputNState用来配置OCx和OcxN通道输出使能。

参数TIM_Pulse是设置比较寄存器CCR的值,决定脉冲宽度,对应PWM1的占空比。

参数OCPolarity和TIM_OCNPolarity是设置OCx和OcxN通道极性,我们可以选择高电平或低电平有效。

参数TIM_OCNIdleState和TIM_OCNIdleState是设置空闲状态时OCx和OcxN通道输出的电平。

针对TIM1输出比较结构体初始化示例如下:

TIM_OCInitTypeDef      TIM_OCInitStructure;  
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = 4;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

在该示例中,设置了工作模式PWM1,使能了OCx和OcxN通道,配置了脉冲宽度、输出极性和空闲状态下的输出电平,所以PWM1的占空比为:CCR / (ARR + 1) = 50%。

4、TIM1断路和死区结构体设置

我们在库函数中设置刹车和死区参数是通过函数TIM_BDTRConfig来实现的,其结构体TIM_BDTRInitTypeDef中列出了各个成员,以下是结构体的定义:

Typedef struct  
{  
    uint16_t TIM_OSSRState;           
    uint16_t TIM_OSSIState;           
    uint16_t TIM_LOCKLevel;           
    uint16_t TIM_DeadTime;            
    uint16_t TIM_Break;             
    uint16_t TIM_BreakPolarity;       
    uint16_t TIM_AutomaticOutput;   
}TIM_BDTRInitTypeDef;

这里结构体中的成员可以对照上文BDTR寄存器的各位来理解,在此不再赘述,本实验中我们针对TIM1断路和死区结构体初始化示例如下:

TIM_BDTRInitTypeDef    TIM_BDTRInitStructure;
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
TIM_BDTRInitStructure.TIM_DeadTime = 11;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);

在该示例中,配置的死区时间为11 / 72000000 = 152ns,配置BKIN引脚为高电平有效。

5、使能TIM1和主输出

因为本实验是互补PWM输出,所以除了要开启定时器,也要对定时器主输出进行使能,配置示例如下: 

TIM_Cmd(TIM1, ENABLE);TIM_CtrlPWMOutputs(TIM1, ENABLE);

6、修改TIM1_CCR1来调整占空比

实际使用时,用户需要控制占空比来调整电机的转速,我们能通过修改TIM1_CCR1则可以控制CH1的输出占空比。在库函数中,修改TIM1_CCR1占空比的函数是:

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);

同样的,对于其他三个通道,也有如下对应函数供调用,用户使用时注意区分即可。

void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

只要按照上述配置,用户在主函数中调用即可,我们示波器的两个输入通道分别接PA8、PB13引脚,可观测到两路互补带死区插入的PWM波形,频率为1MHz,占空比默认为50%(用户可自行调整),死区时间为152ns左右。

8.png

如果将BKIN引脚拉高,可观测到输出信号立刻停止,若松开则恢复默认输出。

9.png

至此,本实验已介绍完毕。

来源:中科芯MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 24

引言

MindSDK为MM32使用星辰处理器内核的系列微控制器,实现了一组TIM样例工程,MindSDK中的TIM模块对应硬件定时器TIM外设。本文通过讲解TIM模块的样例工程,介绍TIM模块的功能和用法。关于TIM模块对应的驱动程序,以及TIM外设模块硬件的实现细节,可具体查阅MindSDK工程的源文件,以及MM32微控制器(例如MM32F5270)的用户手册。

样例工程

MindSDK中为TIM驱动设计的样例工程包括:

  • tim_basic

  • tim_one_time_run

  • tim_output_compare_pwm

  • tim_input_capture

  • tim_external_trigger_input

  • tim_slave_mode

  • tim_slave_mode_encoder

  • tim_comp_output_compare_pwm

其中,tim_basic、tim_one_time_run、tim_output_compare_pwm、tim_input_capture和tim_external_trigger_input 分别演示了定时器最典型的功能,包括定时、输出比较、输入捕捉,以及对外部脉冲进行计数等。另外,还有一些不大典型,用在特殊应用场景的功能,例如,使用“从机”模式干预常规的定时器计数,通过硬件实现互补的PWM输出(常用于电机控制应用中控制驱动桥)。

tim_basic

tim_basic 描述了使用TIM模块最基本的方式,周期定时器。在样例工程中,通过 TIM_Init() 函数,配置一个选定的TIM外设模块的计数引擎,为连续计数模式 TIM_PeriodMode_Continuous ,并指定计数周期为  APP_TIM_UPDATE_PERIOD 。然后,启用选定TIM外设模块对应的NVIC中断。最后,通过调用 TIM_Start() 驱动函数,启动定时器开始计数。

每当定时器计数到达预设的计数周期值后,计数值折返为0,重新开始计数。同时,TIM会触发NVIC中断, tim_basic 样例工程中为TIM中断实现的服务程序中,实现了通过串口发送字符 * 的操作。

最终程序运行时,可以在PC机上的串口通信终端看到以指定周期输出的字符 * ,验证定时器中断被周期触发。

tim_one_time_run

tim_one_time_run 相对于 tim_basic 样例工程实现周期触发定时器中断服务,实现了每次启动定时器后,仅触发一次中断的用法。

其实现原理,是在 tim_basic 配置定时器周期运行的基础之上,修改初始化配置 .PeriodMode 的值为 TIM_PeriodMode_OneTimeRun。之后,每次通过 TIM_Start() 函数启动定时器后,定时器仅计数一个周期后,触发中断,然后停止计数。

实际运行程序时,用户在串口调试终端中每次输入任意字符,程序均会调用一次 TIM_Start() 函数,延时指定计数周期后,在定时器中断服务程序中打印字符 * 到串口终端界面。

tim_output_compare_pwm

tim_output_compare_pwm 实现的是一个通过输出比较功能产生PWM输出信号的样例工程。

其实现原理,是在 tim_basic 基础之上,额外通过驱动函数 TIM_EnableOutputCompare(),启动并配置给定通道 BOARD_TIM_CHANNEL 为输出比较功能。其中,指定通道的配置属性 .PinPolarity 的值为 TIM_PinPolarity_Rising,.RefOutMode 值为 TIM_OutputCompareRefOut_FallingEdgeOnMatch,设定同通道绑定的硬件引脚信号在计数初始的阶段为高电平,当计数值达到通道数据寄存器中设定的匹配值时,输出下降沿信号,输出低电平。

实际运行程序时,用户通过 TIM_Init() 函数配置定时器的基本定时单元,对应的计数周期即为输出PWM信号波形的周期,启用输出比较的指定通道绑定的引脚即为输出PWM信号的引脚,通过 TIM_PutChannelValue() 函数设定输出波形在整个周期下降沿的位置,进而调整PWM输出信号波形的占空比。通道引脚在每次定时器周期的开始输出为高电平,在周期内设定的匹配值的位置产生下降沿,转而输出低电平,再计数周期结束折返为0时,恢复为高电平。如此周而复始,实现输出PWM信号波形。

tim_input_capture

tim_intput_capture 实现的是一个使用定时器为外部输入的触发信号记录时刻的样例工程。

其实现原理,是在 tim_basic 基础之上,额外通过驱动函数 TIM_EnableInputCapture(),启动并配置给定通道 BOARD_TIM_CHANNEL 为输入捕获功能。其中,指定给定通道的捕获输入信号极性 .PinPolarity 的值为 TIM_PinPolarity_Falling,表示在该给定通道绑定的引脚上出现下降沿信号时,触发捕获事件。此时,捕获计数器当前的计数值到给定通道的通道数据寄存器中,这个值就可以作为该捕获事件的时刻记录。

实际运行程序时,用户通过 TIM_Init() 函数配置定时器的基本定时单元,此时定时器的计数周期,就是可能捕获时刻值的有效范围。然后在电路上使用一个按键接入到指定通道绑定的引脚上,模拟产生下降沿触发信号。当按下按键时,触发信号到来,触发程序中的通道事件中断服务程序,在其中可以通过 TIM_GetChannelValue() 函数读取本次输入捕获事件发生时的计数时刻。

tim_external_trigger_input

相对于 tim_basic 中,使用芯片内部的时钟源脉冲进行计数,tim_external_trigger_input 样例工程可以对用户指定引脚上的脉冲进行计数,计数的脉冲来自于芯片外部的信号源。

其实现原理,是在 tim_basic 基础上,额外通过驱动函数 TIM_EnableExtTriggerIn(),配置启用外部对外部输入的脉冲信号进行计数的功能,固定从TIM外设模块的  ETR 引脚捕获来自外部的脉冲信号。每次捕获到一个脉冲信号,等同于使用芯片内部时钟源的脉冲,计数器自增计数。此时,还可以基于这个新的时钟源,使用周期计数中断等功能。

实际运行程序时,用户可以将一个按键接入到指定TIM外设模块的 ETR 引脚上,用手动按按键产生脉冲信号。在程序中指定定时器的计数周期 APP_TIM_UPDATE_PERIOD 值为2,意味着每输入两次脉冲,就会触发一次定时器周期中断。

tim_slave_mode

tim_slave_mode 实现的是一个使用从机TIM从机模式的样例工程。实际上,这里的“从机”同从属关系的的“从”是没关系的,而是可以理解为更丰富的可由用户控制的工作模式。

tim_slave_mode 工程,在 tim_basic 基础上,额外通过驱动函数 TIM_EnableSlaveMode(),配置了其中一种“从机”模式:使用 ETR 作为控制信号(下降沿)的引脚 TIM_SlaveIn_Alt7,当控制信号到来时,选择暂停计数  TIM_SlaveResp_Alt5。

实际运行程序时,用户可以将一个按键接入到指定TIM外设模块的 ETR 引脚上,用手动按按键产生电平控制信号。当按下按键时,控制定时器暂停计数,松开按键时,定时器恢复计数。正常计数到一整个周期时,会产生中断。如此,当按下按键时,会影响定时器中断的周期。

tim_slave_mode_encoder

tim_slave_mode_encoder 工程基于 tim_input_capture 工程,通过额外调用 TIM_EnableSlaveMode() 并传入一组特定的配置,启用了一种特殊的“从机”模式,从而实现了编码器的功能。

tim_comp_output_compare_pwm

tim_comp_output_compare_pwm 基于tim_output_compare_pwm 工程,通过额外的驱动函数 TIM_EnableCompOutput(),实现了PWM信号的互补输出,这意味着当使用正常的输出比较通道输出PWM信号时,还开启了硬件设计的,使用对应的另一个通道,输出电平极性刚好相反的PWM信号。

来源:灵动MM32MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 45
订阅 RSS - TIM