查看: 1209|回复: 0
收起左侧

第五十九章:CH32V103应用教程——TIM-定时器同步

[复制链接]

  离线 

  • TA的每日心情
    慵懒
    2021-7-23 17:16
  • 签到天数: 17 天

    [LV.4]

    发表于 2021-4-30 12:55:29 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 草帽王子 于 2021-9-10 17:49 编辑

    本章教程主要演示4种定时器同步模式。


    1、TIM简介及相关函数介绍

    定时器能够输出时钟脉冲(TRGO),也能接收其他定时器的输入(ITRx)。不同的定时器的ITRx的来源(别的定时器的TRGO)是不一样的。
    所有TIMx定时器在内部相连,用于定时器同步或链接。当一个定时器处于主模式时,它可以对另一个处于从模式的定时器的计数器进行复位、启动、停止或提供时钟等操作。

    1、使用一个定时器作为另一个定时器的预分频器
    CH32V CH573单片机芯片-第五十九章:CH32V103应用教程——TIM-定时器同步risc-v单片机中文社区(1)
    如上图:可以配置定时器1作为定时器2的预分频器。进行下述操作:

    ● 配置定时器1(TIM1)为主模式,它可以在每一个更新事件UEV时输出一个周期性的触发信号。当控制寄存器2(TIM1_CTLR2)的MMS域的值为010时,即更新事件被选为触发输入(TRGO),每当产生一个更新事件时在TRGO1上输出一个上升沿信号。
    ● 连接定时器1的TRGO1输出至定时器2,设置定时器2的从模式控制寄存器(TIM2_SMCFGR)的TS域值为000,即选择内部触发(ITR1)用于同步计数器的触发输入源。
    ● 设置定时器2的从模式控制寄存器(TIM2_SMCFGR)的SMS域值为111,即外部时钟模式 1,选中的触发输入(TRGI)的上升沿驱动计数器。这样定时器2即可由定时器1周期性的上升沿(即定时器1的计数器溢出)信号驱动。
    ● 最后,设置控制寄存器1(TIMx_CTLR1)的CEN位为1使能启动两个定时器。
    注:如果OCx已被选中为定时器1的触发输出(MMS=1xx),它的上升沿用于驱动定时器2的计数器。

    2、使用一个定时器使能另一个定时器
    当使用一个定时器使能另一个定时器时,定时器2的使能由定时器1的输出比较控制。参考第一种配置定时器1和定时器2的连接方式。只当定时器1的OC1REF(输出参考信号)为高时,定时器2才对分频后的内部时钟计数。两个定时器的时钟频率都是由预分频器对定时器时钟(CK_INT)除以3(fCK_CNT=fCK_INT/3)得到。

    ● 设置定时器1(TIM1)的控制寄存器2(TIM1_CTLR2)的MMS的值为100,即配置定时器1为主模式,其输出比较参考信号(OC1REF)被用于作为触发输出(TRGO)
    ● 通过设置比较/捕获控制寄存器1(TIM1_CHCTLR1)的相应位配置定时器1的OC1REF波形
    ●设置从模式控制寄存器(TIM1_SMCFGR)的TS域的值为000,选择内部触发用于同步计数器的触发输入源,即配置定时器2从定时器1获得输入触发。
    ● 设置从模式控制寄存器(TIM1_SMCFGR)的SMS域的值为101,即选择选择核心计数器的时钟和触发模式为门控模式,当触发输入(TRGI)为高时,计数器的时钟开启;在触发输入变为低,计数器停止,计数器的启停都是受控的。
    ● 最后,设置控制寄存器1(TIMx_CTLR1)的CEN位为1使能启动两个定时器(TIM2和TIM1)。
    注:定时器2的时钟不与定时器1的时钟同步,这个模式只影响定时器2计数器的使能信号。

    在上述配置中,在定时器2启动之前,它们的计数器和预分频器未被初始化,因此它们从当前的数值开始计数。可以在启动定时器1之前复位2个定时器,使它们从给定的数值开始,即在定时器计数器中写入需要的任意数值。通过设置事件产生寄存器(TIM1_SWEVGR) 的UG位为1即可复位定时器。

    在下述配置中,需要同步定时器1和定时器2。定时器1是主模式并从0开始,定时器2是从模式并从0xE7开始;2个定时器的预分频器系数相同。设置控制寄存器 1(TIM1_CTLR1) 的CEN位为0,即可禁止定时器1,定时器2随即停止。

    ●设置定时器1(TIM1)的控制寄存器2(TIM1_CTLR2)的MMS域的值为100,即配置定时器1为主模式,其输出比较参考信号(OC1REF)被用于作为触发输出(TRGO)
    ● 通过设置比较/捕获控制寄存器1(TIM1_CHCTLR1)的相应位配置定时器1的OC1REF波形
    ●设置从模式控制寄存器(TIM1_SMCFGR)的TS域的值为000,选择内部触发用于同步计数器的触发输入源,即配置定时器2从定时器1获得输入触发。
    ● 设置从模式控制寄存器(TIM1_SMCFGR)的SMS域的值为101,即选择选择核心计数器的时钟和触发模式为门控模式,当触发输入(TRGI)为高时,计数器的时钟开启;在触发输入变为低,计数器停止,计数器的启停都是受控的。
    ●设置事件产生寄存器(TIM1_SWEVGR和TIM2_SWEVGR)的UG位的值为1,复位定时器1和定时器2。
    ● 写’0xE7’至定时器2计数器(TIM2_CNT),初始化它为0xE7。
    ● 设置控制寄存器1(TIMx_CTLR1)的CEN位为1使能启动两个定时器(TIM1和TIM2)。
    ●设置定时器1控制寄存器1(TIM1_CTLR1)的CEN位为0停止定时器1

    3、使用一个定时器去启动另一个定时器
    当使用一个定时器去启动另一个定时器时,可以使用定时器1的更新事件使能定时器2。参考第一种配置定时器1和定时器2的连接方式。一旦定时器1产生更新事件,定时器2即从它当前的数值(可以是非0)按照分频的内部时钟开始计数。在收到触发信号时,定时器2的控制寄存器1(TIM2_CTLR1)的CEN位被置1,同时计数器开始计数一直到控制寄存器1(TIM2_CTLR1)的CEN位被置0.

    两个定时器的时钟频率都是由预分频器对CK_INT除以3(fCK_CNT=fCK_INT/3)。
    ● 设置定时器1(TIM1)的控制寄存器2(TIM1_CTLR2)的MMS的值为010,即更新事件被选为触发输入(TRGO)。
    ● 通过设置自动重装值寄存器(TIM1_ATRLR)配置定时器1的周期。
    ● 通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的TS域的值为000,配置定时器2从定时器1获得输入触发。
    ● 通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的SMS域的值为110,配置定时器2为触发模式。
    ● 通过设置TIM1_CTLR1寄存器的CEN位为1启动定时器1。

    4、使用一个定时器作为另一个的预分频器
    本次配置讲述使用定时器1作为定时器2的预分频器。参考第一种配置定时器1和定时器2的连接方式。配置流程如下:

    ● 设置定时器1控制寄存器 2(TIM1_CTLR2)的MMS域的值为010,更新事件被选为触发输入(TRGO)。配置定时器1为主模式,送出它的更新事件UEV做为触发输出。然后每次计数器溢出时输出一个周期信号。
    ● 通过设置定时器1自动重装值寄存器(TIM1_ATRLR)配置定时器1的周期。
    ● 通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的TS域的值为000,配置定时器2从定时器1获得输入触发。
    ● 通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的SMS域的值为111,配置定时器2使用外部时钟模式。
    ● 设置定时器2和定时器1控制寄存器1(TIMx_CTLR1)寄存器的CEN位为1启动定时器2和定时器1。

    5、使用一个外部触发同步启动2个定时器
    在使用一个外部触发同步启动2个定时器时,当定时器1的TI1输入上升时使能定时器1,使能定时器1的同时使能定时器2,参考第一种配置定时器1和定时器2的连接方式。为保证计数器的对齐,定时器1必须配置为主/从模式(对应TI1为从,对应定时器2为主):

    ● 通过设置定时器1控制寄存器 2(TIM1_CTLR2)的MMS域的值为001,配置定时器1为主模式,送出它的使能做为触发输出。
    ● 通过设置定时器1从模式控制寄存器(TIM1_SMCFGR)的TS域的值为100,
    配置定时器1为从模式,从TI1获得输入触发。
    ● 通过设置定时器1从模式控制寄存器(TIM2_SMCFGR)的SMS域的值为110,配置定时器1为触发模式。
    ● 通过设置定时器1从模式控制寄存器(TIM1_SMCFGR)的MSM位的值为1,配置定时器1为主/从模式。
    ● 通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的TS域的值为000,配置定时器2从定时器1获得输入触发。
    ● 通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的SMS域的值为110,配置定时器2为触发模式。

    当定时器1的TI1上出现一个上升沿时,两个定时器同步地按照内部时钟开始计数,两个TIF标志也同时被设置。

    注: 在上述配置中,在启动之前两个定时器都通过设置事件产生寄存器(TIM1_SWEVGR) 的UG位进行初始化,两个计数器都从0开始,但可以通过写入任意一个计数器寄存器(TIMx_CNT)在定时器间插入一个偏移。

    关于CH32V103 TIM具体信息,可参考CH32V103应用手册。TIM标准库函数在第七章节已介绍,在此不再赘述。


    2、硬件设计

    本章教程主要演示4种定时器同步模式,其中使用一个外部触发同步启动定时器1和定时器2时,需使用PA8引脚进行外部触发。


    3、软件设计

    本章教程主要演示4种定时器同步模式,具体程序如下:
    tim.h文件
    1. #ifndef __TIM_H
    2. #define __TIM_H

    3. #include "ch32v10x_conf.h"

    4. void TIM_TimSynchroMode1_Init(void);
    5. void TIM_TimSynchroMode2_Init(void);
    6. void TIM_TimSynchroMode3_Init(void);
    7. void TIM_TimSynchroMode4_Init(void);

    8. #endif
    复制代码
    tim.h文件主要进行相关函数声明;
    tim.c文件
    1. #include "tim.h"

    2. /*******************************************************************************
    3. * Function Name  : TIM_TimSynchroMode1_Init
    4. * Description    : Using TIM2 as prescaler for TIM1.
    5. * Input          : None
    6. * Return         : None
    7. *******************************************************************************/
    8. //使用定时器2作为定时器1的预分频器
    9. void TIM_TimSynchroMode1_Init(void)
    10. {
    11.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
    12.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );

    13.     //将TIM1和TIM2计数模式设置为向上计数模式
    14.     TIM_CounterModeConfig( TIM1, TIM_CounterMode_Up );
    15.     TIM_CounterModeConfig( TIM2, TIM_CounterMode_Up );

    16.     //设置TIM1自动重装值寄存器值
    17.     TIM_SetAutoreload( TIM1, 0x3E8 );

    18.     //设置定时器TIM1预分频器值
    19.     TIM_PrescalerConfig( TIM1, 48000-1, TIM_PSCReloadMode_Immediate );

    20.     //当控制寄存器2(TIM1_CTLR2)的MMS域的值为010时,即更新事件被选为触发输入(TRGO),每当产生一个更新事件时在TRGO1上输出一个上升沿信号。
    21.     TIM_SelectOutputTrigger( TIM1, TIM_TRGOSource_Update );

    22.     //连接定时器1的TRGO1输出至定时器2,设置定时器2的从模式控制寄存器(TIM2_SMCFGR)的TS域值为000,即选择内部触发(ITR1)用于同步计数器的触发输入源。
    23.     TIM_ITRxExternalClockConfig( TIM2, TIM_TS_ITR0 );

    24.     //TIM2作为从机模式且 选中的触发输入(TRGI)的上升沿驱动计数器
    25.     //设置定时器2的从模式控制寄存器(TIM2_SMCFGR)的SMS域值为111,即外部时钟模式 1,选中的触发输入(TRGI)的上升沿驱动计数器。这样定时器2即可由定时器1周期性的上升沿(即定时器1的计数器溢出)信号驱动。
    26.     TIM_SelectSlaveMode( TIM2, TIM_SlaveMode_External1 );

    27.     //使能开启TIM1和TIM2,即设置控制寄存器1(TIMx_CTLR1)的CEN位为1使能启动两个定时器。
    28.     TIM_Cmd( TIM1, ENABLE );
    29.     TIM_Cmd( TIM2, ENABLE );
    30. }

    31. /*******************************************************************************
    32. * Function Name  : TIM_TimSynchroMode2_Init
    33. * Description    : Using TIM2 to use TIM1.
    34. * Input          : None
    35. * Return         : None
    36. *******************************************************************************/
    37. //使用定时器2使能定时器1
    38. void TIM_TimSynchroMode2_Init(void)
    39. {
    40.     TIM_OCInitTypeDef TIM_OCInitStructure;

    41.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
    42.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );

    43.     TIM_CounterModeConfig( TIM1, TIM_CounterMode_Up );
    44.     TIM_CounterModeConfig( TIM2, TIM_CounterMode_Up );
    45.     TIM_SetAutoreload( TIM1, 0x3E8 );
    46.     TIM_PrescalerConfig( TIM1, 48000-1, TIM_PSCReloadMode_Immediate );

    47.     //输出比较结构体初始化
    48.     //通过设置比较/捕获控制寄存器1(TIM1_CHCTLR1)的相应位配置定时器1的OC1REF波形
    49.     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;  //配置为PWM模式1
    50.     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  //输出使能
    51.     TIM_OCInitStructure.TIM_Pulse = 0x64;  //设置占空比大小
    52.     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //输出通道电平极性配置
    53.     TIM_OC1Init( TIM1, &TIM_OCInitStructure );  //初始化

    54.     //设置定时器1(TIM1)的控制寄存器2(TIM1_CTLR2)的MMS的值为100,即配置定时器1为主模式,其输出比较参考信号(OC1REF)被用于作为触发输出(TRGO)
    55.     TIM_SelectOutputTrigger( TIM1, TIM_TRGOSource_OC1Ref );

    56.     //设置从模式控制寄存器(TIM1_SMCFGR)的TS域的值为000,选择内部触发用于同步计数器的触发输入源,即配置定时器2从定时器1获得输入触发。
    57.     TIM_SelectInputTrigger( TIM2, TIM_TS_ITR0 );

    58.     //设置从模式控制寄存器(TIM1_SMCFGR)的SMS域的值为101,即选择选择核心计数器的时钟和触发模式为门控模式,当触发输入(TRGI)为高时,计数器的时钟开启;在触发输入变为低,计数器停止,计数器的启停都是受控的。
    59.     TIM_SelectSlaveMode( TIM2, TIM_SlaveMode_Gated );

    60.     //最后,设置控制寄存器1(TIMx_CTLR1)的CEN位为1使能启动两个定时器(TIM2和TIM1)。
    61.     TIM_Cmd( TIM2, ENABLE );
    62.     TIM_Cmd( TIM1, ENABLE );
    63. }

    64. /*******************************************************************************
    65. * Function Name  : TIM_TimSynchroMode3_Init
    66. * Description    : Using TIM2 to start TIM1.
    67. * Input          : None
    68. * Return         : None
    69. *******************************************************************************/
    70. //使用定时器2启动定时器1
    71. void TIM_TimSynchroMode3_Init(void)
    72. {
    73.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
    74.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );

    75.     TIM_CounterModeConfig( TIM1, TIM_CounterMode_Up );
    76.     TIM_CounterModeConfig( TIM2, TIM_CounterMode_Up );

    77.     //通过设置自动重装值寄存器(TIM1_ATRLR)配置定时器1的周期。
    78.     TIM_SetAutoreload( TIM1, 0xFFFF );
    79.     TIM_PrescalerConfig( TIM1, 48000-1, TIM_PSCReloadMode_Immediate );

    80.     //设置定时器1(TIM1)的控制寄存器2(TIM1_CTLR2)的MMS的值为010,即更新事件被选为触发输入(TRGO)。
    81.     TIM_SelectOutputTrigger( TIM1, TIM_TRGOSource_Update );

    82.     //通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的TS域的值为000,配置定时器2从定时器1获得输入触发。
    83.     TIM_SelectInputTrigger( TIM2, TIM_TS_ITR0 );

    84.     //通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的SMS域的值为110,配置定时器2为触发模式。
    85.     TIM_SelectSlaveMode( TIM2, TIM_SlaveMode_Trigger );

    86.     //通过设置TIM1_CTLR1寄存器的CEN位为1启动定时器1。
    87.     TIM_Cmd( TIM1, ENABLE );
    88. }

    89. /*******************************************************************************
    90. * Function Name  : TIM_TimSynchroMode4_Init
    91. * Description    : Starting TIM1 and TIM2 synchronously in response to an external trigger.
    92. * Input          : None
    93. * Return         : None
    94. *******************************************************************************/
    95. //使用外部触发同步启动定时器1和定时器2
    96. void TIM_TimSynchroMode4_Init(void)
    97. {
    98.     GPIO_InitTypeDef GPIO_InitStructure;
    99.     TIM_ICInitTypeDef TIM_ICInitStructure;

    100.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );
    101.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );

    102.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    103.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;  //输入下拉
    104.     GPIO_Init( GPIOA, &GPIO_InitStructure);
    105.     GPIO_ResetBits( GPIOA, GPIO_Pin_8 );

    106.     TIM_CounterModeConfig( TIM1, TIM_CounterMode_Up );
    107.     TIM_CounterModeConfig( TIM2, TIM_CounterMode_Up );
    108.     TIM_SetAutoreload( TIM1, 0xFFFF );
    109.     TIM_PrescalerConfig( TIM1, 48000-1, TIM_PSCReloadMode_Immediate );

    110.     //输入捕获结构体初始化
    111.     TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;  //配置输入捕获的通道,需要根据具体的GPIO来配置
    112.     TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  //输入的需要被捕获的信号的分频系数
    113.     TIM_ICInitStructure.TIM_ICFilter = 0x00;  //输入的需要被捕获的信号的滤波系数
    114.     TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;  //输入捕获信号的极性配置
    115.     TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  //输入通道和捕获通道的映射关系,有直连和非直连两种
    116.     TIM_ICInit( TIM1, &TIM_ICInitStructure );  //初始化

    117.     //通过设置定时器1从模式控制寄存器(TIM1_SMCFGR)的TS域的值为100,配置定时器1为从模式,从TI1获得输入触发。
    118.     TIM_SelectInputTrigger( TIM1, TIM_TS_TI1FP1 );

    119.     //通过设置定时器1从模式控制寄存器(TIM2_SMCFGR)的SMS域的值为110,配置定时器1为触发模式。
    120.     TIM_SelectSlaveMode( TIM1, TIM_SlaveMode_Trigger );

    121.     //通过设置定时器1控制寄存器 2(TIM1_CTLR2)的MMS域的值为001,配置定时器1为主模式,送出它的使能做为触发输出。
    122.     TIM_SelectMasterSlaveMode( TIM1, TIM_MasterSlaveMode_Enable );
    123.     TIM_SelectOutputTrigger( TIM1, TIM_TRGOSource_Enable );

    124.     //通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的TS域的值为000,配置定时器2从定时器1获得输入触发。
    125.     TIM_SelectInputTrigger( TIM2, TIM_TS_ITR0 );

    126.     //通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的SMS域的值为110,配置定时器2为触发模式。
    127.     TIM_SelectSlaveMode( TIM2, TIM_SlaveMode_Trigger );
    128. }

    复制代码
    tim.c文件主要进行4种定时器同步模式的配置;
    main.c文件
    1. int main(void)
    2. {
    3.     USART_Printf_Init(115200);
    4.     printf("SystemClk:%d\r\n",SystemCoreClock);

    5. /* Timer synchronization Mode Selection */
    6. //  TIM_TimSynchroMode1_Init();
    7. //  TIM_TimSynchroMode2_Init();
    8. //  TIM_TimSynchroMode3_Init();
    9.   TIM_TimSynchroMode4_Init();

    10.     while(1)
    11.     {
    12.         printf("TIM1 cnt:%d\r\n", TIM1->CNT);
    13.         printf("TIM2 cnt:%d\r\n", TIM2->CNT);
    14.     }
    15. }
    复制代码
    main.c文件主要进行初始化以及定时器1、2的计数值的打印输出。


    4、下载验证

    将编译好的程序分别在4种不同模式下下载到开发版并复位,串口打印如下:
    1、使用定时器2作为定时器1的预分频器;
    CH32V CH573单片机芯片-第五十九章:CH32V103应用教程——TIM-定时器同步risc-v单片机中文社区(2)
    2、使用定时器2使能定时器1;
    CH32V CH573单片机芯片-第五十九章:CH32V103应用教程——TIM-定时器同步risc-v单片机中文社区(3)
    3、使用定时器2启动定时器1;
    CH32V CH573单片机芯片-第五十九章:CH32V103应用教程——TIM-定时器同步risc-v单片机中文社区(4)
    4、使用一个外部触发同步启动定时器1和定时器2;(需使用PA8引脚进行外部触发)
    CH32V CH573单片机芯片-第五十九章:CH32V103应用教程——TIM-定时器同步risc-v单片机中文社区(5)

    58、TIM-定时器同步.rar
    CH32V CH573单片机芯片-第五十九章:CH32V103应用教程——TIM-定时器同步risc-v单片机中文社区(6) 58、TIM-定时器同步.rar (483.83 KB, 下载次数: 10)
    链接:https://pan.baidu.com/s/19i2GdZ2oqIS14knufHfvCg
    提取码:hmdv
    复制这段内容后打开百度网盘手机App,操作更方便哦







    上一篇:第五十八章:TIM-定时器和外部触发的同步
    下一篇:第六十章:CH32V103应用教程——TIM-DMA
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-4-25 08:50 , Processed in 2.063149 second(s), 48 queries .

    快速回复 返回顶部 返回列表