ShadowDance 发表于 2025-8-30 11:06

沁恒CH32V317的基本定时器BasicTimer

<h1>沁恒CH32V317的基本定时器BasicTimer</h1>
<p>定时/计数器在MCU中的作用简直就是灵魂——谁能没有灵魂呢!?Timer可以用来计时,计数,保证控制精度;也可以用来周期触发,让硬件自己按周期执行;也可以用于输入捕获,或者同步外部时钟,让MCU的内部响应与外部信号同步。</p>
<p>沁恒CH32V317的Timer主要分为三大类:高级定时器(ADTM),通用定时器(GPTM)和基本定时器(BCTM)。今天先学习一下基本定时器BasicTimer。</p>
<p>基本定时器(BCTM)模块包含一个 16 位可自动重装的定时器(TIM6 和 TIM7),用于计数和在更新新事件<br />
产生中断或 DMA 请求。其主要特性是<strong>定时功能</strong>和<strong>触发DAC</strong>功能。</p>
<p>接下来我们通过一个在中断翻转GPIO的LED闪烁实验来演示TIM6基本定时器的定时计数功能。</p>
<p>与其它实验一样,我们需要首先配置MCU的时钟树。我们把沁恒CH32V317的主频提升到最高主频的144MHz。这个主频的提升其实非常简单,只需要在system_ch32v30x.c文件中的宏定义做出更新即可。</p>
<pre><code class="language-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_HSE48000000
//#define SYSCLK_FREQ_56MHz_HSE56000000
//#define SYSCLK_FREQ_72MHz_HSE72000000                /* default */
//#define SYSCLK_FREQ_96MHz_HSE96000000
//#define SYSCLK_FREQ_120MHz_HSE120000000
#define SYSCLK_FREQ_144MHz_HSE144000000
</code></pre>
<p>配置完成了主频,我们还需要了解时钟树,看看Timer6的输入时钟源是哪个?多少的频率?翻开技术手册,如下图所示:</p>
<p><img src="data/attachment/forum/202508/30/110544g7p769jso192pzqv.png" alt="CH32V317-时钟树.png" title="CH32V317-时钟树.png" /></p>
<p>从上面的时钟树可以看到,当主频144MHz时,Timer6的输入时钟最高频率为144MHz。我们本次由于仅做Timer6的实验,故在这里就直接PB1的分频系统为1,Timer6的输入时钟频率为144MHz。</p>
<p>到这里,Timer6的前置条件已经完成,我们再来看看Timer6的特性之一16位计数器。这里说是一个特性,其实主要特别考虑其16位计数的最大范围65535。如果我们直接使用16位计数,则时间周期最大仅为0.43ms。这个定时器的间隔过于频率,对MCU的整个系统来说,反倒成了负担。不过,Timer6还有一个特性参数——预分频系统。我们可以借助预分频系统再次对输入时钟进行分频,从而拓展了Timer6的总计时周期。</p>
<p><img src="data/attachment/forum/202508/30/110554t5u4s57qs09w594i.jpg" alt="CH32V317-预分频系数.jpg" title="CH32V317-预分频系数.jpg" /></p>
<p>Timer6的基本特性介绍完成,我们就尝试一下实现GPIO翻转来控制LED灯闪烁吧!我们设定本次LED灯为快闪,即100ms的翻转率。经过简单计算,我们使用psc = 36k, cnt = 400。即可得到一个周期为100ms的定时器中断了。</p>
<pre><code class="language-c">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, &amp;TIM_TimeBaseInitStructure);

      TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
      TIM_ARRPreloadConfig( TIM6, ENABLE );
      TIM_Cmd( TIM6, ENABLE );
   }
</code></pre>

复古留声机 发表于 2025-9-2 21:32

低功耗与独立性优势显著,基本定时器独立于其他外设,运行时仅消耗少量内核资源

魔法森林精灵 发表于 2025-9-3 20:44

别忘了在NVIC里把TIM6中断优先级设成1

光影捕手 发表于 2025-9-5 22:38

魔法森林精灵 发表于 2025-9-3 20:44
别忘了在NVIC里把TIM6中断优先级设成1

为什么?是一定要这么干对么,不然会怎么样

魔法森林精灵 发表于 2025-9-9 20:32

学习了,对于定时器的中断和DMA请求功能

幻想收藏家 发表于 2025-9-14 23:35

这个定时器的16位计数器特性确实需要特别注意,否则很容易超出范围

破晓战神 发表于 2025-10-10 10:39

学习了,CH32V317的基本定时器功能很强大,通过预分频和自动重装功能,可以灵活控制定时周期。
页: [1]
查看完整版本: 沁恒CH32V317的基本定时器BasicTimer