ARM-定时器-PWM通道输出

学习内容

需求

点亮4个灯,采用pwm的方式。

定时器

通道

引脚

AF

LED序号

T3

CH0

PD12

AF2

LED5

CH1

PD13

AF2

LED6

CH2

PD14

AF2

LED7

CH3

PD15

AF2

LED8

实现LED5, LED6, LED7, LED8呼吸灯效果

通用定时器多通道

点亮T3定时器下的多个通道的灯。

开发流程

  1. 添加Timer依赖
  2. 初始化PWM相关GPIO
  3. 初始化PWM,包含多通道配置
  4. PWM占空比控制

多通道配置

void timer_channel_config(uint32_t timer_periph, uint16_t channel) {/* TIMER 通道输出配置 */timer_oc_parameter_struct ocpara;/* initialize TIMER channel output parameter struct */timer_channel_output_struct_para_init(&ocpara);/* 启用P极输出 */ocpara.outputstate  = (uint16_t)TIMER_CCX_ENABLE;/* 配置输出参数 configure TIMER channel output function */timer_channel_output_config(timer_periph, channel, &ocpara);/* 配置通道输出输出比较模式 configure TIMER channel output compare mode */timer_channel_output_mode_config(timer_periph, channel, TIMER_OC_MODE_PWM0);
}

 

输出比较模式

  • TIMER_OC_MODE_PWM0: 高电平有效
  • TIMER_OC_MODE_PWM1:低电平有效

占空比更新

/*********************************************************** @brief 更新pwm占空比* @param timer_periph 定时器* @param channel 通道* @param duty  占空比[0, 100]* @return **********************************************************/
void PWM_update(uint32_t timer_periph, uint16_t channel, float duty) { // 0-100if(duty > 100) duty = 100;else if(duty < 0) duty = 0;//	pulse / PERIOD == duty / 100uint32_t pulse = PERIOD * duty / 100.0f - 1;// 计数值 65535timer_channel_output_pulse_value_config(timer_periph, channel, pulse);
}

 完整代码

#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "USART0.h"void USART0_on_recv(uint8_t* data, uint32_t len) {printf("g_rx_buffer: %s g_rx_cnt:%d \n", data, len);
}static void GPIO_config() {rcu_periph_clock_enable(RCU_GPIOC);gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);gpio_bit_reset(GPIOC, GPIO_PIN_6);
}void timer_gpio_config(uint32_t gpio_rcu, uint32_t gpio_port, uint32_t gpio_pin, uint32_t gpio_af) {rcu_periph_clock_enable(gpio_rcu);/* 设置gpio模式 */gpio_mode_set(gpio_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gpio_pin);gpio_output_options_set(gpio_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, gpio_pin);gpio_af_set(gpio_port, gpio_af, gpio_pin);
}void timer_init_config(rcu_periph_enum rcu_periph, uint32_t timer_periph,uint16_t t_prescaler, uint32_t t_period) {rcu_periph_clock_enable(rcu_periph);timer_deinit(timer_periph);/*初始化参数 */timer_parameter_struct initpara;/* initialize TIMER init parameter struct */timer_struct_para_init(&initpara);/* 根据需要配置值 分频系数 (可以实现更低的timer频率) */initpara.prescaler 	= t_prescaler - 1;/* 1个周期的计数(period Max: 65535) Freq > 3662  */initpara.period		= t_period - 1;/* initialize TIMER counter */timer_init(timer_periph, &initpara);/* enable a TIMER */timer_enable(timer_periph);}void timer_channel_config(uint32_t timer_periph, uint16_t channel) {/* TIMER 通道输出配置 */timer_oc_parameter_struct ocpara;/* initialize TIMER channel output parameter struct */timer_channel_output_struct_para_init(&ocpara);ocpara.outputstate  = (uint16_t)TIMER_CCX_ENABLE;/* 配置输出参数 configure TIMER channel output function */timer_channel_output_config(timer_periph, channel, &ocpara);/* 配置通道输出输出比较模式 configure TIMER channel output compare mode */timer_channel_output_mode_config(timer_periph, channel, TIMER_OC_MODE_PWM0);
}// TIMER CH
#define LED5 TIMER3, TIMER_CH_0
#define LED6 TIMER3, TIMER_CH_1
#define LED7 TIMER3, TIMER_CH_2
#define LED8 TIMER3, TIMER_CH_3// PWM
#define	PRESCALER		1
#define	FREQ			  10000
#define PERIOD			(SystemCoreClock / FREQ)// LED5 TM3CH0 PD12
// LED6 TM3CH1 PD13
// LED7 TM3CH2 PD14
// LED8 TM3CH3 PD15
static void Timer_config() {// 定时器// GPIO ----------------------------------------timer_gpio_config(RCU_GPIOD, GPIOD, GPIO_PIN_12, GPIO_AF_2);timer_gpio_config(RCU_GPIOD, GPIOD, GPIO_PIN_13, GPIO_AF_2);timer_gpio_config(RCU_GPIOD, GPIOD, GPIO_PIN_14, GPIO_AF_2);timer_gpio_config(RCU_GPIOD, GPIOD, GPIO_PIN_15, GPIO_AF_2);// TIMER----------------------------------------/* 升级频率*/rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);timer_init_config(RCU_TIMER3, TIMER3, PRESCALER, PERIOD); // 与通道无关// TIMER channel-------------------------------timer_channel_config(LED5);timer_channel_config(LED6);timer_channel_config(LED7);timer_channel_config(LED8);}/*********************************************************** @brief 更新pwm占空比* @param timer_periph 定时器* @param channel 通道* @param duty  占空比[0, 100]* @return **********************************************************/
void PWM_update(uint32_t timer_periph, uint16_t channel, float duty) { // 0-100if(duty > 100) duty = 100;else if(duty < 0) duty = 0;//	pulse / PERIOD == duty / 100uint32_t pulse = PERIOD * duty / 100.0f - 1;// 计数值 65535timer_channel_output_pulse_value_config(timer_periph, channel, pulse);
}int main(void)
{systick_config();USART0_init();// 拉低总开关
//  GPIO_config();Timer_config();printf("Init Complete!\n");float duty = 0;int8_t dir = 1;while(1) {PWM_update(LED5, duty);PWM_update(LED6, duty);PWM_update(LED7, duty);PWM_update(LED8, duty);if (duty >= 100) {dir = -1;} else if (duty <= 0) {dir = 1;}duty += dir;printf("duty: %.2f \n", duty);delay_1ms(10);}
}

高级定时器通道输出

高级定时器只有TIMER0和TIMER7支持。由于扩展板上的高级定时器没有对应的LED,我们可以使用跳线的方式,将TIMER0CH0对应的PE8引脚,短接到PD8(LED1)上,通过观察LED1的亮灭,了解是否正确输出。

开发流程

  1. 添加Timer依赖
  2. 初始化PWM,包含多通道配置
  3. Break配置
  4. PWM占空比控制

通道配置

void timer0_channel_config(uint32_t timer_periph, uint16_t channel) {/* TIMER 通道输出配置 */timer_oc_parameter_struct ocpara;/* initialize TIMER channel output parameter struct */timer_channel_output_struct_para_init(&ocpara);// 禁用 OP极
//  ocpara.outputstate  = TIMER_CCX_ENABLE;// 启用 ON极ocpara.outputnstate = TIMER_CCXN_ENABLE;/* 配置输出参数 configure TIMER channel output function */timer_channel_output_config(timer_periph, channel, &ocpara);/* 配置通道输出输出比较模式 configure TIMER channel output compare mode */timer_channel_output_mode_config(timer_periph, channel, TIMER_OC_MODE_PWM0);
}#define LED1 TIMER0, TIMER_CH_0timer0_channel_config(LED1);
  • 特别强调,这里的引脚分为P和N类型,不同引脚要配置不同的输出状态

Break配置

// break 只针对高级定时器TIMER0 & TIMER7,需要打开互补保护电路/* TIMER通道互补保护电路 */
timer_break_parameter_struct breakpara;
/* 初始化TIMER break参数结构体 */
timer_break_struct_para_init(&breakpara);
/* break输入的极性 HIGH */
breakpara.breakpolarity   = TIMER_BREAK_POLARITY_HIGH;
/* 输出自动的启用 */
breakpara.outputautostate = TIMER_OUTAUTO_ENABLE;
/* bread输入的启用*/
breakpara.breakstate     = TIMER_BREAK_ENABLE;
/* 配置TIMER7 break */
timer_break_config(TIMER0, &breakpara);
/* 启用TIMER7 break */
timer_break_enable(TIMER0);
  • breakstate:break状态开启
  • ouputostate:输出状态,自动开启
  • breakpolarity:输出极性,高电平

在ARM32中的高级定时器配置中,break参数用于增强安全性和控制功能,特别是在电机控制或功率转换应用中,避免因故障导致不必要的输出操作。

每个参数的作用和意义:

  1. runoffstate(溢出状态的运行)
    参数示例:TIMER_ROS_STATE_DISABLE
    作用:当定时器运行状态切换到溢出状态时,是否自动关闭输出信号。DISABLE表示不进行自动关闭。
  2. ideloffstate(空闲状态的关闭)
    参数示例:TIMER_IOS_STATE_DISABLE
    作用:当定时器进入空闲状态时,是否自动关闭输出信号。DISABLE表示不进行关闭。
  3. deadtime(死区时间)
    参数示例:255
    作用:定义死区时间(Dead Time),主要用于避免在切换高低驱动时,两个输出的驱动器同时导通,导致短路或过流。255表示配置了较大的死区时间。
  4. breakpolarity(断路信号极性)
    参数示例:TIMER_BREAK_POLARITY_LOW
    作用:定义break信号的极性。在此配置中,当断路信号为低电平时触发break事件,停止输出。
  5. outputautostate(自动输出状态)
    参数示例:TIMER_OUTAUTO_ENABLE
    作用:使能或禁用在break事件后自动恢复输出。当ENABLE时,break事件处理完成后,定时器输出可以自动恢复。
  6. protectmode(保护模式)
    参数示例:TIMER_CCHP_PROT_0
    作用:保护模式用于设置对输出寄存器的保护级别,防止在某些状态下被误修改。TIMER_CCHP_PROT_0表示最低保护级别,允许对输出进行修改。
  7. breakstate(断路状态)
    参数示例:TIMER_BREAK_ENABLE
    作用:开启或禁用break功能。ENABLE表示当检测到断路信号时,会停止输出以保护系统。


这些参数主要用于配置定时器的安全控制,break功能在高电压或高功率应用中非常关键。当发生异常或检测到故障(比如过流或短路)时,可以通过break功能立即停止PWM等输出信号,避免硬件损坏。

互补保护电路:用于驱动H桥或三相逆变器,当检测到故障(如短路)时,通过外部硬件信号(Break)快速关闭PWM输出,避免损坏MOSFET/IGBT。

高级定时器:支持死区时间、互补输出等复杂功能,常用于电机控制、电源转换等场景。

完整代码

#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "USART0.h"void USART0_on_recv(uint8_t* data, uint32_t len) {printf("g_rx_buffer: %s g_rx_cnt:%d \n", data, len);
}static void GPIO_config() {rcu_periph_clock_enable(RCU_GPIOC);gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);gpio_bit_reset(GPIOC, GPIO_PIN_6);
}void timer_gpio_config(uint32_t gpio_rcu, uint32_t gpio_port, uint32_t gpio_pin, uint32_t gpio_af) {rcu_periph_clock_enable(gpio_rcu);/* 设置gpio模式 */gpio_mode_set(gpio_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gpio_pin);gpio_output_options_set(gpio_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, gpio_pin);gpio_af_set(gpio_port, gpio_af, gpio_pin);
}void timer_init_config(rcu_periph_enum rcu_periph, uint32_t timer_periph,uint16_t t_prescaler, uint32_t t_period) {rcu_periph_clock_enable(rcu_periph);timer_deinit(timer_periph);/*初始化参数 */timer_parameter_struct initpara;/* initialize TIMER init parameter struct */timer_struct_para_init(&initpara);/* 根据需要配置值 分频系数 (可以实现更低的timer频率) */initpara.prescaler 	= t_prescaler - 1;/* 1个周期的计数(period Max: 65535) Freq > 3662  */initpara.period		= t_period - 1;/* initialize TIMER counter */timer_init(timer_periph, &initpara);/* enable a TIMER */timer_enable(timer_periph);}void timer0_channel_config(uint32_t timer_periph, uint16_t channel) {/* TIMER 通道输出配置 */timer_oc_parameter_struct ocpara;/* initialize TIMER channel output parameter struct */timer_channel_output_struct_para_init(&ocpara);// 禁用 OP极
//  ocpara.outputstate  = TIMER_CCX_ENABLE;// 启用用 OP极ocpara.outputnstate = TIMER_CCXN_ENABLE;/* 配置输出参数 configure TIMER channel output function */timer_channel_output_config(timer_periph, channel, &ocpara);/* 配置通道输出输出比较模式 configure TIMER channel output compare mode */timer_channel_output_mode_config(timer_periph, channel, TIMER_OC_MODE_PWM0);
}// TIMER CH
#define LED1 TIMER0, TIMER_CH_0// PWM
#define	PRESCALER		1
#define	FREQ			  10000
#define PERIOD			(SystemCoreClock / FREQ)// LED1 TM0CH0_ON PE8
static void Timer_config() {// 定时器// GPIO ----------------------------------------timer_gpio_config(RCU_GPIOE, GPIOE, GPIO_PIN_8,  GPIO_AF_1);// TIMER----------------------------------------/* 升级频率*/rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);timer_init_config(RCU_TIMER0, TIMER0, PRESCALER, PERIOD); // 与通道无关// TIMER channel-------------------------------timer0_channel_config(LED1);// Break --------------------------------------------------// break 只针对高级定时器TIMER0 & TIMER7,打开互补保护电路/* TIMER通道互补保护电路 */timer_break_parameter_struct breakpara;/* 初始化TIMER break参数结构体 */timer_break_struct_para_init(&breakpara);/* break输入的极性 HIGH */breakpara.breakpolarity   = TIMER_BREAK_POLARITY_HIGH;/* 输出自动的启用 */breakpara.outputautostate = TIMER_OUTAUTO_ENABLE;/* bread输入的启用*/breakpara.breakstate     = TIMER_BREAK_ENABLE;/* 配置TIMER7 break */timer_break_config(TIMER0, &breakpara);/* 启用TIMER7 break */timer_break_enable(TIMER0);
}/*********************************************************** @brief 更新pwm占空比* @param timer_periph 定时器* @param channel 通道* @param duty  占空比[0, 100]* @return**********************************************************/
void PWM_update(uint32_t timer_periph, uint16_t channel, float duty) { // 0-100if(duty > 100) duty = 100;else if(duty < 0) duty = 0;//	pulse / PERIOD == duty / 100uint32_t pulse = PERIOD * duty / 100.0f - 1;// 计数值 65535timer_channel_output_pulse_value_config(timer_periph, channel, pulse);
}int main(void)
{systick_config();USART0_init();// 拉低总开关GPIO_config();Timer_config();printf("Init Complete!\n");float duty = 0;int8_t dir = 1;while(1) {PWM_update(LED1, duty);if (duty >= 100) {dir = -1;} else if (duty <= 0) {dir = 1;}duty += dir;printf("duty: %.2f \n", duty);delay_1ms(10);}
}

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

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

相关文章

javaSE(List集合ArrayList实现类与LinkedList实现类)day15

目录 List集合&#xff1a; 1、ArrayList类&#xff1a; &#xff08;1&#xff09;数据结构&#xff1a; &#xff08;2&#xff09;扩容机制 &#xff08;3&#xff09;ArrayList的初始化&#xff1a; &#xff08;4&#xff09;ArrayList的添加元素方法 &#xff08;5…

解决 WSL 中无法访问 registry-1.docker.io/v2/,无法用 docker 拉取 image

文章目录无法拉取docker镜像补充迁移 WSL 位置Install Docker无法拉取docker镜像 docker run hello-world Unable to find image hello-world:latest locally docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline excee…

【C++】简单学——list类

模拟实现之前需要了解的概念带头双向链表&#xff08;double-linked&#xff09;&#xff0c;允许在任何位置进行插入区别相比vector和string&#xff0c;多了这个已经没有下标[ ]了&#xff0c;因为迭代器其实才是主流&#xff08;要包头文件<list>&#xff09;方法构造…

Qt 国际化与本地化完整解决方案

在全球化的今天&#xff0c;软件支持多语言和本地化&#xff08;Internationalization & Localization&#xff0c;简称i18n & l10n&#xff09;已成为基本需求。Qt提供了一套完整的解决方案&#xff0c;帮助开发者轻松实现应用程序的国际化支持。本文将从原理到实践&a…

MNIST 手写数字识别模型分析

功能概述 这段代码实现了一个基于TensorFlow和Keras的MNIST手写数字识别模型。主要功能包括&#xff1a; 加载并预处理MNIST数据集构建一个简单的全连接神经网络模型训练模型并评估其性能使用训练好的模型进行预测保存和加载模型 代码解析 1. 导入必要的库 import matplot…

进阶系统策略

该策略主要基于价格动态分析,结合多种技术指标和数学计算来生成交易信号。其核心逻辑包括: 1. 价格极值计算:首先,策略计算给定周期(由`Var3`定义)内的最高价和最低价,分别存储在`Var12`和`Var13`中。这一步骤旨在捕捉价格的短期波动范围。 2. 相对位置计算:接着,策…

【Linux内核】Linux驱动开发

推荐书籍&#xff1a; 《Linux内核探秘&#xff1a;深入解析文件系统和设备驱动的架构与设计》 知识点 x86的IO地址空间和内存地址空间是独立的两套地址空间&#xff0c;并且使用不同的指令访问。MOV, IN, OUT。内存映射I/O可以将IO映射到内存。ARM等RISC采用统一编编址&#x…

MySQL用户管理(15)

文章目录前言一、用户用户信息创建用户修改密码删除用户二、数据库的权限MySQL中的权限给用户授权回收权限总结前言 其实与 Linux 操作系统类似&#xff0c;MySQL 中也有 超级用户 和 普通用户 之分 如果一个用户只需要访问 MySQL 中的某一个数据库&#xff0c;甚至数据库中的某…

react19相关问题和解答

目录 1. react19将ref放在了props中(不再需要 forwardRef),那么是不是可以通过ref获取子组件的全部变量了? 我的子组件的useImperativeHandle还需要定义吗? 1.1. ref 在 props 中的本质变化 1.2. 为什么不能访问全部变量? 2. In HTML,cannot be a descendant of. Thi…

Code Composer Studio:CCS 设置代码折叠

Code Composer Studio&#xff1a;设置代码折叠,可以按函数&#xff0c;if, 等把代码折叠起来。1.2.开启折叠选项3.开启后&#xff0c;如果文件已经打开&#xff0c;要关掉重新打开文件就可以开到折叠功能生效。

JMeter groovy 编译成.jar 文件

groovy 编译 一、windows 下手动安装Groovy 下载 Groovy 二进制包 前往官网&#xff1a;https://groovy.apache.org/download.html 下载 Binary release&#xff08; https://groovy.jfrog.io/ui/native/dist-release-local/groovy-zips/apache-groovy-sdk-4.0.27.zip &#xf…

使用maven-shade-plugin解决依赖版本冲突

项目里引入多个版本依赖时&#xff0c;最后只会使用其中一个&#xff0c;一般可以通过排除不使用的依赖处理&#xff0c;但是如果需要同时使用多个版本&#xff0c;可以使用maven-shade-plugin解决。以最典型的poi为例&#xff0c;poi版本兼容性很低&#xff0c;如果出现找不到…

[CH582M入门第十一步]DS18B20驱动

学习目标: 1、介绍DS18B20 2、学习单总线 3、学习DS18B20程序驱动一、DS18B20介绍 DS18B20 是一款由 Maxim Integrated(原Dallas Semiconductor) 推出的 数字温度传感器,以其单总线(1-Wire)通信协议、高精度和广泛应用而闻名。以下是其核心特点和应用介绍: 主要特性 数…

SGLang + 分布式推理部署DeepSeek671B满血版

部署设备&#xff1a;28A100 80G&#xff0c;两台机器&#xff0c;每台机器8张A100。 模型&#xff1a;deepseek-671B-int8 模型下载地址&#xff1a;https://huggingface.co/meituan/DeepSeek-R1-Block-INT8 模型参考&#xff1a; 1、SGLang Docker部署 github地址&#…

PCL 间接平差拟合球

目录 一、算法原理 1、计算流程 2、参考文献 二、代码实现 三、结果展示 本文由CSDN点云侠原创,首发于2025年7月24日。博客长期更新,本文最新更新时间为:2025年7月24日。 一、算法原理 1、计算流程 空间球方程: ( x − a ) 2 + ( y − b ) 2 + ( z − c ) 2 = R 2 (1) (…

基于 HAProxy 搭建 EMQ X 集群

负载均衡器&#xff08;LB&#xff09;负责分发设备的 MQTT 连接与消息到 EMQ X 集群&#xff0c;采用 LB 可以提高 EMQ X 集群可用性、实现负载平衡以及动态扩容。 HAProxy简介 HAProxy 是一款高性能的 开源负载均衡器 和 反向代理服务器&#xff0c;主要用于在多个服务器之…

RISC-V基金会Datacenter SIG月会圆满举办,探讨RAS、PMU性能分析实践和经验

一直以来&#xff0c;龙蜥社区在 RISC-V 生态建设中持续投入&#xff0c;并积极贡献上游社区。多位龙蜥社区成员在 RISC-V 国际基金会担任主席/副主席角色&#xff0c;与来自阿里云、阿里达摩院、中兴通讯、浪潮信息、中科院软件所、字节跳动、Google、 MIT、Akeana 等企业的专…

CloudComPy使用PyInstaller打包后报错解决方案

情况描述 笔者在spec文件中&#xff0c;datas变量设置如下。如果你的报错类似于“找不到cloudComPy”&#xff0c;先尝试如下的设置。 datas[(CloudCompare,cloudComPy)], 笔者在打包完成后&#xff0c;打开软件发现报错&#xff1a; from cloudComPy import* ModuleNotFoun…

node.js中的path模块

在 Node.js 中&#xff0c;path 模块提供了处理和操作文件路径的功能&#xff0c;其中 path.join 和 path.resolve 是两个常用的方法。它们在处理路径时有不同的行为和用途: 功能概述 path.join()&#xff1a; 该方法主要用于将多个路径片段拼接成一个完整的路径字符串。它会正…

将Scrapy项目容器化:Docker镜像构建的工程实践

引言&#xff1a;爬虫容器化的战略意义在云原生与微服务架构主导的时代&#xff0c;​​容器化技术​​已成为爬虫项目交付的黄金标准。据2023年分布式系统调查报告显示&#xff1a;92%的生产爬虫系统采用容器化部署容器化使爬虫环境配置时间​​减少87%​​Docker化爬虫的故障…