ARM32开发--PWM高级定时器

news2024/11/15 18:02:33

目录

文章目录

前言

目标

学习内容

需求

高级定时器通道互补输出

开发流程

通道配置

打开互补保护电路

完整代码

练习题

总结


前言

在嵌入式软件开发中,PWM(脉冲宽度调制)技术被广泛应用于控制各种电子设备的亮度、速度等参数。理解PWM开发流程、定时器与通道的关系,掌握多通道配置策略和互补PWM配置策略,以及掌握定时器查询方式和代码抽取优化策略,对于提高嵌入式软件开发的效率和质量至关重要。

本次学习的目标是点亮2个LED灯,采用互补PWM的方式来控制互补LED效果。通过学习高级定时器通道互补输出,我们将逐步了解如何初始化PWM、配置通道的P极和N极、控制PWM占空比,以实现目标效果。


目标

  1. 加强掌握PWM开发流程
  2. 理解定时器与通道的关系
  3. 掌握多通道配置策略
  4. 掌握互补PWM配置策略
  5. 掌握定时器查询方式
  6. 掌握代码抽取优化策略
  7. 掌握PWM调试方式

学习内容

需求

点亮2个灯,采用互补pwm的方式

定时器

通道

引脚

AF

极性

LED序号

T0

ch0

PE8

AF1

ON

LED1

PE9

AF1

OP

LED2

将PE8短接至PD8,PE9短接至PD9,实现互补LED效果。

高级定时器通道互补输出

开发流程

  1. 添加Timer依赖
  2. 初始化PWM
  3. 配置通道的P极和N极
  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);
  ocpara.outputstate  = TIMER_CCX_ENABLE;        // OP Enable
  ocpara.outputnstate = TIMER_CCXN_ENABLE;       // ON Enable
  ocpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;   // OP Polarity
  ocpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;  // ON Polarity
  /* 配置输出参数 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);
}
  • ocnpolarity:N极性电平
  • ocpolarity:P极性电平

打开互补保护电路

// 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;
/* break输入的启用*/
breakpara.breakstate      = TIMER_BREAK_ENABLE;
/* 配置TIMER0 break */
timer_break_config(TIMER0, &breakpara);
/* 启用TIMER0 break */
timer_break_enable(TIMER0);

完整代码

#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);
  
//  rcu_periph_clock_enable(RCU_GPIOD);
//  gpio_mode_set(GPIOD, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_8 | GPIO_PIN_9);
}

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  = TIMER_CCX_ENABLE;        // OP Enable
  ocpara.outputnstate = TIMER_CCXN_ENABLE;       // ON Enable
  ocpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;   // OP Polarity
  ocpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;  // ON Polarity
  /* 配置输出参数 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);
}


// PWM
#define	PRESCALER		1
#define	FREQ			  10000
#define PERIOD			(SystemCoreClock / FREQ)

// LED1 TM0CH1 PE9  OP
// LED2 TM0CH0 PE8  ON
static void Timer_config() {
  // 定时器

  // GPIO ----------------------------------------
  timer_gpio_config(RCU_GPIOE, GPIOE, GPIO_PIN_9, GPIO_AF_1);
  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-------------------------------
  timer_channel_config(TIMER0, TIMER_CH_0);
  
  // 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;
  /* break输入的启用*/
  breakpara.breakstate      = TIMER_BREAK_ENABLE;
  
  /* 配置TIMER0 break */
  timer_break_config(TIMER0, &breakpara);
  /* 启用TIMER0 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-100

  if(duty > 100) duty = 100;
  else if(duty < 0) duty = 0;

//	pulse / PERIOD == duty / 100
  uint32_t pulse = PERIOD * duty / 100.0f - 1;

  // 计数值 65535
  timer_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(TIMER0, TIMER_CH_0, duty);

    if (duty >= 100) {
      dir = -1;
    } else if (duty <= 0) {
      dir = 1;
    }
    duty += dir;

    printf("duty: %.2f \n", duty);

    delay_1ms(10);
  }
}

练习题


总结

通过本次学习,我们深入了解了PWM技术在嵌入式软件开发中的应用。从添加Timer依赖开始,我们逐步完成了初始化PWM、配置通道的P极和N极、设定PWM占空比等步骤,最终实现了点亮2个LED灯的效果,并采用互补PWM的方式来控制LED的亮度。

在实现过程中,我们学习了定时器与通道的关系,掌握了多通道配置策略和互补PWM配置策略,同时了解了定时器查询方式和代码抽取优化策略,为日后更高效地进行PWM开发打下了坚实的基础。通过不断学习和实践,我们将能够提升自己在嵌入式软件开发领域的技能水平,开发出更加优秀和稳定的产品和应用。

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

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

相关文章

STM32驱动带编码器的直流减速电机

STM32驱动带编码器的直流减速电机 文章目录 STM32驱动带编码器的直流减速电机硬件材料MG310 直流减速电机直流电机原理减速器实物接线霍尔编码器 TB6612电机驱动接线说明程序设计定时器生成PWM驱动电机速度计算 实验结果程序下载 硬件材料 主控板&#xff1a;STM32F407ZG直流减…

【漏洞复现】WVP视频平台未授权漏洞

漏洞描述&#xff1a; WVP视频平台api/user存在未授权访问漏洞&#xff0c;攻击者可利用漏洞获取当前系统管理员用户名及密码进行登录系统。 搜索语法: Fofa-Query: body"国标28181" 漏洞详情&#xff1a; 1.WVP视频平台。 2.POC: GET /api/user/all HTTP/1.1 …

Redis项目中竟然有这么多种使用场景!!

下面蜗牛哥依次对Redis 15种业务场景举例说明和解释&#xff1a; 1. 排行榜和计数器 针对Redis作为排行榜和计数器的使用场景&#xff0c;下面是一个Java Spring Boot应用的案例&#xff0c;其中使用Redis来实现一个简单的文章点赞功能&#xff0c;并将点赞数用作排行榜的依据…

Django UpdateView视图

UpdateView是Django中的一个通用视图&#xff0c;用于处理对象的更新操作。它允许用户更新一个已经存在的对象。UpdateView通常与一个模型表单一起使用&#xff0c;这样用户就可以看到当前对象的值&#xff0c;并可以修改它们。 1&#xff0c;添加视图 Test/app3/views.py fr…

什么是覆盖索引 ?

走当前索引就足够&#xff0c;而无需回表就能找到所有数据&#xff0c;就叫覆盖索引。 比如 key1 上有索引。&#xff08;它是一个普通的二级索引&#xff09;。 那么select key1 from s1 where key1 a 这种就叫覆盖索引。 表现就是explain时&#xff0c; Extra 那里显示 …

鸿蒙开发文件管理:【@ohos.fileio (文件管理)】

文件管理 该模块提供文件存储管理能力&#xff0c;包括文件基本管理、文件目录管理、文件信息统计、文件流式读写等常用功能。 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 impor…

AI创意广告案例分析️可口可乐、麦当劳、伊利、钟薛高等一线品牌各显神通

AI 相关的教学我们最近做了不少分享&#xff0c;本期计育韬老师则希望和广告人们谈一谈具体的落地案例应用及其内在创意方法论。结合在 Midjourney 频道 LV.14 的部分创作经验&#xff0c;相信能为广大品牌方带来 AI 广告创作的启迪。 担心版权争议&#xff1f; 那就主打 UG…

分离轴定理:凸多边形相交检测算法

分离轴定理&#xff08;Seperating Axis Theorem&#xff09;是一种确定两个凸多边形是否相交的方法。该算法还可用于查找最小穿透向量&#xff0c;这对于物理模拟和许多其他应用非常有用。SAT 是一种快速通用算法&#xff0c;可以消除对每个形状类型对进行碰撞检测代码的需求&…

在Vue2和Vue3中ECharts如何使用,详细步骤,ref,$ref。echarts官网。

不管是在vue2中还是在vue3中其实本质上的原理和步骤都是一样的&#xff0c;只是语法可能有所不同。 为了方便大家看起乱&#xff0c;vue2和vue3我分开写。 echarts官网&#xff1a; https://echarts.apache.org/zh/index.html Vue2篇&#xff1a; 1.导入echarts包&#xf…

LaDM3IL:多实例学习用于免疫库分类

一个人的免疫组库由某一时间点的大量适应性免疫受体组成&#xff0c;代表了该个体的适应性免疫状态。免疫组库分类和相关受体识别有可能为新型疫苗的开发做出贡献。大量的实例对免疫组库分类提出了挑战&#xff0c;这可以表述为大规模多实例学习 (MMIL&#xff0c;Massive Mult…

AI实时免费在线图片工具4:WordArt艺术字生成;IC-Light打光模型;screenshot to code图像直接生成网页

1、艺术字生成WordArt https://modelscope.cn/studios/WordArt/WordArt/summary?reftop.aibase.com 2、打光模型IC-Light https://huggingface.co/spaces/lllyasviel/IC-Light Screenshot to Code图像直接生成网页 https://huggingface.co/spaces/HuggingFaceM4/screen…

Ubuntu,Linux服务器安装Mellanox MCX653105A IB网卡HCA卡驱动

驱动下载地址 https://network.nvidia.com/products/infiniband-drivers/linux/mlnx_ofed/ 选择对应操作系统 进入目录运行 安装成功显示 如果中途报错&#xff0c;需要核对下载的版本&#xff0c;并且把原来安装的卸载

钡铼BL102优化生产流程PLC-MQTT网关快速转换

在智能制造和工业4.0的推动下&#xff0c;优化生产流程、提升自动化水平已成为现代制造业的核心诉求。作为这一进程的关键环节&#xff0c;将传统的PLC控制系统与先进的物联网技术相结合&#xff0c;实现数据的高效采集与远程管理变得尤为重要。钡铼BL102作为一款专为优化生产流…

Jsch上传本地目录文件到服务器

文章目录 1.Jsch简介1.1 什么是Jsch1.2 Jsch使用步骤和简单示例 2.技术关键点3.Jsch实战3.1 maven依赖3.2 功能实现3.3 效果3.4 封装工具类 4.总结 摘要: 在一些框架开发工作中&#xff0c;需要为项目使用说明文档&#xff0c;来指导用户如何正确使用框架。比如通过markdown编写…

易舟云:让中小企业财务管理变得触手可及

在现代企业运营中&#xff0c;财务管理的精准和高效至关重要。对于中小企业来说&#xff0c;一款专业且易于使用的财务软件更是必不可少的工具。今天&#xff0c;我们就来详细了解一款深受中小企业喜爱的财务软件——易舟云。 财务管理的云端革命 随着云技术的发展&#xff0c;…

EVA-CLIP:在规模上改进CLIP的训练技术

摘要 对比性语言-图像预训练&#xff0c;简称CLIP&#xff0c;因其在各种场景中的潜力而备受关注。在本文中&#xff0c;我们提出了EVA-CLIP&#xff0c;一系列模型&#xff0c;这些模型显著提高了CLIP训练的效率和有效性。我们的方法结合了新的表示学习、优化和增强技术&…

Phaser-圆形路径

使用 Phaser 创建一个简单的路径动画 Phaser 是一个强大的 HTML5 游戏框架&#xff0c;适合用于开发 2D 游戏。在本文中&#xff0c;我们将展示如何使用 Phaser 创建一个简单的动画示例&#xff0c;其中一个红色的圆沿着椭圆路径移动。该示例将帮助你理解如何在 Phaser 中使用…

Linux用户,用户组,所有者权限分配,sftp用户权限分配

注意以下命令执行需要在root用户下执行 tenant命令切换至root命令 sudo -do root 删除用户信息 1.不删除用户主目录 userdel user_name 2.删除用户主目录 userdel -r user_name usermod命令修改用户账户权限 更改用户名 sudo usermod -l newusername oldusername 更…

Redis】Redis主从复制(二)————主从结构/流程

目录 回顾slaveof 命令断开主从复制关系切换主从复制关系只读网络延迟问题应对措施补充 主从结构一主一从结构问题改进 一主多从结构树形主从主从切换结构 主从复制流程简单来记关于数据同步两个参数replicationidoffset. psync 运行流程全量复制和部分复制全量复制流程&#x…

在镜像中添加Git提交号

文章目录 前言环境介绍思路内核cpuinfo中添加Git提交号修改setup.c获取Git提交号和生成GIT_COMMIT_INFO宏继续修改内核setup.c验证 内核设备树中添加Git提交号修改设备树验证 U-Boot版本号添加Git提交号U-Boot配置修改setlocalversion脚本验证 前言 在镜像中加入Git提交号&…