STM32CubeMX与HAL库开发教程五(PWM输出)

发布时间:2024年01月24日

目录

1、生成PWM波

2、与生成PWM波相关的HAL函数

3、STM32CubeMX配置


1、生成PWM波

????????PWM就是脉冲宽度调制,是一种对模拟信号电平进行数字编码的方法,PWM波就是具有一定占空比的方波信号,通过定时器的设置可以控制方波的频率和占空比,从而对模拟电压进行数字编码,理论上,只要带宽足够(PWM波的频率足够高)任何模拟值都可以使用PWM进行编码,使用定时器生成PWM波的工作原理是边缘对齐方式

????????其基本工作原理描述如下

1、设置自动重装载寄存器ARR的值,这个值决定了PWM波一个周期的长度,比如PWM一个周期是100ms

2、设置捕获/比较寄存器CRR的值,在一个ARR计数周期内,当计数器值CNT<CCR时,PWM参考信号OCxREF(x表示定时器编号)为高电平,当CNT>=CCR时,PWM参考信号OCxREF为低电平,并且产生CC(捕获/比较)事件,所以CCR的值决定了占空比,例如一个PWM周期为100ms,设置CCR的值让PWM波一个周期内高电平时间长为70ms,则占空比为70%

3、在计数器的值达到ARR时,产生UEV中断事件,CCR具有预装载功能,修改的CCR值需要在下一个UEV事件才能生成

2、与生成PWM波相关的HAL函数

????????与生成PWM波相关的HAL函数如下表所示,还有以DMA方式启动和停止PWM的函数,但定时器基本不使用DMA方式,后文也不会列出各种模式DMA相关函数,以下函数的用法与前面篇章的基础定时器函数用法类似,其头文件在stm32f1xx_hal_tim.h

其中还有几个重要的函数需要我们记录一下

HAL_TIM_PWM_PulseFinishedCallback()这是PWM的中断回调函数

__HAL_TIM_SET_COMPARE() 这个函数可以改变占空比的值,实例中会用到

__HAL_TIM_GET_COMPARE() 这个函数可以读取占空比的值,实际都是对寄存器CCR操作

3、STM32CubeMX配置

????????CubeMX中通道以上的配置我们都在以前介绍过了,现在先介绍通道中的选项都是什么意思

????????我们先随便选择一个定时器,设置定时器时钟源为内部时钟信号,然后选择通道打开PWM,这里我们可以选择是否打开定时器中断,如果打开后每次触发PWM中断都会跳转到定时器中断回调函数中,需要我们用户自己编写

????????到我们配置定时器PWM参数的时候了,上面这部分和基础定时器中的设置是一样的,我们修改ARR和PSC即可,这里我设置的是20KHZ,频率的计算方式就是周期的倒数,其他的默认设置即可,我们来介绍以下PWM中特有的设置?

  • Mode? ?选择PWM模式1 (一般都用模式1,递增状态下CNT<CCR通道就是有效状态,否则就是无效状态,递减就是CNT>CCR为有效状态,模式二反过来而已)
  • Pulse(占空比值)??先给0 (可以自己设置占空比)
  • Fast Mode???PWM脉冲快速模式? ? :? 和我们配置无关,不使能
  • PWM 极性:? ?设置为低电平? ? ? ? PS:??由于LED是低电平点亮,所以我们把极性设置为low

配置CubeMX结束后就可以生成工程了,我们这里简单来写一个呼吸灯,首先不要忘记在我们生成的tim,c文件中将定时器PWM打开哦,否则使用不了,先开启定时器然后再开启PWM模式

void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

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

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 3600-1;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

     HAL_TIM_Base_Start(&htim1);  /* 先开启定时器 */
	 HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);  /* 启动PWM输出 */
	
  /* USER CODE END TIM1_Init 2 */
  HAL_TIM_MspPostInit(&htim1);

}

接下来附带流水灯的程序

  while (1)
  {
  /* USER CODE END WHILE */
 
  /* USER CODE BEGIN 3 */
 
	  while (pwmVal< 500)
	  {
		  pwmVal++;
		  __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, pwmVal);    //修改比较值,修改占空比
//		  TIM1->CCR1 = pwmVal;    与上方相同
		  HAL_Delay(1);
	  }
	  while (pwmVal)
	  {
		  pwmVal--;
		  __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, pwmVal);    //修改比较值,修改占空比
//		  TIM1->CCR1 = pwmVal;     与上方相同
		  HAL_Delay(1);
	  }
	  HAL_Delay(200);
 
  /* USER CODE END 3 */
 }

文章来源:https://blog.csdn.net/2301_77866762/article/details/135755769
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。