四、GD32 MCU 常见外设介绍 (5) TIMER 模块介绍

 5.1.TIMER 基础知识

TIMER分高级定时器,通用定时器L0,L1,L2和基本定时器。

5.2.硬件连接说明

TIMER 属于片内外设,对于外部硬件设计,只需要单独IO口外接信号线即可。

5.3.GD32 TIMER 外设原理简介(以 GD32F30X 的高级定时器为例)

GD32 TIMER 主要特性

◼ 总通道数: 4;

◼ 计数器宽度: 16位;

◼ 定时器时钟源可选:内部时钟,内部触发,外部输入,外部触发;

◼ 多种计数模式:向上计数,向下计数和中央计数;

◼ 正交编码器接口:用来追踪运动和分辨旋转方向和位置;

◼ 霍尔传感器接口:用来做三相电机控制;

◼ 可编程的预分频器: 16位。运行时可以被改变;

◼ 每个通道可配置:输入捕获模式,输出比较模式,可编程的PWM模式,单脉冲模式;

◼ 可编程的死区时间;

◼ 自动重装载功能;

◼ 可编程的计数器重复功能;

◼ 中止输入功能;

◼ 中断输出和DMA请求:更新事件,触发事件,比较/捕获事件和中止事件;

◼ 多个定时器的菊链使得一个定时器可以同时启动多个定时器;

◼ 定时器的同步允许被选择的定时器在同一个时钟周期开始计数;

◼ 定时器主/从模式控制器。

TIMER 结构框图介绍

5.4.软件配置说明

定时中断 TIMER4

通用定时器L0(TIMER1/2/3/4) 是4通道定时器,支持输入捕获,输出比较,产生PWM信号控制电机和电源管理。通用定时器L0计数器是16位无符号计数器。通用定时器L0是可编程的,可以被用来计数,其外部事件可以驱动其他定时器。

这一章,将使用定时器产生中断,然后在中断服务函数里面翻转 LED上的电平,来指示定时器中断的产生。接下来我们以通用定时器 TIMER4 为实例,来说明要经过哪些步骤,才能达到这个要 求,并产生中断。定时器配置步骤如下:

1)TIMER4 时钟使能

rcu_periph_clock_enable(RCU_TIMER4);

2) 初始化定时器参数,设置自动重装值,分频系数,计数方式等

在库函数中,定时器的初始化参数是通过初始化函数timer_parameter_struct 实现的:

void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara);

第一个参数是确定是哪个定时器,这个比较容易理解。第二个参数是定时器初始化参数结构体指针,结构体类型为timer_parameter_struct ,下面我们看看这个结构体的定义:

/* TIMER init parameter struct definitions */
typedef struct
{ uint16_t prescaler; /*!< prescaler value */uint16_t alignedmode; /*!< aligned mode */uint16_t counterdirection; /*!< counter direction */uint32_t period; /*!< period value */uint16_t clockdivision; /*!< clock division value */uint8_t repetitioncounter; /*!< the counter repetition value */
}timer_parameter_struct;

针对 TIMR4 初始化范例代码格式

 timer_initpara.prescaler = 5999; //30M/6000 =500Hztimer_initpara.alignedmode = TIMER_COUNTER_EDGE;timer_initpara.counterdirection = TIMER_COUNTER_UP;timer_initpara.period = 4000-1; //800mstimer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_init(TIMER4, &timer_initpara);

对于定时器定时周期的计算,设 TIMER4 的经过总线分频后得到的时钟为 30MHz,通过预分频 5999,得到 TIMER4 每个计 数的时钟为 1/(30MHz / (5999+1)) =0.2ms,4000 得到的周期为 0.2ms *4000 =800ms

3)设置 TIMER 允许更新中断

因为我们要使用 TIMER4 的更新中断,寄存器的相应位便可使能更新中断。在库函数里面定时器中断使能是通过timer_interrupt_enable函数来实现的:

void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt);

第一个参数是选择定时器号,这个容易理解。

第二个参数非常关键,是用来指明我们使能的定时器中断的类型。

4) TIMER4 中断优先级设置

在定时器中断使能之后,因为要产生中断,必不可少的要设置 NVIC 相关寄存器,设置中断优先级。通过nvic_irq_enable 函数实现中断优先级的设置。

针对 TIMR4 初始化范例代码格式

nvic_irq_enable(TIMER4_IRQn, 1, 1);

 5)允许 TIMER工作,也就是使能 TIMER

光配置好定时器还不行,没有开启定时器,照样不能用。我们在配置完后要开启定时器,在固件库里面使能定时器的函数是通过timer_enable函数来实现的

void timer_enable(uint32_t timer_periph)

这个函数非常简单,比如我们要使能TIMER4,方法为:

timer_enable(TIMER4);

6)编写中断服务函数

在最后,还是要编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,我们这里使用的是更新(溢出)中断,在处理完中断之后应来清除该中断标志。

在固件库函数里面,用来读取中断状态寄存器的值判断中断类型的函数是:

FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt)

该函数的作用是,判断定时器 TIMER 的中断类型,并判断是否发生中断。

针对 TIMR4 中断服务函数范例代码:

void TIMER4_IRQHandler(void)
{if(SET == timer_interrupt_flag_get(TIMER4, TIMER_INT_UP)){/* clear channel 0 interrupt bit */timer_interrupt_flag_clear(TIMER4, TIMER_INT_UP);gd_eval_led_toggle(LED2);}
}

PWM 输出 TIMER0

高级定时器(TIMER0和TIMER7)是四通道定时器,支持输入捕获和输出比较。可以产生PWM信号控制电机和电源管理。高级定时器含有一个16位无符号计数器。高级定时器是可编程的,可以用来计数,其外部事件可以驱动其他定时器。高级定时器包含了一个死区时间插入模块,非常适合电机控制。

本章,我们使用的是 TIMER0的通道0 输出 PWM(脉冲宽度调制)。

下面我们介绍通过库函数来配置该功能的步骤:

(1)开启 TIMER0 和 GPIO 时钟,配置 PA8复用功能输出。

rcu_periph_clock_enable(RCU_TIMER0);
rcu_periph_clock_enable(RCU_GPIOA);
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);

这里还需要说明一下, 对于定时器通道的引脚关系,引脚的IO口

这里补充说明下关于TIMER的相关GPIO口的命名

TIMERx_CHx : 定时器通道x

TIMERx_CHx_ON :定时器反向通道

TIMERx_BRKIN :刹车引脚

TIMERx_ETI:外部时钟输入

(2)初始化 TIMER0 ,设置 TIMER0 的预分频和周期等参数, ,在上一节定时器中断章节我们已经有讲解,这里就不详细讲解,调用的格式为

timer_initpara.prescaler = 5999;timer_initpara.alignedmode = TIMER_COUNTER_EDGE;timer_initpara.counterdirection = TIMER_COUNTER_UP;timer_initpara.period = 4000;timer_initpara.clockdivision = TIMER_CKDIV_DIV1;timer_initpara.repetitioncounter = 0;
timer_init(TIMER0, &timer_initpara);

3)设置 TIMER0_CH0 的 PWM 模式, 使能 TIMER0 的 CH0 输出。 在库函数中, PWM 通道设置是通过函数timer_channel_output_config来设置的

void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara)

我们直接来看看结构体timer_oc_parameter_struct的定义:

typedef struct
{ uint16_t outputstate; /*!< channel output state */uint16_t outputnstate; /*!< channel complementary output state */uint16_t ocpolarity; /*!< channel output polarity */uint16_t ocnpolarity; /*!< channel complementary output polarity */uint16_t ocidlestate; /*!< idle state of channel output */uint16_t ocnidlestate; /*!< idle state of channel complementary output */
}timer_oc_parameter_struct;

 针对 TIMR0 CH0 初始化范例代码格式

/* CH0, CH1 and CH2 configuration in PWM mode */timer_ocinitpara.outputstate = TIMER_CCX_ENABLE;timer_ocinitpara.outputnstate = TIMER_CCXN_DISABLE;timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH;timer_ocinitpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;timer_ocinitpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;timer_ocinitpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocinitpara);

4)设置PWM输出以及脉冲宽度占空比

timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 2000);timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0);timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);timer_primary_output_config(TIMER0,ENABLE);

5)使能 TIMER0

在完成以上设置了之后,我们需要使能 TIMER0。使能 TIMER0 的方法前面已经讲解过:

timer_enable(TIMER0);

通过以上 5 个步骤,我们就可以控制 TIMER0的 CH0 输出 PWM 波了。这里特别提醒一下大家,高级定时器虽然和通用定时器类似,但是高级定时器要想输出 PWM,必须多额外加一条函数

void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue);

输入捕获 TIMER2

通用定时器L0(TIMER1/2/3/4) 是4通道定时器,支持输入捕获,输出比较,产生PWM信号控制电机和电源管理。通用定时器L0计数器是16位无符号计数器。通用定时器L0是可编程的,可以被用来计数,其外部事件可以驱动其他定时器。

本章要实现通过输入捕获,来获取TIMER2_CH0(PA6)上面的下降沿,下面我们介绍库函数配置上述功能输入捕获的步骤:

1)开启 TIMER2 时钟,配置 PA6为复用功能,并开启上拉电阻。

rcu_periph_clock_enable(RCU_TIMER2);
rcu_periph_clock_enable(RCU_GPIOA);
gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_6); //INCUPTURE -TIMER2

跟上一讲 PWM 输出类似,这里我们使用的是定时器2的通道 0,所以我们从对应的数据手册可以查看到对应的 IO 口为 PA6: 

 2) 初始化定时器参数,设置自动重装值, 分频系数,计数方式等

/* TIMER2 configuration */timer_initpara.prescaler = 5999;timer_initpara.alignedmode = TIMER_COUNTER_EDGE;timer_initpara.counterdirection = TIMER_COUNTER_UP;timer_initpara.period = 4000;timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_init(TIMER2, &timer_initpara);

 3)设置 TIMER2 的输入捕获参数,开启输入捕获

库函数是通过 timer_input_capture_config 函数来初始化输入比较参数的: timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);

同样,我们来看看参数设置结构体 TIM_ICInitTypeDef 的定义:

typedef struct
{ uint16_t icpolarity; /*!< channel input polarity */uint16_t icselection; /*!< channel input mode selection */uint16_t icprescaler; /*!< channel input capture prescaler */uint16_t icfilter; /*!< channel input capture filter control */
}timer_ic_parameter_struct;

我们的配置代码是:

/* initialize TIMER channel input parameter struct */timer_channel_input_struct_para_init(&timer_icinitpara);/* TIMER2 CH0 input capture configuration */timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING;timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;timer_icinitpara.icfilter = 0x0;
timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);

4) 使能捕获中断和NVIC

timer_interrupt_enable(TIMER2,TIMER_INT_CH0);
nvic_irq_enable(TIMER2_IRQn, 1, 1);

5) 编写中断服务函数

void TIMER2_IRQHandler(void){……}

 6) 使能定时器

timer_enable(TIMER2);

通过以上 6 步设置,定时器 2 的通道 0 就可以开始输入捕获了

外部时钟输入 TIMER1

通用定时器L0(TIMER1/2/3/4) 是4通道定时器,支持输入捕获,输出比较,产生PWM信号控制电机和电源管理。通用定时器L0计数器是16位无符号计数器。通用定时器L0是可编程的,可以被用来计数,其外部事件可以驱动其他定时器。

本章要实现使用TIMER1 PA0 作为时钟输入引脚,配置流程:

(1)使能GPIO,TIMER 时钟和GPIO口复用配置

rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_AF);
rcu_periph_clock_enable(RCU_TIMER1);
gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_50MHZ,GPIO_PIN_0);

(2)通过查看数据手册,可以看到TIMER1_CH0_ETI,根据前面所讲,是可以支持外部时钟输入的。

TIMER的结构体,初始化定时器参数,设置自动重装值, 分频系数,计数方式等

//ETItimer_initpara.prescaler = 1; // 2 分频timer_initpara.alignedmode = TIMER_COUNTER_EDGE;timer_initpara.counterdirection = TIMER_COUNTER_UP;timer_initpara.period = 65535;timer_initpara.clockdivision = TIMER_CKDIV_DIV1;timer_initpara.repetitioncounter = 0;timer_init(TIMER1,&timer_initpara);
timer_enable(TIMER1);

(3)配置TIMER的时钟来源和时钟源处理的配置

timer_input_trigger_source_select(TIMER1,TIMER_SMCFG_TRGSEL_ETIFP);
timer_external_clock_mode1_config(TIMER1, TIMER_EXT_TRI_PSC_OFF, TIMER_ETP_RISING, 0);

(4)使能TIMER

timer_enable(TIMER1);

5.5.TIMER 使用注意事项

TIMER 高级定时器 做定时用的时候(使用到UPDAT中断),在产生中断之后,高级定时器的其他所有的状态标志位会被置位,但是不会置位中断标志位.

本章内容每日持续更新,如有兴趣,请关注收藏

更多GD32 MCU相关咨询:https://www.gd32bbs.com/ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/383977.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑屏幕录制软件,分享4款(2024最新)

在今天&#xff0c;我们的电脑屏幕成为了一个多彩多姿的窗口。通过它我们可以浏览网页、观看视频、处理文档、进行游戏……有时&#xff0c;我们想要记录下这些精彩瞬间&#xff0c;与朋友分享&#xff0c;或者作为教程留存&#xff0c;这时&#xff0c;电脑屏幕录制就显得尤为…

全年销售7亿块,巧克力企业如何通过相邻业务打造极致产品力?

蒂罗尔巧克力是日本经典的巧克力品牌。 糖果业务是松尾早期的主营业务&#xff0c;在主营业务下滑的情况下&#xff0c;确立新的竞争方向&#xff0c;通过主营业务优势进入相邻业务&#xff0c;打造新产品成就巧克力极致产品力&#xff0c;避免衰退重回增长。 如何通过进入相邻…

Ubuntu下载jdk:cannot execute binary file

虚拟机上Ubuntu系统安装jdk且配置环境之后&#xff0c;java -version显示cannot execute binary file&#xff0c;多番查阅推测是由于系统和jdk版本不兼容的原因。 uname -m查看系统版本位i686&#xff0c;是32位的&#xff0c;和64位的jdk版本不兼容。因此&#xff0c;下载32位…

Linux:core文件无法生成排查步骤

1、进程的RLIMIT_CORE或RLIMIT_SIZE被设置为0。使用getrlimit和ulimit检查修改。 使用ulimit -a 命令检查是否开启core文件生成限制 如果发现-c后面的结果是0&#xff0c;就临时添加环境变量ulimit -c unlimited&#xff0c;之后在启动程序观察是否有core生成&#xff0c;如果…

【学习笔记】解决Serial Communication Library编译问题

【学习笔记】解决编译 Serial Communication Library 时的 Catkin 依赖问题 Serial Communication Library 是一个用 C 编写的用于连接类似 rs-232 串口的跨平台库。它提供了一个现代的 C 接口&#xff0c;它的工作流程设计在外观和感觉上与 PySerial 相似&#xff0c;但串口速…

Axure软件新功能解析与应用技巧分享

Axure是一种用于创建原型和交互设计的软件工具&#xff0c;广泛应用于操作界面。&#xff08;UI&#xff09;和客户体验&#xff08;UX&#xff09;为了展示和测试应用程序、网站或其他数据产品的性能和操作界面&#xff0c;设计帮助产品经理、设计师和开发者制作具有交互性的原…

服务器上使用Docker部署sonarQube,并集成到Jenkins实现自动化。

目标是要在目标服务器上使用docker工具部署好sonar环境&#xff0c;然后再集成到Jenkins中实现自动化的代码审查工作。 Docker 首先Dokcer的源大部分现在都用不了&#xff0c;于是我上网查询&#xff0c;终于找到了一个可用的镜像。 编辑/etc/docker/daemon.json文件&#x…

lua 游戏架构 之 游戏 AI (五)ai_autofight_find_way

这段Lua脚本定义了一个名为 ai_autofight_find_way 的类&#xff0c;继承自 ai_base 类。 lua 游戏架构 之 游戏 AI &#xff08;一&#xff09;ai_base-CSDN博客文章浏览阅读238次。定义了一套接口和属性&#xff0c;可以基于这个基础类派生出具有特定行为的AI组件。例如&…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第三十八章 驱动模块编译进内核

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

Golang | Leetcode Golang题解之第279题完全平方数

题目&#xff1a; 题解&#xff1a; // 判断是否为完全平方数 func isPerfectSquare(x int) bool {y : int(math.Sqrt(float64(x)))return y*y x }// 判断是否能表示为 4^k*(8m7) func checkAnswer4(x int) bool {for x%4 0 {x / 4}return x%8 7 }func numSquares(n int) i…

【快速逆向二/无过程/有源码】掌上高考—2024高考志愿填报服务平台

逆向日期&#xff1a;2024.07.21 使用工具&#xff1a;Node.js 加密工具&#xff1a;Crypto-js标准库 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 AES解密处理&#xff08;直接解密即可&#xff09;&#xff08;crypto-js.js 标准算法&…

深蓝学院 机器人操作系统ROS理论与实践(四)

一、机器人是什么&#xff1f; 机器人是如何组成的&#xff08;控制的角度&#xff09; 二、机器人系统构建 执行机构的实现——机器人底盘、电机、舵机等 驱动系统的实现 内部传感器的实现 控制系统的实现 外部传感系统的实现——摄像头、激光雷达、GPS等 1、连接摄像头 …

STM32——GPIO(点亮LEDLED闪烁)

一、什么是GPIO&#xff1f; GPIO&#xff08;通用输入输出接口&#xff09;&#xff1a; 1.GPIO 功能概述 GPIO 是通用输入/输出&#xff08;General Purpose I/O&#xff09;的简称&#xff0c;既能当输入口使用&#xff0c;又能当输出口使用。端口&#xff0c;就是元器件…

uniapp手写滚动选择器

文章目录 效果展示HTML/Template部分&#xff1a;JavaScript部分&#xff1a;CSS部分&#xff1a;完整代码 没有符合项目要求的选择器 就手写了一个 效果展示 实现一个时间选择器的功能&#xff0c;可以选择小时和分钟&#xff1a; HTML/Template部分&#xff1a; <picker…

【OpenCV C++20 学习笔记】扫描图片数据

扫描图片数据 应用情景图像数据扫描的难点颜色空间缩减&#xff08;color space reduction&#xff09;查询表 扫描算法计算查询表统计运算时长连续内存3种扫描方法C风格的扫描方法迭代器方法坐标方法LUT方法 算法效率对比结论 应用情景 图像数据扫描的难点 在上一篇文章《基…

调度子系统在特定时间执行

时序逻辑调度器设计模式允许您安排Simulink子系统在指定时间执行。以下模型说明了这种设计模式。 时序逻辑调度器图表包含以下逻辑&#xff1a; 时序逻辑调度器的关键行为 时序逻辑调度器图表包含两个状态&#xff0c;它们以不同的速率调度函数调用子系统A1、A2和A3的执行&…

【管控业财一体化】

1. 引言 大型集团在现代企业管理中扮演着举足轻重的角色&#xff0c;其管控业财一体化解决方案是实现企业高效运营的关键。随着数字化转型的加速&#xff0c;业财一体化不再局限于财务与业务流程的简单融合&#xff0c;而是向着更深层次的数据驱动、智能化决策和价值创造方向发…

Python小工具——监听某网站的数据变化并进行邮件通知

目录 一、需求描述 二、解析 三、实例代码 一、需求描述 监听自考网2024年广东省6月份的毕业生学历注册进度&#xff0c;这是网址&#xff1a;https://www.chsi.com.cn/xlcx/count_zk.jsp&#xff0c; 如上图所示&#xff0c;我们想知道这个红色的空格啥时候被填满&#xf…

7月26日贪心练习-摆动序列专题

前言 大家好&#xff0c;今天学习用贪心思想解决摆动序列问题&#xff0c;共三题&#xff0c;分享自己的思路&#xff0c;请大家多多支持 算法思想 大家可以先看看这道我们后面会讲的题看看怎么个事&#xff0c;. - 力扣&#xff08;LeetCode&#xff09; 由此题题解说明算…

SwiftSage:参考人脑双系统,结合快思和慢想的智能体,解决复杂任务同时降低成本

SwiftSage&#xff1a;参考人脑双系统&#xff0c;结合快思和慢想的智能体&#xff0c;解决复杂任务同时降低成本 提出背景解法拆解子解法1&#xff1a;SWIFT模块子解法2&#xff1a;SAGE模块模块整合和决策树逻辑链 SwiftSage 工作流程效果 论文&#xff1a;SWIFTSAGE: A Gene…