STM32初学入门笔记(2):STM32CubeMX配置STM32输出可调PWM方波

这篇具有很好参考价值的文章主要介绍了STM32初学入门笔记(2):STM32CubeMX配置STM32输出可调PWM方波。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

PWM是一种应用广泛的利用微处理器的数字输出来对模拟电路进行控制的一种技术(即对脉冲宽度的控制)PWM同时也是驱动蜂鸣器,驱动舵机,通信等重要的一环,而对于初学者而言,点完灯的下一个程序就是驱动蜂鸣器,本篇将讲述如何使用及调整PWM输出频率,占空比

工程文件可入Q群:659512171获取

 PWM简介:

对于STM32,PWM输出依靠定时器,而在STM32F103c8t6中,共有4个定时器可供输出,每个都可以配置4路输出,所以总共可以输出16路PWM,本篇只介绍和应用单路PWM输出。

工程开始:

新建工程:

打开STM32CubeMX,新建工程,配置外部高速时钟:

stm32cubemx输出pwm,STM32,stm32,单片机,笔记

 stm32cubemx输出pwm,STM32,stm32,单片机,笔记

 输入需要的频率,敲击回车,STM32CubeMX会自动配置(在这里我把时钟频率设为了最高72,但其实不设也行,在后面的分频改一下就好了)

配置调试:

这里一定要选好,不然会导致芯片自锁

配置工程文件:

stm32cubemx输出pwm,STM32,stm32,单片机,笔记

配置计时器:

 下面对这其中的3个值进行说明:

预分频(psc):CPU运行频率先经过它分频再进入计时器,如CPU运行在 x Mhz 下,预分频为 y,那进入计时器的频率也就为 x/(y+1) Mhz(因为从0计数,所以是y+1)。

自动重装值(arr):指一次周期的计数长度

脉冲长度:指输出脉冲的计数长度

在这里就可以知道怎么调节频率于占空比了,首先,在预分频(y)和主频(x)一定的情况下,要保持输出 a% 占空比的 b Hz 的方波,那么自动重装值就应该是 x / (y+1) / b ,而脉冲长度也就应该是 (x / (y+1) / b) * a%,所以只需要写一个函数调节自动重装值和脉冲长度就可以实现调节频率和占空比的目的了。stm32cubemx输出pwm,STM32,stm32,单片机,笔记

这里我分别把预分频、自动重装值、脉冲长度设置为了 999、1440、720,所以频率和占空比分别应为:72,000,000 / (999+1)/1440 = 50 (Hz),1440 / 720 = 50%

然后点击右上角的GENERATE CODE生成文件,然后打开。

Keil配置: 

频率占空比调节方式一:

 打开main.c,tim.c,tim.h文件:

stm32cubemx输出pwm,STM32,stm32,单片机,笔记( .h文件可以在引用中通过右键打开)

找到 "MX_TIM2_Init" 函数stm32cubemx输出pwm,STM32,stm32,单片机,笔记

 可以看到我们设置的参数都在这个初始化函数里了,接下来只需要设置2个变量替换其中2个具体值。

stm32cubemx输出pwm,STM32,stm32,单片机,笔记stm32cubemx输出pwm,STM32,stm32,单片机,笔记

将上面这一段代码复制到下面的  /* USER CODE BEGIN 1 */  和  /* USER CODE END 1 */  区间里,并把上面这一段代码注释掉(删掉也可以),

接着,更改一下后面括号中的数据(原本是 void,无类型,现在要换成数据),只需要设置自动重装值和脉冲长度的变量:

/* USER CODE BEGIN 1 */
void MX_TIM2_Init(uint16_t arr, uint16_t pul)
{

  /* 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 = 1000;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = arr;
  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 = pul;
  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);

}

/* USER CODE END 1 */

另外,还需要在tim.h中更改对此函数的声明,不然是报错不通过的,也无法在主程序中引用,同样把函数声明移到用户区域里,并注释掉:

stm32cubemx输出pwm,STM32,stm32,单片机,笔记

/* USER CODE BEGIN Prototypes */
void MX_TIM2_Init(uint16_t arr, uint16_t pul);
/* USER CODE END Prototypes */

 如果你觉得每次都写 HAL_TIM_PWM_Start 和 HAL_TIM_PWM_Stop 太麻烦,可以再加一个PWM开启/关闭函数,同样是在用户区域写如下函数:

void PWM (int onoff)
{
	if (onoff == 0){
		HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
	}else if (onoff == 1){
		HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
	}
}

 以及函数声明:

void PWM (int onoff);

在这里当数据为0时,停止PWM,当为1时,开启PWM 

最后,tim.c中的用户端应是如下代码:

/* USER CODE BEGIN 1 */
void MX_TIM2_Init(uint16_t arr, uint16_t pul)
{

  /* 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 = 1000;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = arr;
  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 = pul;
  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);

}

void PWM (int onoff)
{
	if (onoff == 0){
		HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
	}else if (onoff == 1){
		HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
	}
}
/* USER CODE END 1 */

整个tim.h应是如下代码:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    tim.h
  * @brief   This file contains all the function prototypes for
  *          the tim.c file
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TIM_H__
#define __TIM_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

extern TIM_HandleTypeDef htim2;

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

//void MX_TIM2_Init(void);

void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);

/* USER CODE BEGIN Prototypes */
void MX_TIM2_Init(uint16_t arr, uint16_t pul);
void PWM (int onoff);
/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif

#endif /* __TIM_H__ */

最后,在main.c中引用就行了,记得要把初始化的参数填上去,这里给出一个实例(整个int main函数) :

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* 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(1440,36);
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		PWM(1);
		HAL_Delay(1500);
		PWM(0);
		MX_TIM2_Init(1440,180);
		PWM(1);
		HAL_Delay(1500);
		PWM(0);
		MX_TIM2_Init(1440,36);
  }
  /* USER CODE END 3 */
}

 这里先是初始化PWM输出为50HZ,脉宽0.5ms(即2.5%占空比)的信号,然后打开PWM输出,延时1.5秒后关闭,再配置为50Hz,脉宽2.5ms(即12.5%占空比)的信号,然后再次打开输出,延时1.5秒后关闭并重新配置为50HZ,脉宽1ms的信号,这两个分别是舵机的0°,180°信号,可以让连接在tim2的一通道(即PA0)的舵机在0°到180°间重复旋转,效果如下:

stm32cubemx输出pwm,STM32,stm32,单片机,笔记

相信大家也看到了,这种方式来调节频率和占空比麻烦且会有一段时间的空缺,会影响到对波形比较敏感的设备,所以接下来介绍第二种方式

方式二:

前面过程的都与第一种方式相同,可以完全保留,第一种方式的调节函数可以作为初始化使用,此方式无需编写任何函数,调用了HAL库中的修改CCR(储存脉冲长度数值)和ARR(储存自动重装值)寄存器的函数,接下来直接上代码:

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* 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(1440,36);
  /* USER CODE BEGIN 2 */
  PWM(1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	HAL_Delay(1500);
    __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,180); //修改CCR寄存器
	HAL_Delay(1500);
    __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,36);
    /*
    __HAL_TIM_SET_AUTORELOAD(&htim2,1440); //修改ARR寄存器,没有通道限制,整个定时器一起改
    */
  }
  /* USER CODE END 3 */
}

 上面程序实现效果与第一种相同,但此程序可以在PWM运行时更改,无需关闭PWM,没有空缺

另外,对于频率的修改还可以通过改预分频系数来解决,但由于自动重装值与预分频之间是连除的关系,所以一般只修改自动重装值,修改预分频系数的函数如下:

__HAL_TIM_SET_PRESCALER(TIM_TypeDef* TIMx, uint32_t Prescaler);
/*举一个例子:
__HAL_TIM_SET_PRESCALER(&htim2, 1000);
这条语句就是把定时器二的预分频系数设为1000
*/

都看到这里了点点关注再走呗

 交流Q群:659512171文章来源地址https://www.toymoban.com/news/detail-630028.html

到了这里,关于STM32初学入门笔记(2):STM32CubeMX配置STM32输出可调PWM方波的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32 PWM模式与输出比较模式的区别。PWM占空比不生效,在STM32CubeMX中配置PWM的两种模式——蓝桥杯嵌入式

      🎊【蓝桥杯嵌入式】专题正在持续更新中,原理图解析✨,各模块分析✨以及历年真题讲解✨都已更新完毕,欢迎大家前往订阅本专题🎏 🎏【蓝桥杯嵌入式】蓝桥杯第十届省赛真题 🎏【蓝桥杯嵌入式】蓝桥杯第十二届省赛程序真题 🎏【蓝桥杯嵌入式】蓝桥杯第十三届

    2023年04月15日
    浏览(24)
  • STM32初学入门笔记(5):使用STM32CubeMX通过SPI,IIC驱动OLED屏幕

    随着时代的进步,OLED显示屏成为了继LCD显示屏之后的新一代显示屏技术,OLED具有可视角高,功耗低,厚度薄,耐冲击、振动能力强,像素响应时间低等优点,在嵌入式开发中,OLED显示器也是一个主要的部分,制作OLED显示模块的驱动也是学习STM32路上的重要一部分,本篇将从

    2024年02月04日
    浏览(20)
  • STM32主从模式实现两路同步PWM脉冲输出,频率、占空比可调

    原理:定时器1为主模式,定时器8为从模式,TIM1的定时器使能操作作为触发输出[TRGO]触发TIM8并使能TIM8的计数器,同时输出两路频率、占空比以及脉冲数量(小于256个,高级定时器重复计数功能为8位)可调PWM波形。 关键代码: 定时器1(TIM1)设为主模式: 定时器2(TIM8)设为从

    2024年02月13日
    浏览(20)
  • STM32 通过PWM输出一个方波并通过定时器输入捕获模式测量方波的周期(cubeMX+keil配置)

    前言:本文章用cubeMX和keil来进行代码编写,实现STM32的相应功能 本文章使用的STM32核心板是STM32H743VIT6,如果使用的是其他的核心板操作过程类似,可以尝试使用此教程。 (1)首先点击左侧的Timers  (2)选择一个定时器配置PWM 我选择的是TIM5,如上图 点击TIM5 Mode的配置如下

    2024年02月19日
    浏览(31)
  • 定时器(PWM输出)触发ADC采样(DMA)——STM32CubeMX

    我用的单片机是STM32F103CBTX 定时器:使用PWM输出的模式 ADC:使用DMA的模式 (在不使用DMA的情况下,定时器控制ADC进行数据采集只能是单通道!如果开启了多通道,读取到的ADC采集值只会是最后一个通道的值!所以,要想使用定时器控制ADC采集 多通道 , 必须使用DMA !)  看

    2024年04月10日
    浏览(29)
  • 步进电机简单使用:STM32 PWM输出固定数目的脉冲数(基于CubeMX)

    使用步进电机之前,我们需要了解步距角的概念:步进电机接收到一个脉冲转动的角度,步进电机步距角通常 为1.8°,即步进电机接收到一个脉冲转动1.8°,则若步进电机接收到360°/1.8°=200个脉冲,步进电机就能转动一圈 步进电机通过驱动器控制,驱动器如下图所示(都比较

    2024年02月06日
    浏览(18)
  • STM32开发(6)----CubeMX配置PWM

    本章介绍使用STM32CubeMX对PWM进行配置的方法,PWM的基本原理,并通过示波器来测试实现结果,如果有LED灯也可以,PWM控制LED灯的亮度。 PWM(Pulse Width Modulation)脉冲宽度调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。它是把每一脉冲宽度均相等

    2024年02月03日
    浏览(26)
  • STM32 HAL库 通用定时器介绍及相关应用例程 定时器中断 输出PWM (点亮LED呼吸灯、输出PWM、输入捕获) CubeMX

    (部分图引自于ATK) 前情提要(基本定时器) 点此进入 通用定时器类别 通用定时器和基本定时器相比大致的工作方式是相似的,不过通用定时器比基本定时器多了一些很好用的功能,比如: 外部输入捕获 输出比较 输出PWM 时钟源 CubeMX为我们提供了配置时钟的非常方便的工

    2024年04月15日
    浏览(49)
  • 搭建stm32电机控制代码框架(五)——Stm32CubeMx配置PWM

    采样配置完成后,进行PWM的配置。PWM的生成依赖于STM32的TIM1定时器,其功能完备如下图所示,电机控制中主要应用其PWM生成功能。 我们当前阶段的目标是生成占空比为50%的三路PWM,其开关频率为10kHz。 那么开始CubeMx的配置,依据stm32f405数据手册中地址总线部分内容,TIM1是挂

    2024年02月16日
    浏览(21)
  • STM32学习笔记(一):输出PWM——HAL库

    本篇文章为个人参考总结所用,如果错误还望指出。 涉及的知识: 1、STM32CubeMx的部分使用 2、PWM原理及常用概念 3、用单片机生成一定频率的PWM 用到的软件及单片机: 1、STM32CubeMx 2、IDE: MDK-Keil软件 3、芯片:STM32F407ZGT6 4、开发板:正点原子探索者 注:不同型号的单片机实现

    2024年02月12日
    浏览(17)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包