离线
TA的每日心情 | 慵懒 2021-7-23 17:16 |
---|
签到天数: 17 天 [LV.4]
|
有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 草帽王子 于 2021-9-10 17:49 编辑
本章教程主要演示4种定时器同步模式。
1、TIM简介及相关函数介绍
定时器能够输出时钟脉冲(TRGO),也能接收其他定时器的输入(ITRx)。不同的定时器的ITRx的来源(别的定时器的TRGO)是不一样的。
所有TIMx定时器在内部相连,用于定时器同步或链接。当一个定时器处于主模式时,它可以对另一个处于从模式的定时器的计数器进行复位、启动、停止或提供时钟等操作。
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文件
- #ifndef __TIM_H
- #define __TIM_H
- #include "ch32v10x_conf.h"
- void TIM_TimSynchroMode1_Init(void);
- void TIM_TimSynchroMode2_Init(void);
- void TIM_TimSynchroMode3_Init(void);
- void TIM_TimSynchroMode4_Init(void);
- #endif
复制代码 tim.h文件主要进行相关函数声明;
tim.c文件
- #include "tim.h"
- /*******************************************************************************
- * Function Name : TIM_TimSynchroMode1_Init
- * Description : Using TIM2 as prescaler for TIM1.
- * Input : None
- * Return : None
- *******************************************************************************/
- //使用定时器2作为定时器1的预分频器
- void TIM_TimSynchroMode1_Init(void)
- {
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
- RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );
- //将TIM1和TIM2计数模式设置为向上计数模式
- TIM_CounterModeConfig( TIM1, TIM_CounterMode_Up );
- TIM_CounterModeConfig( TIM2, TIM_CounterMode_Up );
- //设置TIM1自动重装值寄存器值
- TIM_SetAutoreload( TIM1, 0x3E8 );
- //设置定时器TIM1预分频器值
- TIM_PrescalerConfig( TIM1, 48000-1, TIM_PSCReloadMode_Immediate );
- //当控制寄存器2(TIM1_CTLR2)的MMS域的值为010时,即更新事件被选为触发输入(TRGO),每当产生一个更新事件时在TRGO1上输出一个上升沿信号。
- TIM_SelectOutputTrigger( TIM1, TIM_TRGOSource_Update );
- //连接定时器1的TRGO1输出至定时器2,设置定时器2的从模式控制寄存器(TIM2_SMCFGR)的TS域值为000,即选择内部触发(ITR1)用于同步计数器的触发输入源。
- TIM_ITRxExternalClockConfig( TIM2, TIM_TS_ITR0 );
- //TIM2作为从机模式且 选中的触发输入(TRGI)的上升沿驱动计数器
- //设置定时器2的从模式控制寄存器(TIM2_SMCFGR)的SMS域值为111,即外部时钟模式 1,选中的触发输入(TRGI)的上升沿驱动计数器。这样定时器2即可由定时器1周期性的上升沿(即定时器1的计数器溢出)信号驱动。
- TIM_SelectSlaveMode( TIM2, TIM_SlaveMode_External1 );
- //使能开启TIM1和TIM2,即设置控制寄存器1(TIMx_CTLR1)的CEN位为1使能启动两个定时器。
- TIM_Cmd( TIM1, ENABLE );
- TIM_Cmd( TIM2, ENABLE );
- }
- /*******************************************************************************
- * Function Name : TIM_TimSynchroMode2_Init
- * Description : Using TIM2 to use TIM1.
- * Input : None
- * Return : None
- *******************************************************************************/
- //使用定时器2使能定时器1
- void TIM_TimSynchroMode2_Init(void)
- {
- TIM_OCInitTypeDef TIM_OCInitStructure;
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
- RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );
- TIM_CounterModeConfig( TIM1, TIM_CounterMode_Up );
- TIM_CounterModeConfig( TIM2, TIM_CounterMode_Up );
- TIM_SetAutoreload( TIM1, 0x3E8 );
- TIM_PrescalerConfig( TIM1, 48000-1, TIM_PSCReloadMode_Immediate );
- //输出比较结构体初始化
- //通过设置比较/捕获控制寄存器1(TIM1_CHCTLR1)的相应位配置定时器1的OC1REF波形
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //配置为PWM模式1
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输出使能
- TIM_OCInitStructure.TIM_Pulse = 0x64; //设置占空比大小
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出通道电平极性配置
- TIM_OC1Init( TIM1, &TIM_OCInitStructure ); //初始化
- //设置定时器1(TIM1)的控制寄存器2(TIM1_CTLR2)的MMS的值为100,即配置定时器1为主模式,其输出比较参考信号(OC1REF)被用于作为触发输出(TRGO)
- TIM_SelectOutputTrigger( TIM1, TIM_TRGOSource_OC1Ref );
- //设置从模式控制寄存器(TIM1_SMCFGR)的TS域的值为000,选择内部触发用于同步计数器的触发输入源,即配置定时器2从定时器1获得输入触发。
- TIM_SelectInputTrigger( TIM2, TIM_TS_ITR0 );
- //设置从模式控制寄存器(TIM1_SMCFGR)的SMS域的值为101,即选择选择核心计数器的时钟和触发模式为门控模式,当触发输入(TRGI)为高时,计数器的时钟开启;在触发输入变为低,计数器停止,计数器的启停都是受控的。
- TIM_SelectSlaveMode( TIM2, TIM_SlaveMode_Gated );
- //最后,设置控制寄存器1(TIMx_CTLR1)的CEN位为1使能启动两个定时器(TIM2和TIM1)。
- TIM_Cmd( TIM2, ENABLE );
- TIM_Cmd( TIM1, ENABLE );
- }
- /*******************************************************************************
- * Function Name : TIM_TimSynchroMode3_Init
- * Description : Using TIM2 to start TIM1.
- * Input : None
- * Return : None
- *******************************************************************************/
- //使用定时器2启动定时器1
- void TIM_TimSynchroMode3_Init(void)
- {
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
- RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );
- TIM_CounterModeConfig( TIM1, TIM_CounterMode_Up );
- TIM_CounterModeConfig( TIM2, TIM_CounterMode_Up );
- //通过设置自动重装值寄存器(TIM1_ATRLR)配置定时器1的周期。
- TIM_SetAutoreload( TIM1, 0xFFFF );
- TIM_PrescalerConfig( TIM1, 48000-1, TIM_PSCReloadMode_Immediate );
- //设置定时器1(TIM1)的控制寄存器2(TIM1_CTLR2)的MMS的值为010,即更新事件被选为触发输入(TRGO)。
- TIM_SelectOutputTrigger( TIM1, TIM_TRGOSource_Update );
- //通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的TS域的值为000,配置定时器2从定时器1获得输入触发。
- TIM_SelectInputTrigger( TIM2, TIM_TS_ITR0 );
- //通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的SMS域的值为110,配置定时器2为触发模式。
- TIM_SelectSlaveMode( TIM2, TIM_SlaveMode_Trigger );
- //通过设置TIM1_CTLR1寄存器的CEN位为1启动定时器1。
- TIM_Cmd( TIM1, ENABLE );
- }
- /*******************************************************************************
- * Function Name : TIM_TimSynchroMode4_Init
- * Description : Starting TIM1 and TIM2 synchronously in response to an external trigger.
- * Input : None
- * Return : None
- *******************************************************************************/
- //使用外部触发同步启动定时器1和定时器2
- void TIM_TimSynchroMode4_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- TIM_ICInitTypeDef TIM_ICInitStructure;
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );
- RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //输入下拉
- GPIO_Init( GPIOA, &GPIO_InitStructure);
- GPIO_ResetBits( GPIOA, GPIO_Pin_8 );
- TIM_CounterModeConfig( TIM1, TIM_CounterMode_Up );
- TIM_CounterModeConfig( TIM2, TIM_CounterMode_Up );
- TIM_SetAutoreload( TIM1, 0xFFFF );
- TIM_PrescalerConfig( TIM1, 48000-1, TIM_PSCReloadMode_Immediate );
- //输入捕获结构体初始化
- TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //配置输入捕获的通道,需要根据具体的GPIO来配置
- TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //输入的需要被捕获的信号的分频系数
- TIM_ICInitStructure.TIM_ICFilter = 0x00; //输入的需要被捕获的信号的滤波系数
- TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //输入捕获信号的极性配置
- TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //输入通道和捕获通道的映射关系,有直连和非直连两种
- TIM_ICInit( TIM1, &TIM_ICInitStructure ); //初始化
- //通过设置定时器1从模式控制寄存器(TIM1_SMCFGR)的TS域的值为100,配置定时器1为从模式,从TI1获得输入触发。
- TIM_SelectInputTrigger( TIM1, TIM_TS_TI1FP1 );
- //通过设置定时器1从模式控制寄存器(TIM2_SMCFGR)的SMS域的值为110,配置定时器1为触发模式。
- TIM_SelectSlaveMode( TIM1, TIM_SlaveMode_Trigger );
- //通过设置定时器1控制寄存器 2(TIM1_CTLR2)的MMS域的值为001,配置定时器1为主模式,送出它的使能做为触发输出。
- TIM_SelectMasterSlaveMode( TIM1, TIM_MasterSlaveMode_Enable );
- TIM_SelectOutputTrigger( TIM1, TIM_TRGOSource_Enable );
- //通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的TS域的值为000,配置定时器2从定时器1获得输入触发。
- TIM_SelectInputTrigger( TIM2, TIM_TS_ITR0 );
- //通过设置定时器2从模式控制寄存器(TIM2_SMCFGR)的SMS域的值为110,配置定时器2为触发模式。
- TIM_SelectSlaveMode( TIM2, TIM_SlaveMode_Trigger );
- }
复制代码 tim.c文件主要进行4种定时器同步模式的配置;
main.c文件
- int main(void)
- {
- USART_Printf_Init(115200);
- printf("SystemClk:%d\r\n",SystemCoreClock);
- /* Timer synchronization Mode Selection */
- // TIM_TimSynchroMode1_Init();
- // TIM_TimSynchroMode2_Init();
- // TIM_TimSynchroMode3_Init();
- TIM_TimSynchroMode4_Init();
- while(1)
- {
- printf("TIM1 cnt:%d\r\n", TIM1->CNT);
- printf("TIM2 cnt:%d\r\n", TIM2->CNT);
- }
- }
复制代码 main.c文件主要进行初始化以及定时器1、2的计数值的打印输出。
4、下载验证
将编译好的程序分别在4种不同模式下下载到开发版并复位,串口打印如下:
1、使用定时器2作为定时器1的预分频器;
2、使用定时器2使能定时器1;
3、使用定时器2启动定时器1;
4、使用一个外部触发同步启动定时器1和定时器2;(需使用PA8引脚进行外部触发)
58、TIM-定时器同步.rar
58、TIM-定时器同步.rar
(483.83 KB, 下载次数: 10)
链接:https://pan.baidu.com/s/19i2GdZ2oqIS14knufHfvCg
提取码:hmdv
复制这段内容后打开百度网盘手机App,操作更方便哦
完
|
上一篇: 第五十八章:TIM-定时器和外部触发的同步下一篇: 第六十章:CH32V103应用教程——TIM-DMA
|