打印
[RISC-V MCU 应用开发]

第五十八章、CH32V103应用教程——TIM-定时器和外部触发的...

[复制链接]
1037|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 RISCVLAR 于 2021-1-21 15:43 编辑

CH32V103应用教程——TIM-定时器和外部触发的同步

本章教程演示当TIM1_CH1(即PA8引脚)检测到上升沿时,在不同从模式下,TIM1的不同工作方式。具体如下:
复位模式:TIM1->CNT 复位重新计数
门控模式:PA8引脚输入低电平,TIM1->CNT 正常计数,否则停止计数。
触发模式:TIM1->CNT 继续计数。

1、TIM简介及相关函数介绍
定时器TIM能够在复位模式、门控模式和触发模式三种模式下和一个外部的触发同步。三种模式下和外部触发同步的具体介绍如下:

1、从模式:复位模式
在发生一个触发输入事件时,计数器和预分频器可以被重新初始化;同时,如果控制寄存器1(TIMx_CTLR1)的URS位置0,则会产生一个更新事件UEV;此外,自动重装值寄存器(TIMx_ATRLR)和比较/捕获寄存器(TIMx_CHxCVR)也会被更新。
下述配置例程中, TI1输入端的上升沿导致向上计数器被清零:
● 配置通道1检测TI1的上升沿。配置输入滤波器的带宽(本章例程不需要任何滤波器,因此设置比较/捕获控制寄存器1(TIM1_CHCTLR1)IC1F域为0000)。在触发操作中不使用捕获预分频器,因此不需要进行配置。设置比较/捕获控制寄存器1(TIM1_CHCTLR1)CC1S域值为01,只选择输入捕获源。设置比较/捕获使能寄存器中位CC1P值为0确定极性,即只检测上升沿。
● 设置从模式控制寄存器(TIM1_SMCFGR)中SMS域值为100,即选择从模式为复位模式,触发输入(TRGI)的上升沿将初始化计数器,并且产生一个更新寄存器的信号;设置从模式控制寄存器(TIM1_SMCFGR)中TS域值为101,即选择滤波后的定时器输入1(TI1FP1)用于同步计数器的触发输入源。
● 设置控制寄存器1(TIM1_CTLR1)的CEN位值为1,使能计数器。计数器开始依据内部时钟计数,然后正常运转直到TI1出现一个上升沿;此时,计数器被清零然后从0重新开始计数。同时,中断状态寄存器(TIM1_INTFR)中的TIF位被置1,即触发器事件产生,然后根据DMA/中断使能寄存器(TIM1_DMAINTENR)中的TIE位的值和TDE位的值产生一个中断请求或一个DMA请求。
下图显示当自动重装值寄存器(TIMx_ATRLR)的值为0x36时的动作。在TI1上升沿和计数器的实际复位之间的延时取决于TI1输入端的重同步电路。

2、从模式:门控模式
根据选中的输入端电平使能计数器。
在下面配置例程中,当TI1为低电平时,计数器向上计数:
● 配置通道1检测TI1的低电平。配置输入滤波器的带宽(本章例程不需要任何滤波器,因此设置比较/捕获控制寄存器1(TIM1_CHCTLR1)IC1F域为0000)。在触发操作中不使用捕获预分频器,因此不需要进行配置。设置比较/捕获控制寄存器1(TIM1_CHCTLR1)CC1S域值为01,只选择输入捕获源。设置比较/捕获使能寄存器中位CC1P值为1确定极性,即只检测低电平。
● 设置从模式控制寄存器(TIM1_SMCFGR)中SMS域值为101,即选择从模式为门控模式,当触发输入(TRGI)为高时,计数器的时钟开启;在触发输入变为低,计数器停止,计数器的启停都是受控的。设置从模式控制寄存器(TIM1_SMCFGR)中TS域值为101,即选择滤波后的定时器输入1(TI1FP1)用于同步计数器的触发输入源。
● 设置控制寄存器1(TIM1_CTLR1)的CEN位值为1,使能计数器。在门控模式下,如果CEN=0,则计数器不能启动,不论触发输入电平如何。一旦使能计数器,只要TI1为低,计数器开始依据内部时钟计数,一旦TI1变高则停止计数。当计数器开始或停止时中断状态寄存器(TIM1_INTFR)中的TIF位被置1。
TI1上升沿和计数器实际停止之间的延时取决于TI1输入端的重同步电路。

3、从模式:触发模式
根据输入端上选中的事件使能计数器。
在下面配置例程中,计数器在TI2输入的上升沿开始向上计数:
● 配置通道2检测TI2的上升沿。配置输入滤波器的带宽(本章例程不需要任何滤波器,因此设置比较/捕获控制寄存器1(TIM1_CHCTLR1)IC2F域为0000)。在触发操作中不使用捕获预分频器,因此不需要进行配置。设置比较/捕获控制寄存器1(TIM1_CHCTLR1)CC2S域值为01,只选择输入捕获源。设置比较/捕获使能寄存器中位CC2P值为1确定极性,即只检测低电平。
● 设置从模式控制寄存器(TIM1_SMCFGR)中SMS域值为110,即选择从模式为触发模式,即计数器在触发输入TRGI的上升沿启动,只有计数器的启动是受控的。设置从模式控制寄存器(TIM1_SMCFGR)中TS域值为110,即选择滤波后的定时器输入2(TI2FP2)用于同步计数器的触发输入源。当TI2出现一个上升沿时,计数器开始在内部时钟驱动下计数,同时中断状态寄存器(TIM1_INTFR)中的TIF位被置1,即触发器事件产生。
TI2上升沿和计数器启动计数之间的延时,取决于TI2输入端的重同步电路。

4、从模式:外部模式2+触发模式
外部时钟模式2可以与另一种从模式(外部时钟模式1和编码器模式除外)一起使用。此时,外部时钟引脚(ETR)信号被用作外部时钟的输入,在复位模式、门控模式或触发模式时可以选择另一个输入作为触发输入。不建议通过设置从模式控制寄存器(TIM1_SMCFGR)中TS域的值选择外部触发输入(ETRF)作为同步计数器的触发输入源。
在下面配置例程中,一旦在TI1上出现一个上升沿,计数器即在ETR的每一个上升沿向上计数一次:
1)通过设置从模式控制寄存器(TIM1_SMCFGR)配置外部触发输入电路:
─ ETF=0000:没有滤波
─ ETPS=00:不用预分频器
─ ETP=0:检测ETR的上升沿,置ECE=1使能外部时钟模式2。
2)按如下配置通道1,检测TI的上升沿:
─ 设置比较/捕获控制寄存器1(TIM1_CHCTLR1)IC1F域值为0000,即没有滤波
─ 触发操作中不使用捕获预分频器,不需要配置
─ 设置比较/捕获控制寄存器1(TIM1_CHCTLR1)中CC1S域的值为01,选择对应输入捕获源
─ 设置比较/捕获使能寄存器(TIM1_CCER)中位CC1P的值为0确定极性(只检测上升沿)
3)设置从模式控制寄存器(TIM1_SMCFGR)中SMS域值为110,即选择从模式为触发模式,即计数器在触发输入TRGI的上升沿启动,只有计数器的启动是受控的。设置从模式控制寄存器(TIM1_SMCFGR)中TS域值为101,即选择滤波后的定时器输入1(TI2FP1)用于同步计数器的触发输入源。当TI1上出现一个上升沿时,中断状态寄存器(TIM1_INTFR)中的TIF位被置1,计数器开始在ETR的上升沿计数。
ETR信号的上升沿和计数器实际复位间的延时,取决于外部触发信号(ETRP)输入端的重同步电路。

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

2、硬件设计
本章教程演示当TIM_CH1(PA8)引脚检测到上升沿时,在不同从模式下,TIM1的不同工作方式。因此需要将PA8引脚外部触发输入源所在引脚进行连接。

3软件设计
本章教程演示当TIM_CH1(PA8)引脚检测到上升沿时,在不同从模式下,TIM1的不同工作方式。具体程序如下:
tim.h文件
#ifndef __TIM_H
#define __TIM_H

#include "ch32v10x_conf.h"

/* Slave Mode Definition */
#define RESET_MODE      0
#define GATED_MODE      1
#define TRIGGER__MODE   2

/*  Slave Mode Selection */
//#define SLAVE_MODE   RESET_MODE
//#define SLAVE_MODE   GATED_MODE
#define SLAVE_MODE   TRIGGER__MODE

void TIM1_Synchro_ExtTrigger_Init( u16 arr, u16 psc );

#endif
tim.h文件主要进行相关宏定义和函数声明;
tim.c文件
#include "tim.h"

/*******************************************************************************
* Function Name  : TIM1_Synchro_ExtTrigger_Init
* Description    : Initializes TIM1 external trigger synchronization.
* Input          : arr: the period value.
*                  psc: the prescaler value.
* Return         : None
*******************************************************************************/
void TIM1_Synchro_ExtTrigger_Init( u16 arr, u16 psc )
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );

    //GPIO初始化配置
    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 );  //将PA8引脚拉低

    //时基结构体初始化配置
    TIM_TimeBaseInitStructure.TIM_Period = arr;  //设置自动重装载寄存器的值
    TIM_TimeBaseInitStructure.TIM_Prescaler = psc;  //设置定时器预分频器值
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //设置时钟分频因子,配置死区时间时需要用到
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;  //设置计数器计数模式,向上计数
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter =  0x00;  //设置重复计数器的值,没用到不用管
    TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure);  //初始化定时器

    //输入捕获结构体初始化
    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_Rising;  //配置输入捕获信号的极性
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  //设置输入通道和捕获通道的映射关系
    TIM_ICInit( TIM1, &TIM_ICInitStructure );  //定时器输入捕获初始化

    TIM_SelectInputTrigger( TIM1, TIM_TS_TI1FP1 );  //选择输入触发源

#if (SLAVE_MODE == RESET_MODE)
    TIM_SelectSlaveMode( TIM1, TIM_SlaveMode_Reset );  //复位模式

#elif (SLAVE_MODE == GATED_MODE)
    TIM_SelectSlaveMode( TIM1, TIM_SlaveMode_Gated );  //门控模式

#elif (SLAVE_MODE == TRIGGER__MODE)
    TIM_SelectSlaveMode( TIM1, TIM_SlaveMode_Trigger );  //触发模式

#endif

    TIM_SelectMasterSlaveMode( TIM1, TIM_MasterSlaveMode_Enable );  //使能开启定时器1与其从机之间的同步(通过TRGO)

#if (SLAVE_MODE != TRIGGER__MODE)
    TIM_Cmd( TIM1, ENABLE );  //使能开启TIM1

#endif
}<span style="font-family: 宋体; font-size: large; text-indent: 24pt; background-color: rgb(255, 255, 255);"> </span>
tim.c文件主要进行定时器相关初始化配置以及各种从模式的选择。其中在模式选择中,TIM_SelectSlaveMode函数主要进行对从模式的选择,TIM_SelectSlaveMode函数具体如下:
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode)
{
  TIMx->SMCFGR &= (uint16_t)~((uint16_t)TIM_SMS);
  TIMx->SMCFGR |= TIM_SlaveMode;
}
TIM_SelectSlaveMode函数主要对从模式控制寄存器(TIM1_SMCFGR)进行配置。由函数可知,首先第一步对TIM_SMS值进行取反,TIM_SMS 值为0x0007,取反之后值为0xFFF8,从模式控制寄存器&上0xFFF8之后对从模式控制寄存器(TIM1_SMCFGR)SMS域进行清0,然后根据所选择模式对SMS域进行配置。比如:当所选模式为复位模式,复位模式TIM_SlaveMode_Reset的值为0x0004,即SMS域值为100,即为复位模式,触发输入(TRGI)的上升沿将初始化计数器,并且产生一个更新寄存器的信号。其他模式与复位模式类似,在此不再介绍。
main.c文件
int main(void)
{
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n",SystemCoreClock);

    TIM1_Synchro_ExtTrigger_Init( 0xFFFF, 48000-1);

    while(1)
    {
        printf("cnt:%d\r\n", TIM1->CNT);
    }
}
main.c文件主要进行函数初始化以及打印输出计数器的值。

4下载验证
将编译好的程序下载到开发版并复位,在不同模式下,串口打印如下:
1、复位模式:当PA8引脚检测到上升沿,计数器复位重新计数;
2、门控模式:当PA8引脚输入高电平时,计数器正常计数,否则停止计数
3、触发模式:当PA8引脚检测到上升沿,计数器继续计数;

57、TIM-从模式.rar

466.54 KB

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

132

主题

293

帖子

41

粉丝