【工具使用】STM32CubeMX-定时器PWM配置

news2024/10/7 18:27:37

一、概述

    无论是新手还是大佬,基于STM32单片机的开发,使用STM32CubeMX都是可以极大提升开发效率的,并且其界面化的开发,也大大降低了新手对STM32单片机的开发门槛。
    本文主要讲述STM32芯片定时器PWM功能的配置及其相关知识。

二、软件说明

    STM32CubeMX是ST官方出的一款针对ST的MCU/MPU跨平台的图形化工具,支持在Linux、MacOS、Window系统下开发,其对接的底层接口是HAL库,另外习惯于寄存器开发的同学们,也可以使用LL库。STM32CubeMX除了集成MCU/MPU的硬件抽象层,另外还集成了像RTOS,文件系统,USB,网络,显示,嵌入式AI等中间件,这样开发者就能够很轻松的完成MCU/MPU的底层驱动的配置,留出更多精力开发上层功能逻辑,能够更进一步提高了嵌入式开发效率。
    演示版本 6.7.0

三、定时器PWM功能简介

    定时器,顾名思义,就是定时的功能,定时器在单片机中算是除GPIO外最基本的外设。在ST中,定时器分为几种,基础定时器,通用定时器,高级定时器和低功耗定时器。其中定时器除了用作定时外,还可以用作输入捕获、比较输出、PWM输出等功能。本文重点介绍PWM输出的功能配置。
    脉宽调制(Pulse Width Modulation),简称PWM或P波,其实就是输出像方波一样的波型。其中PWM有几个比较重要的参数,一是频率(周期),二是占空比,三是幅值。
在这里插入图片描述

    之前我们已经介绍过基础定时器,基础定时器里只有最简单的定时功能,而本文要使用的是PWM,基础定时器是无法满足此功能的,那么这里就得来看下通用定时器。
在这里插入图片描述
    这个框图比基础定时器要复杂一些,这里我们把它拆成四部分,基础定时、触发源、输入部分和输出部分。虽然框图这么划分,但实现基础定时、输入和输出的预分频、重装载值、计数值这部分是重叠的。输入和输出更是共用了捕获/比较的寄存器。
基础定时:这一块跟之前基础定时器的配置方式是一样的,可以参考那一篇文章STM32CubeMX-基础定时器配置。
触发源:用于触发启动定时器的功能。
输入部分:可用来配置输入捕获的功能,一般用作频率检测、电平翻转触发等。本文重点为PWM,所以输入部分在其他文章里再详细说明。
输出部分:可用来配置比较输出和PWM输出。

    这里重点关注下PWM相关的配置项。
PSC prescaler(预分频):用于将定时器的输入时钟分频使用,比如单片机当前芯片主频为48M,给到定时器的时钟也为48M,但由于功耗或实际应用场景等原因,并不需要定时器以这么高频率进行计数,那就可以使用预分频将频率降低。比如来个48分频,那实际定时器计数频率就是1MHz。需要注意的是,这个寄存器默认值为0,即一分频,所以想要设置48分频,应该设置寄存器的值为47,即设置值=预分频系数-1

CNT counter(计数值):这个就是定时器工作时的计数值,当定时器启动时,该寄存器每隔一个时钟周期会往上加1,直到计数值溢出(16位的定时器上溢值就是2的16次方,即65535)或在开启自动重装载功能时达到重装载值,则清0。

Auto-reload register(重装载值):在开启了自动重装载功能后,当CNT计数值大于该设定值时,CNT计数值会自动清0重新计数。所以重装载值的设定值,一般也是需要设置目标值-1,也就是如果想要计10个数,那只要设置9即可。

Capture/Compare x register(x通道的捕获/比较寄存器):当定时器某一通道配置为PWM功能时,该通道的此寄存器则作为比较寄存器。当CNT计数值大于该寄存器值时,输出电平翻转。

Output control(输出控制器):这个用来总体控制输出的开关。

    预分频系数和重装载值这两个就决定了PWM的属性之一:频率。具体计算公式如下:

PWM频率 = (系统时钟频率 / 预分频系数) / 重装载值

    而比较值和重装载值这两个就决定了PWM的另一个属性之一:占空比。具体计算公式如下:

PWM占空比 = 比较值 / 重装载值

    可以看到这个定时器是有4个独立通道的,但4个通道共享一个分频系数和重装载值。所以当使用同个定时器输出多个PWM通道时,其频率是共享的,只有占空比可以独立设置。如果真的需要不同通道设置不同的频率,那只能选择使用不同的定时器。
    那除了通用定时器,其他类型的定时器是否也有PWM呢?看下高级定时器,这里也有PWM的功能,甚至比通用定时器的PWM功能更丰富。从系统框图上最直观可以看到就是多了一路BKIN,一般是用在电机控制上紧急关闭输出的。在这里插入图片描述
    另外需要注意的一个点是,因为高级定时器一般用在电机控制上,电机控制一般是需要2~3路PWM按一定的时序输出的,所以使用PWM时,高级定时器比通用定时器需要多开一个总输出的寄存器。

四、定时器配置

    这里我们来实现一个高级一点的点灯方式——呼吸灯。首先呼吸灯就是让LED的亮度从灭到亮无级过度,看起来就像是人呼吸一样顺畅。那怎么做到让LED亮度无级调节呢?最直接的方法就是调节控制LED灯的电压,前面知道了点亮一个LED灯是需要给一个3.3V的电压值,那如果我们给一个2V的电压值,那LED灯的亮度是不是就会比原本3.3V暗一些。但怎么调节给定的电压值呢?这里可以用PWM技术来处理。幅值为3.3V,占空比为50%的PWM,其平均电压为3.3*50%=1.65V。这里还有个问题,就是PWM的频率应该设置多少?这里只需要设置一个人眼看不出灯闪的频率即可,先初定一个2kHz。知道原理后,就可以开始对PWM进行设置了。

在这里插入图片描述

    首先选择需要控制的IO口(需要确定该IO口是否具备定时器通道输出的功能),这里我们用的是开发板的PA5口,也就是LED灯的那个端口,选择TIM2_CH1。然后在左边的菜单框中选择Timers->TIM2,在弹出的菜单栏中,找到Clock Source,配置成Internal Clock,即使用内部时间作为时钟源。再配置Channel1为PWM Generation CH1,即PWM功能。
在这里插入图片描述
Slave Mode(从机模式):可以在多种模式下与外部触发器同步,可配置为重置模式(输入出现上升沿时复位定时器计数并更新寄存器值)、门控模式(输入高电平时启动计数,输入低电平时停止计数,不重置寄存器)和触发模式(输入出现上升沿时启动计数,不能控制停止)。
Trigger Source(触发源):就上面框图里可用的ITR0~4等触发源,用来触发定时器工作,如果由软件启动,则不需要配置此项。
Clock Source(时钟源):一般使用内部时钟源即可。
Channel x(第x通道):可以配置每个通道的功能,比如PWM输出,比较输出,输入捕获等,当配置为PWM或比较输出时,还可以选配是否从端口输出,选择不输出的一般是用作当计数值达到某个设定阀值时,触发一个中断,这种应用可以不需要端口输出电平。
One Pulse Mode(单脉冲模式):启用该功能时,当定时器计数值达到重装载值时停止计数。

    接下来就是配置PWM的相关参数。首先根据系统时钟的频率配置定时器的预分频系数,因为当前主频配置为48M,为了比较方便地得到2kHz的频率,这边配置为48分频,所以Prescaler值应该设定为48-1=47。然后计数模式默认按向上计数即可,重装载值配置为499(因为定时器分频后频率为1MHz,所以计数值累加一次时间为1us,每计500次为一个周期,其频率即为2kHz,所以将重装载值配置为500,同样的因从0开始计数,设置寄存器时也需要将其-1设置)。最后开启自动重装载功能即可。因为我们现在要实现的功能是呼吸灯,所以需要输出的PWM占空比是需要实时改变的,因此这里Pulse可配可不配,具体数值在代码里体现。
在这里插入图片描述

Prescaler(预分频):用于将定时器的输入时钟分频使用,比如单片机当前芯片主频为48M,给到定时器的时钟也为48M,但由于功耗或实际应用场景等原因,并不需要定时器以这么高频率进行计数,那就可以使用预分频将频率降低。比如来个48分频,那实际定时器计数频率就是1MHz。需要注意的是,这个寄存器默认值为0,即一分频,所以想要设置48分频,应该设置寄存器的值为47,即设置值=预分频系数-1
Counter Mode(计数类型):可配置为向上计数和向下计数两种模式,向上计数则是定时器的计数正常向上累加,达到溢出值后清0,向下计数则是定时器的计数向下递减,减至0时将计数值恢复至最大值。
Counter Period(重装载值-32位):在开启了自动重装载功能后,当CNT计数值大于该设定值时,CNT计数值会自动清0重新计数。所以重装载值的设定值,一般也是需要设置目标值-1,也就是如果想要计10个数,那只要设置9即可。
Internal Clock Division(内部时钟分频):用于对内部时钟进行分频,可以配置为二分频和四分频。
auto-reload preload(自动重装载):开启自动重装载功能后,如果配置的计数类型是向上计数时,当计数值大于重装载值时,定时器会自动将计数值清0重新开始计数;如果配置的计数类型是向下计数,则当计数值为0时,定时器自动将计数值设置为重装载值。

    然后就是PWM模式下PWM Generation Channel x那一项的相关配置。
Mode(PWM的模式):有两种模式,分别是PWM1和PWM2,设置为PWM1时,如果设置为向上计数,则当计数值<比较值时,输出低电平;如果设置为向下计数,则当计数值>比较值时,输出低电平。PWM2则与之相反。
Pulse(输出比较值):当计数值超过该设定值时,电平翻转,所以PWM的占空比即由该寄存器值/重装载值可得。
Output compare preload(输出比较值预加载):当使能此功能时,设置Pulse输出比较值时,该值不会立即生效,而是会等到当前PWM完成一个周期的输出后才把当前值设置至Pulse输出比较值的寄存器中。这样可以实现设置的平滑切换。不使能则是立即生效。这里建议使能该功能。
Fast Mode(快速模式):快速模式选择,当需要输出高速PWM时则选配此功能。
CH Polarity(通道极性):用来配置PWM输出的初始电平极性,当配置为High(高)时,默认为高电平;配置为low(低)时,则默认为低电平。

  • HAL库代码实现

    因为CubeMX已经配置好PWM的频率,生成工程后,只需要调用启动PWM的接口即可。而要实现呼吸灯的效果,只要循环修改定时器的比较值,也就是让PWM输出的占空比从0%到100%,再从100%到0%。每次设置时需要增加一个延时,防止呼吸过于急促。

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  uint32_t duty = 0;
  uint32_t pre_d, comp_d = 0;
  uint8_t dir = 0;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
	
  /* 开启定时器 */
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  
  /* 获取当前定时器重装载值 */
  pre_d = __HAL_TIM_GET_AUTORELOAD(&htim2);
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	/* 占空比由0~100再从100到0循环,单位% */
	if (dir == 0)
	{
	    duty++;
	}
	else
	{
	    duty--;
	}
	if (duty >= 100)
	{
	    dir = 1;
	}
	else if (duty == 0)
	{
	    dir = 0;
	}
	
	/* 延个时,防止呼吸过快 */
	HAL_Delay(10);
	
	/* 根据占空比计算比较值 */
	comp_d = pre_d * duty / 100;
	
	/* 设置比较值 */
       if (__HAL_TIM_GET_COMPARE(&htim2, TIM_CHANNEL_1) != comp_d)
	{
		__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, comp_d);
	}
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
  • LL库代码实现

    同样的,仿照HAL库的实现方式,调用相应的LL库接口。首先是初始化部分,HAL库简化后核心逻辑如下,其实就只是使能当前通道后打开定时器而已,中间使能总输出只在高级定时器中才需要。
在这里插入图片描述
    其他接口在LL库均能找到对应的接口,这里就直接上代码了。当然,使用LL库的时候,还是记得需要把生成代码库切成LL库。
在这里插入图片描述

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  uint32_t duty = 0;
  uint32_t pre_d, comp_d = 0;
  uint8_t dir = 0;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG);
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);

  /* SysTick_IRQn interrupt configuration */
  NVIC_SetPriority(SysTick_IRQn, 3);

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
	
  /* 使能通道 */
  LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1);

  /* 使能总输出 */
  LL_TIM_EnableAllOutputs(TIM2);

  /* 使能定时器 */
  LL_TIM_EnableCounter(TIM2);

  /* 获取当前定时器重装载值 */
  pre_d = LL_TIM_GetAutoReload(TIM2);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	/* 占空比由0~100再从100到0循环,单位% */
	if (dir == 0)
	{
	    duty++;
	}
	else
	{
	    duty--;
	}
	if (duty >= 100)
	{
	    dir = 1;
	}
	else if (duty == 0)
	{
	    dir = 0;
	}
	
	/* 根据占空比计算比较值 */
	comp_d = pre_d * duty / 100;
	
	/* 延个时,防止呼吸过快 */
	LL_mDelay(10);
	
	/* 设置比较值 */
	if (LL_TIM_OC_GetCompareCH1(TIM2) != comp_d)
	{
		LL_TIM_OC_SetCompareCH1(TIM2, comp_d);
	}
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
  • 效果演示

    烧录软件至开发板中,可以看到呼吸灯的效果。
在这里插入图片描述

五、注意事项

1、留意预分频系数和重装载值设置的时候都是要减1处理,也就是想要2分频,PSC需要设置为1,想要计数10次复位,则需要给重装载值设置9。
2、配置完生成的工程,并不会在初始化的时候就给打开计数,需要在使用过程中自行调用LL库打开。
3、使用高级定时器实现PWM功能时,需要多一个总输出的控制,否则端口不会输出PWM。
4、同个定时器的不同通道只能是相同的频率,需要输出不同频率的PWM波,需要使用不同的定时器。

六、相关链接

对于刚入门的小伙伴可以先看下STM32CubeMX的基础使用及Keil的基础使用。
【工具使用】STM32CubeMX-基础使用篇
【工具使用】Keil5软件使用-基础使用篇
定时器的基础认识及配置可参考基础定时器的配置。
【工具使用】STM32CubeMX-基础定时器配置

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

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

相关文章

「Verilog学习笔记」优先编码器电路①

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1ns//优先编码器电路1 //电路的优先顺序是&#xff0c;从9到1&#xff0c;高级到低级 //9个输入端&#xff1a;I端&#xff0c;4个输出端&#xff1a;Y端&am…

ACM练习——第一天

因为最近要去农大参加他们的算法邀请赛&#xff0c;然后赛制是ACM赛制的&#xff0c;所以我就直接很迷茫。 然后我就找到了牛客的ACM练习题&#xff0c;好好的练习一下ACM写法&#xff0c;而且我还要被迫写C&#xff0c;哭了。 开始钻研 1.从Java过度到C 题目源于牛客网&…

【系统安装】ubuntu20.04安装,正经教程,小白安装教程,百分百成功安装

1、安装的前提是有启动盘&#xff0c;这个比较好处理&#xff0c;清华源找到ubuntu20.04.iso镜像文件下载&#xff0c;然后用Rufus来制作启动盘就可以了&#xff0c;需要注意的是目标文件系统需要是UEFI&#xff0c;其他的话就没太多要求了&#xff0c;如果卡在这一步的话&…

dameng数据库数据id decimal类型,精度丢失

问题处理 这一次也是精度丢失&#xff0c;但是问题呢还是不一样&#xff0c;这一次所有的id都被加一了&#xff0c;只有id字段被加一&#xff0c;还有的查询查出来封装成对象之后对象的id字段被减一了&#xff0c;数据库id字段使用的decimal&#xff08;20,6&#xff09;&…

JumpServer管理虚拟机

环境准备 1.虚拟机192.168.1.111在线安装JumpServer https://blog.csdn.net/tongxin_tongmeng/article/details/1340166222.虚拟机192.168.1.112创建用户changwq、wangwj useradd changwq && passwd changwq、useradd wangwj && passwd wangwj3.虚拟机192.168.…

SecureCRT 超时自动断开连接问题解决方法

很多人在使用SecureCRT时&#xff0c;会遇到这种情况&#xff1a;SecureCRT 超时自动断开连接&#xff0c;这种情况会给工作带来很多不便&#xff0c; 比如在做数据库还原操作时&#xff0c;连接突然断掉了&#xff0c;会导致还原操作失败&#xff0c;很是令人困扰。 那么我们…

Js 保留关键字

JavaScript 关键字用于标识要执行的操作&#xff0c;和其他任何编程语言一样&#xff0c;JavaScript 保留了一些关键字为自己所用&#xff1b;这些关键字有些在目前的版本中可能没有使用&#xff0c;但在以后 JavaScript 扩展中会用到。 以下是JS中最重要的保留关键字&#xf…

人工智能与光伏发电:携手共创智能能源未来

人工智能与光伏发电&#xff1a;携手共创智能能源未来 摘要&#xff1a;本文将探讨人工智能与光伏发电技术的结合&#xff0c;并分析它们如何共同推动智能能源领域的发展。本文将介绍这两项技术的基本原理、结合方式以及通过人工智能提升光伏发电系统的效率和可靠性。 一、引…

文心一言 VS 讯飞星火 VS chatgpt (134)-- 算法导论11.2 6题

六、用go语言&#xff0c;假设将n 个关键字存储到一个大小为 m 且通过链接法解决冲突的散列表中&#xff0c;同时已知每条链的长度&#xff0c;包括其中最长链的长度 L&#xff0c;请描述从散列表的所有关键字中均匀随机地选择某一元素并在 O(L(11/a))的期望时间内返回该关键字…

【论文精读】Pose-Free Neural Radiance Fields via Implicit Pose Regularization

今天读的是一篇发表在ICCV 2023上的文章&#xff0c;作者来自NTU。 文章地址&#xff1a;点击前往 文章目录 Abstract1 Intro2 Related Work3 Preliminary4 Proposed Method4.1 Overall Framework4.2 Scene Codebook Construction4.3 Pose-Guided View Reconstruction4.4 Train…

【带头学C++】----- 五、字符串操作函数 ---- 5.1 字符串操作函数

5.1字符串操作函数(以str开头的字符串处理函数默认遇到\0结束操作) 5.1.1 测量字符串的长度strlen() strlen() 函数用于计算一个字符串的长度。 #include <string.h> //注意&#xff1a;该头文件必须包含 size_t strlen(const char *s); // s指的是需要测量字符串的首地…

计算机二级Office真题解析 excel减免税,订单,成绩

第一题 1.将“Excel 减免税.xlsx”文件另存为 excel.xlsx&#xff0c;最后提交该文件&#xff08;1 分&#xff09;。 2.将“对应代码.xlsx”文件中的 sheet1 工作表插入到 excel.xlsx 中&#xff0c;工作 表名重命名为“代码”&#xff08;3 分&#xff09;。 3.在"序号&…

Rust 中的引用与借用

目录 1、引用与借用 1.1 可变引用 1.2 悬垂引用 1.3 引用的规则 2、slice 类型 2.1 字符串字面量其实就是一个slice 2.2 总结 1、引用与借用 在之前我们将String 类型的值返回给调用函数&#xff0c;这样会导致这个String会被移动到函数中&#xff0c;这样在原来的作用域…

2023年亚太杯数学建模思路 - 案例:FPTree-频繁模式树算法

文章目录 赛题思路算法介绍FP树表示法构建FP树实现代码 建模资料 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#…

git 命令行回退版本

git 命令行回退版本 git 命令行回退版本命令: 1.切换到需要回退的分支 git checkout branch-v2.0.02.更新远程分支 git fetch3.找到需要回退版本的版本号git revert a6914da55ff40a09e67ac2426b86f1212e6580eb4.清除工作区缓存git clean -df5.强制提交git push -f

[Linux] dns域名解析服务

一、DNS 1.1 DNS简介 域名解析&#xff1a;&#xff08;英文&#xff1a;Domain Name System&#xff0c;缩写&#xff1a;DNS&#xff09;是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便地访问互联网。DNS使用udp53和tcp53…

互联网Java工程师面试题·微服务篇·第三弹

目录 34、什么是端到端微服务测试&#xff1f; 35、Container 在微服务中的用途是什么&#xff1f; 36、什么是微服务架构中的 DRY&#xff1f; 37、什么是消费者驱动的合同&#xff08;CDC&#xff09;&#xff1f; 38、Web&#xff0c;RESTful API 在微服务中的作用是什…

C++字典树算法:找出强数对的最大异或值 II

涉及知识点 数学 字典树 题目 给你一个下标从 0 开始的整数数组 nums 。如果一对整数 x 和 y 满足以下条件&#xff0c;则称其为 强数对 &#xff1a; |x - y| < min(x, y) 你需要从 nums 中选出两个整数&#xff0c;且满足&#xff1a;这两个整数可以形成一个强数对&…

Mybatis框架——mybatis是什么

第一&#xff0c;mybatis是一个持久层的框架&#xff0c;它支持自定义SQL&#xff0c;存储过程以及高级映射。 mybatis几乎代替了所有的JDBC代码以及设置参数和获取结果集的工作&#xff0c;可以通过简单的XML或者注解来配置和映射原始类型、接口和Java POJO&#xff08;Plain…

webgoat-Challenges

AdminLostpassword 这一题密码藏在logo图片里 请求GET /WebGoat/challenge/logo 搜索admin看到密码&#xff0c;使用账号admin和这个密码登录拿到flag Without password 题目要求&#xff1a;在不知道Larry的密码情况下登录 考虑使用SQL注入 密码输入 123 or 11 -- Admin p…