沁恒CH32V317的基本定时器BasicTimer
定时/计数器在MCU中的作用简直就是灵魂——谁能没有灵魂呢!?Timer可以用来计时,计数,保证控制精度;也可以用来周期触发,让硬件自己按周期执行;也可以用于输入捕获,或者同步外部时钟,让MCU的内部响应与外部信号同步。
沁恒CH32V317的Timer主要分为三大类:高级定时器(ADTM),通用定时器(GPTM)和基本定时器(BCTM)。今天先学习一下基本定时器BasicTimer。
基本定时器(BCTM)模块包含一个 16 位可自动重装的定时器(TIM6 和 TIM7),用于计数和在更新新事件
产生中断或 DMA 请求。其主要特性是定时功能和触发DAC功能。
接下来我们通过一个在中断翻转GPIO的LED闪烁实验来演示TIM6基本定时器的定时计数功能。
与其它实验一样,我们需要首先配置MCU的时钟树。我们把沁恒CH32V317的主频提升到最高主频的144MHz。这个主频的提升其实非常简单,只需要在system_ch32v30x.c文件中的宏定义做出更新即可。
/*
* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
* reset the HSI is used as SYSCLK source).
* If none of the define below is enabled, the HSI is used as System clock source.
*/
//#define SYSCLK_FREQ_HSE HSE_VALUE
//#define SYSCLK_FREQ_48MHz_HSE 48000000
//#define SYSCLK_FREQ_56MHz_HSE 56000000
//#define SYSCLK_FREQ_72MHz_HSE 72000000 /* default */
//#define SYSCLK_FREQ_96MHz_HSE 96000000
//#define SYSCLK_FREQ_120MHz_HSE 120000000
#define SYSCLK_FREQ_144MHz_HSE 144000000
配置完成了主频,我们还需要了解时钟树,看看Timer6的输入时钟源是哪个?多少的频率?翻开技术手册,如下图所示:

从上面的时钟树可以看到,当主频144MHz时,Timer6的输入时钟最高频率为144MHz。我们本次由于仅做Timer6的实验,故在这里就直接PB1的分频系统为1,Timer6的输入时钟频率为144MHz。
到这里,Timer6的前置条件已经完成,我们再来看看Timer6的特性之一16位计数器。这里说是一个特性,其实主要特别考虑其16位计数的最大范围65535。如果我们直接使用16位计数,则时间周期最大仅为0.43ms。这个定时器的间隔过于频率,对MCU的整个系统来说,反倒成了负担。不过,Timer6还有一个特性参数——预分频系统。我们可以借助预分频系统再次对输入时钟进行分频,从而拓展了Timer6的总计时周期。

Timer6的基本特性介绍完成,我们就尝试一下实现GPIO翻转来控制LED灯闪烁吧!我们设定本次LED灯为快闪,即100ms的翻转率。经过简单计算,我们使用psc = 36k, cnt = 400。即可得到一个周期为100ms的定时器中断了。
void TIM6_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM6, ENABLE );
TIM_TimeBaseInitStructure.TIM_Period = 400 -1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 36000 - 1;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Down;
TIM_TimeBaseInit( TIM6, &TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
TIM_ARRPreloadConfig( TIM6, ENABLE );
TIM_Cmd( TIM6, ENABLE );
}