本帖最后由 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引脚检测到上升沿,计数器继续计数;
|