IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> GD32F4(7):GD32F4定时器使用 -> 正文阅读

[嵌入式]GD32F4(7):GD32F4定时器使用

GD32F4定时器:利用溢出中断实现定时

1. 系统环境

  • 系统:win10
  • IDE: Keil5
  • 开发板:GD32官方开发板GD32F427R-START
  • GD库版本:GD32F4xx_Firmware_Library_V3.0.0

2. 定时器描述

对于任何的外设,在使用的时候看一下时钟树都是重要的,因此对于定时器的使用,先看gd32f4的时钟树对定时器的描述如下:
在这里插入图片描述

从时钟树我们可知,定时器1、2、3、4、5、6、11、12、13是在APB1总线下面,定时器0、7、8、9、10是在APB2总线下面。

同时在时钟树下面有这样一段关于time的描述:

TIMER时钟由AHB时钟分频获得,它的频率可以等于CK_APBx、CK_APBx的两倍或CK_APBx的四倍。
详细信息请参考RCU_CFG1寄存器的TIMERSEL位。

既然如此,我们就看看RCU_CFG1寄存器的TIMERSEL位的描述:
在这里插入图片描述
在这里插入图片描述

可能你看到这一下就懵了,没关系我们先写定时器程序,边写边过来分析,就会恍然大悟。

3. 定时器程序编写

下面我们实现一个定时器溢出中断,定时器虽然有高级、普通之分,但是那是其它功能(如PWM),对于定时器溢出中断可以说没区别。因此我们就以定时器1为例来写一个定时器最简单的初始化。

void timer_init(void)
{
   
	timer_parameter_struct timer_initpara; //定时器结构体 
	rcu_periph_clock_enable(RCU_TIMER1); //开启定时器时钟
    
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);//配置定时器时钟,这个后面重点说
    
	timer_struct_para_init(&timer_initpara);//将定时器结构体内参数配置成默认参数
    timer_deinit(TIMER1); //复位定时器
    
	//配置TIMER1,时钟为200M/200/1000 = 1k
    timer_initpara.prescaler         = 200-1;//预分频
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE; //边缘对齐
    timer_initpara.counterdirection  = TIMER_COUNTER_UP; //向上计数方式
    timer_initpara.period            = 1000-1; //计数值
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0; //设置重复计数器值,0表示不重复计数,每次溢出都产生更新事件
    timer_init(TIMER1,&timer_initpara);
    
    timer_auto_reload_shadow_enable(TIMER1);//使能自动重加载
    timer_enable(TIMER1);//使能定时器    
}


下面我们分析一下函数rcu_timer_clock_prescaler_config,因为它决定了定时器的时钟究竟是多少:

rcu_timer_clock_prescaler_config有一个参数,值为RCU_TIMER_PSC_MUL2或RCU_TIMER_PSC_MUL4,我们对照时钟树详细来说一下参数的意思:
在这里插入图片描述

这个图里面有三部分被红框标识,我们暂时称之上图1、上图2和上图3,后面分析的时候会用到。

定时器的TIMERSEL寄存器:
在这里插入图片描述

看上面时钟树局部图,对于GD32F425来讲,CK_AHB最高可以配置到200M,方法请参考我的另一篇文章

因为APBx的分频器(上图1)和定时器的时钟倍频器(上图2)是耦合在一起的,定时器的时钟倍频器不可以单独设置,因此有如下情况,

当函数rcu_timer_clock_prescaler_config参数为RCU_TIMER_PSC_MUL2的时候TIMERSEL的值将被设置为0,此时:

  • 若APBx的分频系数为不分频(上图1),那么定时器倍频器(上图2)将不倍频,此时CK_TIMERx = CK_AHB,即定时器时钟就是AHB总线时钟。
  • 若APBx的分频系数为2分频(上图1),那么定时器倍频器(上图2)将进行2倍频,此时依旧CK_TIMERx = CK_AHB,即定时器时钟就是AHB总线时钟。
  • 若APBx设置的分频系数是除不分频、2分频外的其它分频(上图1),那么定时器倍频器(上图2)将进行2倍频,此时CK_TIMERx = 2 x CK_APBx,即定时器时钟就是APBx总线时钟的2倍,具体多少要看APBx的时钟。

当函数rcu_timer_clock_prescaler_config参数为RCU_TIMER_PSC_MUL4的时候TIMERSEL的值将被设置为1,此时:

  • 若APBx的分频系数为不分频(上图1),那么定时器倍频器(上图2)将不倍频,此时CK_TIMERx = CK_AHB,即定时器时钟就是AHB总线时钟。
  • 若APBx的分频系数为2分频(上图1),那么定时器倍频器(上图2)将进行2倍频,此时依旧CK_TIMERx = CK_AHB,即定时器时钟就是AHB总线时钟。
  • 若APBx的分频系数为4分频(上图1),那么定时器倍频器(上图2)将进行4倍频,此时依旧CK_TIMERx = CK_AHB,即定时器时钟就是AHB总线时钟。
  • 若APBx设置的分频系数是除不分频、2分频、4分频外的其它分频(上图1),那么定时器倍频器(上图2)将进行4倍频,此时CK_TIMERx = 4 x CK_APBx,即定时器时钟就是APBx总线时钟的4倍,具体多少要看APBx的时钟。

现在我们指导,这个定时器的时钟和APBx的分频系数相关,那么我们就看一下在时钟初始化的时候,设置情况:

system_gd32f4xx.csystem_clock_200m_25m_hxtal(void)函数里面(因为我用的是25m晶振,所以是这个函数),里面有段代码如下:

/* HXTAL is stable */
/* AHB = SYSCLK */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
/* APB2 = AHB/2 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
/* APB1 = AHB/4 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;

现在我们知道,对于我的工程APB1进行了4分频,APB2进行了2分频,那么为了保证挂在APB1总线上的timer1的输入时钟为200M,那么就要选择 rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);

基于其它的设置,就和STM32的定时器基本没有区别了,下面代码prescaler是将定时器的时钟先进行200分频,period是计数周期值为1000一个循环,如下:

timer_initpara.prescaler         = 200-1;//预分频
timer_initpara.period            = 1000-1; //计数值

4. 一个完整的代码例子

下面我们将完成一个定时器1毫秒溢出中断的程序,注意我这个的前提的APB1 = AHB/4, AHB = 200M,具体配置请看上面的描述;

//定时器初始化
void time1_init(void)
{
	
	timer_parameter_struct timer_initpara;//定时器结构体
	
	rcu_periph_clock_enable(RCU_TIMER1);//开启定时器时钟
	//因为APB1是AHB的4分频,因此定时器时钟CK_TIMERx = CK_AHB = 200m
	rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);//配置定时器时钟等于CK_AHB
	
	timer_struct_para_init(&timer_initpara);//将定时器结构体内参数配置成默认参数
    timer_deinit(TIMER1); //复位定时器
	
	/* TIMER1 configuration */
	//200M/200/1000 = 1k
    timer_initpara.prescaler         = 200-1;//预分频
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE; //边缘对齐
    timer_initpara.counterdirection  = TIMER_COUNTER_UP; //向上计数方式
    timer_initpara.period            = 1000-1; //计数值
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0; //每次溢出都产生更新是件
    timer_init(TIMER1,&timer_initpara);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER1);//使能自动重加载
	
	timer_interrupt_enable(TIMER1,TIMER_INT_UP);//使能溢出中断
	
	nvic_irq_enable(TIMER1_IRQn, 0, 1);//配置中断优先级
	
    /* TIMER1 enable */
    timer_enable(TIMER1);//使能定时器

}

//main函数
int main(void)
{
	nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);//配置优先级分组	
	timer1_init();
}

//中断函数
void TIMER1_IRQHandler(void)
{
    if(SET == timer_interrupt_flag_get(TIMER1,TIMER_INT_UP)){
        //用户代码
		/* clear TIMER interrupt flag */
		timer_interrupt_flag_clear(TIMER1,TIMER_INT_UP);
    }      
}

代码简述:

利用rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4)将定时器时钟CK_TIMERx = CK_AHB = 200m

进入定时器配置,200M首先进行200分频,然后在计数1000次触发一次中断,此时200M/200/1000 = 1k,也就是说定时器中断周期为1k,即中断时间为1ms。

若需要1秒中断只需要将上面程序中的

timer_initpara.period = 1000-1; //计数值

改为

timer_initpara.period = 1000000-1; //计数值

注意:我们都知道STM32的timer1的溢出中断是有专门的中断函数的,而GD32的timer0对标的STM32的timer1,因此GD32的timer0也有专门的溢出中断函数,而对于GD32的timer1,所有的中断共用一个TIMER1_IRQHandler函数。也有些定时器好几个定时器共用一个中断函数,在编写的时候这点要注意。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 01:27:46  更:2022-09-04 01:31:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:49:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码