立创·天空星开发板-GD32F407VE-Timer

本文以 立创·天空星开发板-GD32F407VET6-青春版 作为学习的板子,记录学习笔记。

立创·天空星开发板-GD32F407VE-Timer

定时器

定时器是嵌入式系统中常用的一种外设,它可以产生一定的时间间隔、延时、定时等功能,广泛应用于定时、计数、脉冲宽度调制(PWM)等领域。

具体而言,定时器可以实现以下功能:

  1. 计时:定时器可以用来实现延时操作,例如等待外部设备的稳定、等待数据的接收等,也可以用来定时执行一些任务,例如周期性任务、定时采集数据等。
  2. 计数:定时器可以用来实现计数功能,例如计数外部事件的次数、计算脉冲信号的频率等。
  3. PWM输出:定时器可以用来产生PWM信号,通过调节占空比可以实现各种功能,例如LED调光、舵机控制等。
  4. 中断控制:定时器通常具有中断功能,可以在计数器计数到一定值时触发中断,以实现各种复杂的功能。

根据 GD32F407VE 的用户手册,定时器(TIMERx)分为五种类型,如下表所示:

可以看出所有的定时器都有预分频器,且都是 16位的,另外,除了定时器 1/4 支持 32位计数器外,其他的都是16位的计数器。

16位能表示的最大值为:2^16 - 1 = 65536 - 1 = 65535.

所以,在定时器配置的过程中,预分频器和计数器的配置都不建议超过 65535

基本定时器示例

c 复制代码
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"

#include "ExtendedUSART.h"

#define PRESCALER 16800
#define PERIOD    SystemCoreClock / PRESCALER

static void TIMER5_config() {
	// 定时器 - 时钟配置
    rcu_periph_clock_enable(RCU_TIMER5);
    timer_deinit(TIMER5);
    // 定时器 - 倍频配置
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
    // 定时器 - 参数配置
    timer_parameter_struct tps;
    timer_struct_para_init(&tps);
    tps.prescaler = PRESCALER - 1;        // 分频系数
    tps.period = PERIOD - 1;              // 周期计数
    timer_init(TIMER5, &tps);
    // 定时器 - 中断配置
    nvic_irq_enable(TIMER5_DAC_IRQn, 2, 2);
    timer_interrupt_enable(TIMER5, TIMER_INT_UP);
    timer_enable(TIMER5);
}

void TIMER5_DAC_IRQHandler(void) {
    if(SET == timer_interrupt_flag_get(TIMER5, TIMER_INT_UP)) {
		//清除中断标志位
		timer_interrupt_flag_clear(TIMER5,TIMER_INT_FLAG_UP);
		printf("timer interrupt triggered!");
    }
}

int main(void) {
    systick_config();
    USART0_config();
	TIMER5_config();
	
	printf("USART0 in GD32 is running!\r\n");
    while(1);
}

该段代码的执行效果是每隔 1s 向串口输出文本 timer interrupt triggered!,可以通过串口助手看到输出,导入的 ExtendedUSART.h 可参考之前写的 立创·天空星开发板-GD32F407VE-USART

我这里用的是基本定时器5,采用向上的计数模式,也就是自增计数,当计数值达到计数器最大值 65535 时,触发中断,自动自行中断处理函数 TIMER5_DAC_IRQHandler

最为重要的两个参数是 PRESCALERPERIOD。这两个参数的目的是为了降频。因为 GD32F407VE 的主频是 168MHz,从计数的角度来说就是 MCU 能在 1s 内计数到 168M,从某种角度来说,可以理解为 168M ≈ 1s。那分频的意义在于,我希望能让 MCU 慢下来,同样是 1s,分频系数越大,数的数字就越少。

举例来说,如果按如下配置:

c 复制代码
tps.prescaler = 16800;        // 分频系数
tps.period = 10000;           // 周期计数

不难发现,将 168MHz 按 16800 分频后,就使得原本能 1s 数数到 168M 现在 1s 只能数到 10000。

那我们就可以将数 10000 个数等价于 1s。数完就触发一次中断。如果希望半秒来一次中断,那就可以将计数周期设置为 5000。因为计数周期缩短一倍,触发时间自然缩短一半。

另外,还有一个比较重要的配置,那就是倍频。我在代码中采用的是四倍频,其函数的简介如下:

c 复制代码
/*!
    \brief    configure the TIMER clock prescaler selection
    \param[in]  timer_clock_prescaler: TIMER clock selection
                only one parameter can be selected which is shown as below:
      \arg        RCU_TIMER_PSC_MUL2: if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB)
                                      or 0b100(CK_APBx = CK_AHB/2), the TIMER clock is equal to CK_AHB(CK_TIMERx = CK_AHB).
                                      or else, the TIMER clock is twice the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 2 x CK_APB1;
                                      TIMER in APB2 domain: CK_TIMERx = 2 x CK_APB2)
      \arg        RCU_TIMER_PSC_MUL4: if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB),
                                      0b100(CK_APBx = CK_AHB/2), or 0b101(CK_APBx = CK_AHB/4), the TIMER clock is equal to CK_AHB(CK_TIMERx = CK_AHB).
                                      or else, the TIMER clock is four timers the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 4 x CK_APB1;
                                      TIMER in APB2 domain: CK_TIMERx = 4 x CK_APB2)
    \param[out] none
    \retval     none
*/
void rcu_timer_clock_prescaler_config(uint32_t timer_clock_prescaler)

可见,GD32F407VE 提供了两种倍频的配置。置于选择哪种倍频,得取决于数据手册中的功能框图。如下所示:

由图所示,Timer5 在 APB1 总线上,其最高频率是42MHz,是 AHB 总线的四分之一。这就是需要进行四倍频的原因之一。另外,还可以通过数据手册中的时钟树来判断,如下所示:

相关推荐
hopetomorrow21 分钟前
学习路之压力测试--jmeter安装教程
学习·jmeter·压力测试
hopetomorrow22 分钟前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php
/**书香门第*/1 小时前
Cocos creator 3.8 支持的动画 7
学习·游戏·游戏引擎·游戏程序·cocos2d
美式小田1 小时前
单片机学习笔记 9. 8×8LED点阵屏
笔记·单片机·嵌入式硬件·学习
兰_博1 小时前
51单片机-独立按键与数码管联动
单片机·嵌入式硬件·51单片机
猫爪笔记1 小时前
前端:HTML (学习笔记)【2】
前端·笔记·学习·html
_不会dp不改名_1 小时前
HCIA笔记3--TCP-UDP-交换机工作原理
笔记·tcp/ip·udp
时光の尘2 小时前
C语言菜鸟入门·关键字·float以及double的用法
运维·服务器·c语言·开发语言·stm32·单片机·c
-一杯为品-2 小时前
【51单片机】程序实验5&6.独立按键-矩阵按键
c语言·笔记·学习·51单片机·硬件工程
风尚云网3 小时前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网