炸鸡派-PWM基础例程

发布于:2025-07-07 ⋅ 阅读:(18) ⋅ 点赞:(0)

PWM

main.c

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();

  /*DMA初始化*/
  MX_DMA_Init();

  MX_USART1_UART_Init();

  /*定时器11初始化*/
  MX_TIM11_Init();

  /*定时器2初始化*/
  MX_TIM2_Init();

  /*串口接收DMA配置*/
  HAL_UART_Receive_DMA(&huart1, RXbuf, 50);

  /*串口空闲中断使能*/
  __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);

  /*定时器11基础中断打开*/
  HAL_TIM_Base_Start_IT(&htim11);

  /*定时器2通道3PWM打开*/
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
  while (1)
  {
    if(timecount >= 500)
    {
      timecount = 0;
      printf("500ms time up\r\n");
      HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    }
  }
}

定时器11初始化

        TIM1、TIM8、TIM9、TIM10、TIM11等定时器都挂载在APB2总线上。

        系统时钟初始化的时候用的高速内部时钟,16Mhz。

APB2拉满100Mhz,定时器也是100Mhz
void MX_TIM11_Init(void)
{
  htim11.Instance = TIM11;
  htim11.Init.Prescaler = 99;
  htim11.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim11.Init.Period = 999;
  htim11.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim11.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim11) != HAL_OK)
  {
    Error_Handler();
  }
}

        初始化得到1ms一个中断。

        定时器溢出值和预分频值都是从0开始计数。

        定时时间1ms一次。

定时器2初始化PWM

void MX_TIM2_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};  // 定义主配置结构体
  TIM_OC_InitTypeDef sConfigOC = {0};           // 定义输出比较配置结构体

  htim2.Instance = TIM2;                        // 指定定时器实例为 TIM2
  htim2.Init.Prescaler = 99;                    // 预分频器值,设置时钟分频
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;  // 计数模式:向上计数
  htim2.Init.Period = 999;                      // 自动重装载值
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 时钟分频因子
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; // 禁用自动重装载寄存器的预装载
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)       // 初始化定时器为 PWM 模式
  {
    Error_Handler();                            // 初始化失败,调用错误处理函数
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; // 主输出触发信号配置为复位
  /*
    在主从同步模式下,主定时器的 TRGO 信号可以被用作从定时器的触发输入(ETR)。
    如果不需要使用 TRGO 信号,将其设置为 TIM_TRGO_RESET 可以确保不会意外触发其他外设或定时器。
  */

  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; // 禁用主从模式

  // 配置主从同步
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) 
  {
    Error_Handler();                            // 配置失败,调用错误处理函数
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;           // 输出比较模式:PWM1
  sConfigOC.Pulse = 800;                        // 捕获/比较寄存器的值
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;   // 输出极性:高电平有效

  /*启用快速输出模式(TIM_OCFAST_ENABLE)时,
    定时器的输出比较事件(如 PWM 信号的更新)会更快地反映到输出引脚上,
    减少延迟。在大多数应用场景中,
    默认配置为禁用快速输出模式(TIM_OCFAST_DISABLE),
    因为这可以确保系统的稳定性和兼容性*/
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;    // 禁用快速模式
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) // 配置定时器通道 3 为 PWM 输出
  {
    Error_Handler();                            // 配置失败,调用错误处理函数
  }

  HAL_TIM_MspPostInit(&htim2);                  // 执行与硬件相关的初始化(如 GPIO 配置)
}

TIM1_TRG_COM_TIM11_IRQHandler

        复合中断处理函数,它同时处理以下中断源:

  1. TIM1 的触发(Trigger)事件

    • 当定时器 1 的触发输入(如外部触发信号或内部触发信号)被检测到时,会触发该中断。

  2. TIM1 的通信(Communication)事件

    • 包括以下具体事件:

      • 更新事件(UEV):当定时器计数器溢出或通过软件触发时。

      • 捕获/比较事件(CCx):当定时器捕获或比较事件发生时。

  3. TIM11 的中断事件

    • 定时器 11 的所有中断请求也会被这个中断处理函数处理。

PWM带死区

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM1_Init();
  if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  } 

  while (1)
  {
  }
}

TIM1初始化PWM带死区

void MX_TIM1_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

	/*TIM1 初始化句柄*/
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 9;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 199;
  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 = 99;
  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();
  }
	
	/*死区时间配置*/
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 20;
  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();
  }

  HAL_TIM_MspPostInit(&htim1);

}