【STM32基础 CubeMX】PWM输出

news2025/2/22 10:33:34

文章目录

  • 前言
  • 一、PWM是什么?
  • 二、CubeMX配置PWM
  • 三、代码分析
    • 3.1 CubeMX生成代码
    • 3.2 PWM的几个库函数
      • HAL_TIM_PWM_Start
    • 3.3 PWM回调函数
    • 3.4 占空比
      • 占空比是什么
      • __HAL_TIM_SET_COMPARE设置占空比
  • 四、呼吸灯示例
  • 总结


前言

STM32微控制器是一系列功能强大的微控制器,广泛应用于嵌入式系统和电子设备中。其中一个常见的应用是生成PWM信号,用于控制各种设备,如电机、LED灯、声音发生器等。了解如何配置和使用PWM输出对于嵌入式系统开发非常重要。

CubeMX是STMicroelectronics提供的一种工具,用于帮助开发人员轻松配置STM32微控制器并生成初始化代码。通过CubeMX,您可以在不深入复杂的寄存器级编程的情况下,设置PWM输出的参数,节省了大量的时间和精力。

在本文中,我们将首先介绍STM32微控制器的基础知识,包括GPIO(通用输入/输出)引脚和定时器的概念,这是配置PWM输出所必需的。然后,我们将详细讨论CubeMX的基本用法,包括如何创建一个新的项目、配置定时器和GPIO引脚,以及生成PWM输出代码。


一、PWM是什么?

当我们需要控制某些东西的强度、亮度、速度等时,常常会用到PWM,即脉冲宽度调制。
想象一下你在做热巧克力,你有一杯热奶和一块巧克力,你想要控制巧克力的甜度。你可以用勺子每次蘸取一小勺巧克力,然后搅拌到奶里。如果你蘸巧克力的时间很短,巧克力味就不浓;如果你蘸巧克力的时间很长,巧克力味就浓。
PWM就有点像这个过程。它是一种通过不断切换电流的方式来控制设备的强度或亮度的方法。在PWM中,我们不是像勺子一样蘸取巧克力,而是快速地打开和关闭电流,然后根据打开和关闭的时间来控制设备的表现。如果打开时间很短,设备的效果就弱;如果打开时间很长,设备的效果就强。
所以,PWM就像在控制设备的过程中,以不同的速度开和关开关,从而控制了设备的特性,就像你用不同时间搅拌巧克力来控制它的味道一样。这是一种常见的电子控制技术,用于各种应用,从调光LED到控制电机速度都可以使用PWM。

二、CubeMX配置PWM

1、其实PWM占用的是定时器,所以我们要选择定时器。
在这里插入图片描述
2、然后选择通道
在这里插入图片描述
千万不要选错了。

3、设置分频系数,和我们之前的定时器是一样的,如果忘记了的同学建议重看前面的文章!
在这里插入图片描述
4、设置周期
在这里插入图片描述
1000-1代表一个毫秒一次,可以说,这个就是我们常说的占空比,在后面我们会将占空比是什么。

5、最后,设置一下中断开启即可
在这里插入图片描述
6、最后生成代码就可以了

三、代码分析

3.1 CubeMX生成代码

static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 72-1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 1000-1;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);

}

代码分析:
TIM_MasterConfigTypeDef sMasterConfig = {0}; 和 TIM_OC_InitTypeDef sConfigOC = {0}; 这两行定义了两个结构体变量 sMasterConfig 和 sConfigOC,用来存储定时器的配置信息。

htim2.Instance = TIM2; 这行代码将定时器 htim2 的实例设置为 TIM2,表明要配置的是 TIM2 定时器。

htim2.Init.Prescaler = 72-1; 这行代码设置了 TIM2 的分频器,分频器决定了计数器的计数速度。

htim2.Init.CounterMode = TIM_COUNTERMODE_UP; 这行代码设置了计数模式,即计数器是向上计数还是向下计数。

htim2.Init.Period = 1000-1; 这行代码设置了计数器的周期,即计数器从 0 开始计数,一直计数到 999,然后重新开始。

htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; 这行代码设置了时钟分频器的分频系数,这里是不分频。

htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; 这行代码禁用了自动重装载预装载,这意味着在更新定时器参数时不会立即生效,而是等待计数器计数到上一个周期结束后才会生效。

if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) 这行代码初始化了 PWM 功能的定时器 TIM2,如果初始化失败就会调用 Error_Handler() 函数进行错误处理。

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; 这行代码设置了主定时器的输出触发模式,这里是复位触发。

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; 这行代码禁用了主从模式,主从模式通常用于多个定时器的同步。

if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) 这行代码配置了主定时器的同步功能,如果配置失败就会调用 Error_Handler() 函数进行错误处理。

sConfigOC.OCMode = TIM_OCMODE_PWM1; 这行代码设置了 TIM2 的通道 1 为 PWM1 模式。

sConfigOC.Pulse = 0; 这行代码设置了 PWM 的脉冲值,初始值为 0。

sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; 这行代码设置了 PWM 输出的极性,这里是高电平有效。

sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; 这行代码禁用了快速输出模式。

if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) 这行代码配置了 TIM2 的通道 1 为 PWM 模式,如果配置失败就会调用 Error_Handler() 函数进行错误处理。

HAL_TIM_MspPostInit(&htim2); 这行代码完成了定时器的初始化后处理,可能包括一些硬件相关的配置。

3.2 PWM的几个库函数

HAL_TIM_PWM_Start

HAL_TIM_PWM_Start 函数是HAL库(Hardware Abstraction Layer,硬件抽象层)中用于启动定时器的 PWM(脉冲宽度调制)功能的函数。以下是该函数的原型、功能和参数含义:

HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel);

HAL_StatusTypeDef:这是函数的返回类型,它表示函数执行的结果,通常用于检查函数是否成功执行。如果成功,返回 HAL_OK,否则返回错误代码。

TIM_HandleTypeDef *htim:这是一个指向 TIM_HandleTypeDef 结构体的指针,用于指定要操作的定时器。

uint32_t Channel:这是一个表示通道的参数,用于指定要启动 PWM 的定时器通道。通常,定时器可以有多个通道,每个通道可以独立配置并启动 PWM 输出。

函数的功能是启动指定通道的 PWM 输出。PWM 是一种用于产生脉冲宽度可调的信号的技术,通常用于控制电机速度、LED亮度等应用。通过调整参数,你可以控制 PWM 的频率和占空比。启动 PWM 后,定时器将按照配置的参数生成 PWM 信号,并根据需要输出到相应的引脚上。

使用示例:

HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

上述示例代码将启动 htim2 定时器的通道 1 上的 PWM 输出。这将使定时器开始生成 PWM 信号,并根据配置的参数输出到相应的引脚上。

3.3 PWM回调函数

函数原型如下:

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim);

3.4 占空比

占空比是什么

在前面我们已经设置了这个属性
在这里插入图片描述
占空比是一个用来描述脉冲信号中高电平时间与周期之比的概念。通俗来说,它表示了一个周期内信号处于高电平状态的时间比例。

考虑一个周期性的信号,比如一个方波或PWM(脉冲宽度调制)信号。这个信号在一个周期内会不断重复,而占空比告诉我们高电平(通常是1,表示电压为高的状态)在这个周期内占据了多大的比例。

举个例子,如果我们有一个方波信号,它在一个周期内持续高电平的时间是2毫秒,而周期总共是10毫秒,那么占空比就是2毫秒/10毫秒,也就是20%。这意味着在这个信号中,高电平状态占据了整个周期的20%。占空比通常以百分比的形式表示,因此这个信号的占空比是20%。

占空比在电子电路和信号处理中非常重要,因为它决定了信号的特性。在PWM中,占空比控制了输出信号的平均电压或功率,因此可以用来控制电机的速度、LED的亮度等。在电路设计中,占空比也常常用来调整信号的特性,以满足特定的需求。

或者我们可以简单的理解为:占我们上面的图片上的1000的百分之几,我们的灯的亮度就会是正常的百分之几。

__HAL_TIM_SET_COMPARE设置占空比

__HAL_TIM_SET_COMPARE 宏是用于在STMicroelectronics的HAL库中设置定时器的通道比较值(比较寄存器值)的宏。这个宏通常用于PWM(脉冲宽度调制)控制,其中比较值决定了PWM信号的占空比。以下是宏的作用和参数:

作用:

__HAL_TIM_SET_COMPARE 宏的作用是将指定定时器的指定通道的比较值(比较寄存器的值)设置为给定的值。这允许您动态地更改PWM信号的占空比,以控制相关设备的亮度、速度或其他特性。
参数:

TIMx:这是指向TIM(定时器)外设的指针,其中 x 表示具体的定时器,例如 TIM1、TIM2 等。您需要指定要设置比较值的定时器。

Channel:这是指定要设置比较值的通道,通常以宏的形式表示,如 TIM_CHANNEL_1、TIM_CHANNEL_2 等。不同的通道对应于定时器的不同输出引脚或用途。

Compare:这是要设置的比较值。比较值决定了PWM信号的占空比。具体数值的意义取决于应用,通常是一个表示时间或百分比的值。

使用示例:

__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 500);

上述示例将 htim2 定时器的通道 1 的比较值设置为 500。这将影响定时器生成的PWM信号的占空比,具体效果取决于定时器和应用的配置。

四、呼吸灯示例

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
	static uint32_t index = 0;
	static uint8_t step = 0;
	
	switch(step)
	{
		case 0:
		{
			__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_1,index);
			index++;
			if(index >= 1000)
			{
				step = 1;
			}
		}
		break;
		
		case 2:
		{
			__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_1,index);
			index--;
			if(index == 0)
			{
				step = 0;
			}
		}
		break;
	}
}

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim):这是一个函数定义,表示一个回调函数,它会在PWM信号的一个脉冲周期结束后被调用。它接受一个指向定时器句柄(TIM_HandleTypeDef)的指针作为参数。

static uint32_t index = 0;:这是一个静态变量,用来记录一个数值,初始值为0。它在函数内部保留其值,而不会在每次函数调用时重新初始化。

static uint8_t step = 0;:同样是一个静态变量,用来记录一个表示步骤的数值,初始值为0。

switch(step):这是一个开关语句,根据 step 的值来执行不同的代码块。

case 0::如果 step 的值为0,那么执行以下代码块。

__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, index);:这是一个函数调用,用于设置定时器的通道1的PWM信号的占空比,占空比的值由 index 决定。

index++;:增加 index 的值,这将在下次函数调用时用于增加PWM信号的占空比。

if(index >= 1000):如果 index 的值大于或等于1000,执行以下代码块。

step = 1;:将 step 的值设置为1,这将触发下一个 case 中的代码块执行。

case 2::如果 step 的值为2,执行以下代码块。

index–;:减小 index 的值,这将在下次函数调用时用于减小PWM信号的占空比。

if(index == 0):如果 index 的值等于0,执行以下代码块。

step = 0;:将 step 的值重新设置为0,这将触发下一个 case 0 中的代码块执行,形成一个循环。

这段代码的作用是在PWM信号中逐渐增加占空比,然后再逐渐减小占空比,不断循环。这通常用于控制某些设备或效果的强度或速度。每次函数调用都会更新PWM信号的占空比,直到达到一定条件(例如占空比达到1000或0)时,会改变步骤(step)来反转占空比的变化方向。这种方式可以创建一种周期性变化的PWM信号,用于控制设备的行为。


总结

STM32微控制器是一系列功能强大的微控制器,广泛应用于嵌入式系统和电子设备中。其中一个常见的应用是生成PWM信号,用于控制各种设备,如电机、LED灯、声音发生器等。了解如何配置和使用PWM输出对于嵌入式系统开发非常重要。

CubeMX是STMicroelectronics提供的一种工具,用于帮助开发人员轻松配置STM32微控制器并生成初始化代码。通过CubeMX,您可以在不深入复杂的寄存器级编程的情况下,设置PWM输出的参数,节省了大量的时间和精力。

在本文中,我们将首先介绍STM32微控制器的基础知识,包括GPIO(通用输入/输出)引脚和定时器的概念,这是配置PWM输出所必需的。然后,我们将详细讨论CubeMX的基本用法,包括如何创建一个新的项目、配置定时器和GPIO引脚,以及生成PWM输出代码。

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

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

相关文章

unordered_map/unordered_set的学习[unordered系列]

文章目录 1.老生常谈_遍历2.性能测试3.OJ训练3.1存在重复元素3.2两个数组的交集Ⅱ3.3两句话中的不常见单词3.4两个数组的交集3.5在长度2N的数组中找出重复N次的元素 1.老生常谈_遍历 #pragma once #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <l…

红黑树(有图解)

目录 介绍 概念 性质 模拟实现 结点定义 插入 保证平衡的原因 一般情况 特殊情况(uncle为黑) uncle不存在 旋转方式 右旋 迭代器 -- 代码 介绍 概念 红黑树是一种自平衡的二叉搜索树 它是在每个节点上引入额外的颜色信息,通过对任何一条从根到叶子的路径…

项目管理之高效合作

序 一件事能不能做成&#xff0c;和你有什么关系&#xff1f;靠的是你的努力吗&#xff1f;还是说靠的只是一个运气&#xff1f; 就像买彩票一样&#xff0c;你觉得中奖和个人努力有没有关系&#xff1b;就像和高考一样&#xff0c;你觉得考上北大清华和个人努力有没有关系&…

IDEA git操作技巧大全,持续更新中

作者简介 目录 1.创建新项目 2.推拉代码 3.状态标识 5.cherry pick 6.revert 7.squash 8.版本回退 9.合并冲突 1.创建新项目 首先我们在GitHub上创建一个新的项目&#xff0c;然后将这个空项目拉到本地&#xff0c;在本地搭建起一个maven项目的骨架再推上去&#xff0…

两条链表相同位数相加[中等]

优质博文IT-BLOG-CN 一、题目 给你两个非空的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照逆序的方式存储的&#xff0c;并且每个节点只能存储一位数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字0之外&#xff0c;这…

一文带你掌握 优先级队列

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;强烈推荐优质专栏: &#x1f354;&#x1f35f;&#x1f32f;C的世界(持续更新中) &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;…

Leetcode.965 单值二叉树

本专栏内容为&#xff1a;leetcode刷题专栏&#xff0c;记录了leetcode热门题目以及重难点题目的详细记录 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;八大排序汇总 &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &…

【算法练习Day9】用栈实现队列用队列实现栈

、​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 用栈实现队列用队列实…

代码随想录算法训练营第五十一天 |309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费、总结

一、309.最佳买卖股票时机含冷冻期 题目链接/文章讲解&#xff1a;代码随想录 视频讲解&#xff1a;动态规划来决定最佳时机&#xff0c;这次有冷冻期&#xff01;| LeetCode&#xff1a;309.买卖股票的最佳时机含冷冻期_哔哩哔哩_bilibili 思考&#xff1a; 1.确定dp数组&…

创建型设计模式 原型模式 建造者模式 创建者模式对比

创建型设计模式 单例 工厂模式 看这一篇就够了_软工菜鸡的博客-CSDN博客 4.3 原型模式 4.3.1 概述 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象。 4.3.2 结构 原型模式包含如下角色&#xff1a; 抽象原型类&#xff1a;规定了…

FFmpeg 命令:从入门到精通 | ffmpeg 命令视频录制

FFmpeg 命令&#xff1a;从入门到精通 | ffmpeg 命令视频录制 FFmpeg 命令&#xff1a;从入门到精通 | ffmpeg 命令视频录制安装软件&#xff1a;Screen Capturer Recorder查看可用设备名字音视频录制录制视频&#xff08;默认参数&#xff09;录制声音&#xff08;默认参数&am…

计算机竞赛 深度学习疲劳检测 驾驶行为检测 - python opencv cnn

文章目录 0 前言1 课题背景2 相关技术2.1 Dlib人脸识别库2.2 疲劳检测算法2.3 YOLOV5算法 3 效果展示3.1 眨眼3.2 打哈欠3.3 使用手机检测3.4 抽烟检测3.5 喝水检测 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习加…

AJAX--Express速成

一、基本概念 1、AJAX(Asynchronous JavaScript And XML)&#xff0c;即为异步的JavaScript 和 XML。 2、异步的JavaScript 它可以异步地向服务器发送请求&#xff0c;在等待响应的过程中&#xff0c;不会阻塞当前页面。浏览器可以做自己的事情。直到成功获取响应后&#xf…

1558. 得到目标数组的最少函数调用次数

1558. 得到目标数组的最少函数调用次数 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 1558. 得到目标数组的最少函数调用次数 https://leetcode.cn/problems/minimum-numbers-of-function-calls-to-make-target…

毛玻璃用户卡交互

效果展示 页面结构组成 从效果展示可以看到&#xff0c;此效果都是比较常规的。主要的核心就是卡片的悬停效果。 CSS 知识点 backdrop-filter 回顾transitiontransform 页面基础布局实现 <section><div class"container"><div class"card&q…

Academic accumulation|社会创业研究:过去的成就和未来的承诺

文献来源&#xff1a;Saebi T, Foss N J, Linder S. Social entrepreneurship research: Past achievements and future promises[J]. Journal of management, 2019, 45(1): 70-95. 一、文章介绍 &#xff08;一&#xff09;文章主要包含什么&#xff1f; SE越来越受到学术界的…

凉鞋的 Unity 笔记 104. 测试所涉及的窗口

104. 测试所涉及的窗口 在上一篇&#xff0c;笔者简单介绍了检视器窗口&#xff0c;如图所示&#xff1a; 我们接着介绍上图中的最后一个部分内容&#xff0c;测试部分。 测试部分我们只做了一件非常简单的操作&#xff0c;就是点击了一下运行按钮&#xff0c;查看结果&#…

【浅记】分而治之

归并排序 算法流程&#xff1a; 将数组A[1,n]排序问题分解为A[1,n/2]和A[n/21,n]排序问题递归解决子问题得到两个有序的子数组将两个子数组合并为一个有序数组 符合分而治之的思想&#xff1a; 分解原问题解决子问题合并问题解 递归式求解 递归树法 用树的形式表示抽象递…

JAVA面经整理(4)

一)Volitaile关键字的作用: volatile的使用:常常用于一写多读的情况下&#xff0c;解决内存可见性和指令重排序 JAVA内存的JMM模型:主要是用来屏蔽不同硬件和操作系统的内存访问差异的&#xff0c;在不同的硬件和不同的操作系统内存的访问是有差异的&#xff0c;这种差异会导致…

C. Best Binary String

题目&#xff1a;样例&#xff1a; 输入 4 ??01? 10100 1??10? 0?1?10?10输出 00011 10100 111101 011110010 思路&#xff1a; 根据题意&#xff0c; 题目意思是 ‘&#xff1f;’ 字符 该替换何值&#xff0c;使得原字符串&#xff0c;最少操作 翻转任意区间&#…