ARM32开发--PWM高级定时器

目录

文章目录

前言

目标

学习内容

需求

高级定时器通道互补输出

开发流程

通道配置

打开互补保护电路

完整代码

练习题

总结


前言

在嵌入式软件开发中,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开发打下了坚实的基础。通过不断学习和实践,我们将能够提升自己在嵌入式软件开发领域的技能水平,开发出更加优秀和稳定的产品和应用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分离式网络变压器与传统网络变压器在电路设计中如何选择?

Hqst盈盛&#xff08;华强盛&#xff09;电子导读&#xff1a;今天分享的是&#xff1a;分离式网络变压器与传统网络变压器在电路设计中如何选择&#xff1f; 首先&#xff0c;我们要了解传统网络变压器和分离式网络变压器在设计上主要有以下不同点&#xff1a; 1、传统网络变…

Java GUI编程

引言 图形用户界面&#xff08;GUI&#xff09;编程是使应用程序与用户进行交互的重要部分。Java提供了多种用于GUI开发的工具和库&#xff0c;最常用的是Swing和AWT。本文将详细介绍Java GUI编程的基础知识&#xff0c;包括Swing和AWT框架、事件处理以及高级GUI组件的使用&…

【Pandas驯化-02】pd.read_csv读取中文出现error解决方法

【Pandas】驯化-02pd.read_csv读取中文出现error解决方法 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 相关内容文档获取 微信公众号 &…

剃头师傅不担心AI大模型 到底谁该担心?

到底学什么&#xff0c;不会被AI替代&#xff1f; 我家附近有一家美容店&#xff0c;已经开了20多年&#xff0c;店里的一位伙计硬是靠着自己的坚持从学徒熬成了门店的合伙人&#xff0c;所以现在去理发时&#xff0c;我都叫他“周董”。 这天&#xff0c;我问他&#xff0c;…

网络通信的两大支柱:TCP与UDP协议详解(非常详细)零基础入门到精通,收藏这一篇就够了

在构建现代互联网通信的基石中&#xff0c;TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;起着至关重要的作用。本文将深入探讨两者的区别及应用场景。 1 TCP和UDP的共同点 传输层协议&#xff1a; TCP和UDP都是传输层协议&#xff…

联想电脑电池只能充到80%,就不在充电了,猛一看以为坏了,只是设置了养护模式。

现在电池管理模式有三种&#xff1a; 1&#xff09;常规 2&#xff09;养护 3&#xff09;快充 好久没有用联想的电脑了&#xff0c;猛一看&#xff0c;咱充到了80%不充了&#xff0c;难道电池是坏的&#xff1f;我们要如何设置才可以让其充电到100%呢&#xff1f; 右下角…

智慧监狱技术解决方案

1. **建设背景**&#xff1a;介绍了智慧监狱建设的战略部署&#xff0c;包括司法部提出的“数字法治、智慧司法”信息化体系建设&#xff0c;以及智慧监狱建设的总体目标、重点任务和实施步骤。 2. **建设需求**&#xff1a;分析了当前监狱系统存在的问题&#xff0c;如子系统…

后端中缓存的作用以及基于Spring框架演示实现缓存

缓存的作用及演示 现在我们使用的程序都是通过去数据库里拿数据然后展示的 长期对数据库进行数据访问 这样数据库的压力会越来越大 数据库扛不住了 创建了一个新的区域 程序访问去缓存 缓存区数据库 缓存里放数据 有效降低数据访问的压力 我们首先进行一个演示 为了演示…

大模型系列:Prompt提示工程常用技巧和实践

前言 Prompt提示语是使用大模型解决实际问题的最直接的方式&#xff0c;本篇介绍Prompt提示工程常用的技巧&#xff0c;包括Zero-Shot、Few-Shot、CoT思维链、Least-to-Most任务分解。 内容摘要 Prompt提示工程简述Prompt的一般结构介绍零样本提示Zero-Shot少样本提示Few-Sho…

企业化运维(3)_PHP、nginx结合php-fpm、memcache、openresty、goaccess日志可视化

###1.PHP源码编译### 解压PHP压缩包&#xff0c;切入PHP目录&#xff0c;进行configure-->make-->make installd三部曲 [rootserver1 ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel ##依赖性 [rootserver1 ~]# yum…

python如何对list求和

如何在Python中对多个list的对应元素求和&#xff0c;前提是每个list的长度一样。比如&#xff1a;a[1&#xff0c;2&#xff0c;3]&#xff0c;b[2&#xff0c;3&#xff0c;4]&#xff0c;c[3&#xff0c;4&#xff0c;5]&#xff0c;对a&#xff0c;b&#xff0c;c的对应元素…

Maven常用命令介绍(Ⅰ)

基本命令 Maven生命周期 Maven的生命周期是对所有的构建过程进行抽象和统一。Maven的生命周期是抽象的&#xff0c;这意味着生命周期本身不做任何实际的工作&#xff0c;生命周期只是定义了一系列的阶段&#xff0c;并确定这些阶段的执行顺序。而在执行这些阶段时&#xff0c;…

父亲节马上到了-和我一起用Python写父亲节的祝福吧

前言 让我们一起用Python写一段父亲节的祝福吧 &#x1f4dd;个人主页→数据挖掘博主ZTLJQ的主页 个人推荐python学习系列&#xff1a; ☄️爬虫JS逆向系列专栏 - 爬虫逆向教学 ☄️python系列专栏 - 从零开始学python 话不多说先上代码 import tkinter as tk from doctest imp…

MEMS:Lecture 16 Gyros

陀螺仪原理 A classic spinning gyroscope measures the rotation rate by utilizing the conservation of angular momentum. 经典旋转陀螺仪通过利用角动量守恒来测量旋转速率。 Coriolis Effect and Coriolis Force 科里奥利效应是一种出现在旋转参考系中的现象。它描述了…

显示类控件——Label

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;QT ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、Label介绍属性代码示例: 显示不同格式的文本代码示例: 显示图片代码示例: 文本对齐, 自动换行…

PFA 反应罐内衬特氟龙 润滑绝缘行业加工 匠心工艺

PFA反应罐别名也叫反应瓶&#xff0c;储样罐&#xff0c;清洗罐等。可作为样品前处理实验中消解样品和中低压溶样的反应容器&#xff0c;广泛应用于半导体分析、新材料、新能源、同位素分析等。 PFA反应罐规格参考&#xff1a;250ml、300ml、350ml、500ml、1L等。 产品特点&…

大众点评js逆向过程(未完)

1、这里mtgsig已经被拼到url中 2、进入后mtgsig已经计算完&#xff0c; ir he(this[b(4326)], !1), 就是加密函数 32 次 796 1143 ->508 -> 754 -> 1151 160 注意IC这个数组 控制流平坦化进行AST 解析 AST网址

Swift开发——循环执行方式

本文将介绍 Swift 语言的循环执行方式 01、循环执行方式 在Swift语言中,主要有两种循环执行控制方式: for-in结构和while结构。while结构又细分为当型while结构和直到型while结构,后者称为repeat-while结构。下面首先介绍for-in结构。 循环控制方式for-in结构可用于区间中的…

2024全新仿麻豆视频苹果cms源码v10影视模板

下载地址&#xff1a;2024全新仿麻豆视频苹果cms源码v10影视模板 高端大气的设计&#xff0c;适合做电影、连续剧、综艺、动漫、微电影、纪录片、海外剧等视频网站

【秋招突围】2024届秋招笔试-小红书笔试题-第一套-三语言题解(Java/Cpp/Python)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系计划跟新各公司春秋招的笔试题 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f4e7; 清隆这边…