立创·天空星开发板-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 总线的四分之一。这就是需要进行四倍频的原因之一。另外,还可以通过数据手册中的时钟树来判断,如下所示:

相关推荐
OH五星上将1 小时前
OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【内核通信机制】上
linux·嵌入式硬件·harmonyos·openharmony·鸿蒙开发·liteos-a·鸿蒙内核
爱桥代码的程序媛1 小时前
鸿蒙OpenHarmony【轻量系统内核通信机制(互斥锁)】子系统开发
嵌入式硬件·harmonyos·鸿蒙·openharmony··鸿蒙开发·子系统开发
ImomoTo2 小时前
HarmonyOS学习(十三)——数据管理(二) 关系型数据库
数据库·学习·harmonyos·arkts·鸿蒙
开MINI的工科男4 小时前
【笔记】自动驾驶预测与决策规划_Part3_路径与轨迹规划
人工智能·笔记·自动驾驶·预测与决策
wang_book4 小时前
Gitlab学习(007 gitlab项目操作)
java·运维·git·学习·spring·gitlab
weixin_455446175 小时前
Python学习的主要知识框架
开发语言·python·学习
Ylucius7 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
LvManBa7 小时前
Vue学习记录之六(组件实战及BEM框架了解)
vue.js·学习·rust
c10638915147 小时前
STM32外设之LTDC/DMA2D—液晶显示(野火)
stm32·单片机·嵌入式硬件