一.概要

我们在STM32G474单片机开发入门(七)定时器PWM波输出与输入实战中介绍了脉冲宽度调制(PWM),是用TIM2_CH4实现输出,TIM2是一个通用定时器,STM32G474的特色就是还有一个高精度定时器HRTIM,接下去我们介绍下这个高精度定时器,以及如何用这个HRTIM定时器输出PWM波。
在这里插入图片描述

二.HRTIM高精度定时器特色

‌1.超高时间分辨率‌
通过170MHz,32倍频到5.44GHz,实现184ps分辨率,支持精确的PWM占空比和频率调整‌。我们原先的TIM1,TIM2定时时期时钟倍频只能到10ns级别的分辨率,所以HRTIM的精度高很多。HRTIM高精度定时器的定时单元还针对电压/温度变化进行补偿,确保稳定性‌。

2.多通道灵活控制‌
包含6个独立16位定时单元,每个单元带4个比较单元,可控制12个输出通道,每个通道支持最多32个设置/重置源‌。模块化架构适合多开关电源拓扑‌。

‌3.高级PWM功能‌
支持死区插入和互补PWM输出(通过软件配置实现硬件级互补)‌。提供Burst模式,可编程运行/空闲状态交替周期,降低开关损耗‌,支持单脉冲模式、重复计数和故障保护机制‌。

典型应用场景包括高频开关电源(如Buck-Bo拓扑)、电机控制和逆变系统‌。需注意其PWM配置复杂度较高,需合理设置Master Timer事件触发以避免丢波现象‌。

三.HRTIM高精度定时器框图

在这里插入图片描述
HRTIM内部结构框图如上所示,HRTIM包含1个主Master timer定时器单元,6个子定时器单元(A,B,C,D,E,F),这7个定时器单元,每个定时器单元可独立使用,亦可与其他耦合使用。
6个子定时器单元,每个单元内含:
• 16-bit 计数器
• 4x 16-bit 比较寄存器
• 2x 16-bit 捕获寄存器
• 2路PWM输出

Master timer定时器基于5.44GHz时钟驱动,提供184ps的超高分辨率‌,Master timer定时器没有PWM输出功能,子定时器可通过总线接收Master Timer的同步事件(如计数器复位、启动/停止计数)‌。

四.CubeMX配置HRTIM1输出50KHZ PWM波例程

1.硬件准备

STLINK接STM32G474RET6开发板,STLINK接电脑USB口,示波器探头接PB14脚。
在这里插入图片描述

2.创建CubeMX工程

如下图所示,打开STM32CubeMX软件,新建工程。
在这里插入图片描述
如下图所示,Part Number处输入STM32G474RE,再双击就创建新的工程。
在这里插入图片描述

如下图所示,配置下载口引脚,PA13为SWD的SWDIO脚,PA14为SWD的SWCLK脚。
在这里插入图片描述

如下图所示,配置HRTIM1,50Khz,50%占空比的PWM输出,PB14为PWM输出引脚。
在这里插入图片描述
在这里插入图片描述

如下图所示,配置系统主频170Mhz,使用外部8MHZ晶振。
在这里插入图片描述

配置工程文件名,保存路径,KEIL5工程输出方式,生成工程。
在这里插入图片描述
在这里插入图片描述

如下图所示,增加代码,添加PWM输出使能。
在这里插入图片描述
如下图所示,增加代码,添加TIMD_PERIOD分频系数宏定义,根据时钟频率,周期决定,倍频系数这里选择16,如果频率比较低,需要调低倍频系数。
在这里插入图片描述

主要代码如下

#define HRTIM_INPUT_CLOCK 170000000
#define TIMD_PWM_FREQ 50000
#define TIMD_DUTY_CYCLE 0.5
//由于有最低频率的限制,所以不同的频率可能需要修改宏定义
//比如100KHZ的PWM,宏定义需要改成#define TIMD_PERIOD ((uint16_t)((((uint64_t)HRTIM_INPUT_CLOCK) * 32) / TIMD_PWM_FREQ))
//同时初始化中同步修改pTimeBaseCfg.PrescalerRatio = HRTIM_PRESCALERRATIO_MUL32;
#define TIMD_PERIOD ((uint16_t)((((uint64_t)HRTIM_INPUT_CLOCK) * 16) / TIMD_PWM_FREQ))//定义周期




//#define HRTIM_PRESCALERRATIO_MUL32    (0x00000000U)  /*!< fHRCK: fHRTIM x 32U = 4.608 GHz - Resolution: 217 ps - Min PWM frequency: 70.3 kHz (fHRTIM=144MHz) */
//#define HRTIM_PRESCALERRATIO_MUL16    (0x00000001U)  /*!< fHRCK: fHRTIM x 16U = 2.304 GHz - Resolution: 434 ps - Min PWM frequency: 35.1 KHz (fHRTIM=144MHz) */
//#define HRTIM_PRESCALERRATIO_MUL8     (0x00000002U)  /*!< fHRCK: fHRTIM x 8U = 1.152 GHz - Resolution: 868 ps - Min PWM frequency: 17.6 kHz (fHRTIM=144MHz)  */
//#define HRTIM_PRESCALERRATIO_MUL4     (0x00000003U)  /*!< fHRCK: fHRTIM x 4U = 576 MHz - Resolution: 1.73 ns - Min PWM frequency: 8.8 kHz (fHRTIM=144MHz)    */
//#define HRTIM_PRESCALERRATIO_MUL2     (0x00000004U)  /*!< fHRCK: fHRTIM x 2U = 288 MHz - Resolution: 3.47 ns - Min PWM frequency: 4.4 kHz (fHRTIM=144MHz)    */
//#define HRTIM_PRESCALERRATIO_DIV1     (0x00000005U)  /*!< fHRCK: fHRTIM = 144 MHz - Resolution: 6.95 ns - Min PWM frequency: 2.2 kHz (fHRTIM=144MHz)         */
//#define HRTIM_PRESCALERRATIO_DIV2     (0x00000006U)  /*!< fHRCK: fHRTIM / 2U = 72 MHz - Resolution: 13.88 ns- Min PWM frequency: 1.1 kHz (fHRTIM=144MHz)     */
//#define HRTIM_PRESCALERRATIO_DIV4     (0x00000007U)  /*!< fHRCK: fHRTIM / 4U = 36 MHz - Resolution: 27.7 ns- Min PWM frequency: 550Hz (fHRTIM=144MHz)  

/* USER CODE END 0 */

HRTIM_HandleTypeDef hhrtim1;

/* HRTIM1 init function */
void MX_HRTIM1_Init(void)
{
  HRTIM_TimeBaseCfgTypeDef pTimeBaseCfg = {0};
  HRTIM_TimerCtlTypeDef pTimerCtl = {0};
  HRTIM_TimerCfgTypeDef pTimerCfg = {0};
  HRTIM_CompareCfgTypeDef pCompareCfg = {0};
  HRTIM_OutputCfgTypeDef pOutputCfg = {0};

  hhrtim1.Instance = HRTIM1;
  hhrtim1.Init.HRTIMInterruptResquests = HRTIM_IT_NONE;
  hhrtim1.Init.SyncOptions = HRTIM_SYNCOPTION_NONE;
  if (HAL_HRTIM_Init(&hhrtim1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_HRTIM_DLLCalibrationStart(&hhrtim1, HRTIM_CALIBRATIONRATE_3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_HRTIM_PollForDLLCalibration(&hhrtim1, 10) != HAL_OK)
  {
    Error_Handler();
  }
  pTimeBaseCfg.Period = TIMD_PERIOD;
  pTimeBaseCfg.RepetitionCounter = 0x00;
  pTimeBaseCfg.PrescalerRatio = HRTIM_PRESCALERRATIO_MUL16;
  pTimeBaseCfg.Mode = HRTIM_MODE_CONTINUOUS;
  if (HAL_HRTIM_TimeBaseConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_D, &pTimeBaseCfg) != HAL_OK)
  {
    Error_Handler();
  }
  pTimerCtl.UpDownMode = HRTIM_TIMERUPDOWNMODE_UP;
  pTimerCtl.GreaterCMP1 = HRTIM_TIMERGTCMP1_EQUAL;
  pTimerCtl.DualChannelDacEnable = HRTIM_TIMER_DCDE_DISABLED;
  if (HAL_HRTIM_WaveformTimerControl(&hhrtim1, HRTIM_TIMERINDEX_TIMER_D, &pTimerCtl) != HAL_OK)
  {
    Error_Handler();
  }
  pTimerCfg.InterruptRequests = HRTIM_TIM_IT_NONE;
  pTimerCfg.DMARequests = HRTIM_TIM_DMA_NONE;
  pTimerCfg.DMASrcAddress = 0x0000;
  pTimerCfg.DMADstAddress = 0x0000;
  pTimerCfg.DMASize = 0x1;
  pTimerCfg.HalfModeEnable = HRTIM_HALFMODE_DISABLED;
  pTimerCfg.InterleavedMode = HRTIM_INTERLEAVED_MODE_DISABLED;
  pTimerCfg.StartOnSync = HRTIM_SYNCSTART_DISABLED;
  pTimerCfg.ResetOnSync = HRTIM_SYNCRESET_DISABLED;
  pTimerCfg.DACSynchro = HRTIM_DACSYNC_NONE;
  pTimerCfg.PreloadEnable = HRTIM_PRELOAD_DISABLED;
  pTimerCfg.UpdateGating = HRTIM_UPDATEGATING_INDEPENDENT;
  pTimerCfg.BurstMode = HRTIM_TIMERBURSTMODE_MAINTAINCLOCK;
  pTimerCfg.RepetitionUpdate = HRTIM_UPDATEONREPETITION_DISABLED;
  pTimerCfg.PushPull = HRTIM_TIMPUSHPULLMODE_DISABLED;
  pTimerCfg.FaultEnable = HRTIM_TIMFAULTENABLE_NONE;
  pTimerCfg.FaultLock = HRTIM_TIMFAULTLOCK_READWRITE;
  pTimerCfg.DeadTimeInsertion = HRTIM_TIMDEADTIMEINSERTION_DISABLED;
  pTimerCfg.DelayedProtectionMode = HRTIM_TIMER_D_E_DELAYEDPROTECTION_DISABLED;
  pTimerCfg.UpdateTrigger = HRTIM_TIMUPDATETRIGGER_NONE;
  pTimerCfg.ResetTrigger = HRTIM_TIMRESETTRIGGER_NONE;
  pTimerCfg.ResetUpdate = HRTIM_TIMUPDATEONRESET_DISABLED;
  pTimerCfg.ReSyncUpdate = HRTIM_TIMERESYNC_UPDATE_UNCONDITIONAL;
  if (HAL_HRTIM_WaveformTimerConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_D, &pTimerCfg) != HAL_OK)
  {
    Error_Handler();
  }
  pCompareCfg.CompareValue = TIMD_PERIOD * TIMD_DUTY_CYCLE;
  if (HAL_HRTIM_WaveformCompareConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_D, HRTIM_COMPAREUNIT_1, &pCompareCfg) != HAL_OK)
  {
    Error_Handler();
  }
  pOutputCfg.Polarity = HRTIM_OUTPUTPOLARITY_HIGH;
  pOutputCfg.SetSource = HRTIM_OUTPUTSET_TIMPER;
  pOutputCfg.ResetSource = HRTIM_OUTPUTRESET_TIMCMP1;
  pOutputCfg.IdleMode = HRTIM_OUTPUTIDLEMODE_NONE;
  pOutputCfg.IdleLevel = HRTIM_OUTPUTIDLELEVEL_INACTIVE;
  pOutputCfg.FaultLevel = HRTIM_OUTPUTFAULTLEVEL_NONE;
  pOutputCfg.ChopperModeEnable = HRTIM_OUTPUTCHOPPERMODE_DISABLED;
  pOutputCfg.BurstModeEntryDelayed = HRTIM_OUTPUTBURSTMODEENTRY_REGULAR;
  if (HAL_HRTIM_WaveformOutputConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_D, HRTIM_OUTPUT_TD1, &pOutputCfg) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_HRTIM_MspPostInit(&hhrtim1);

}
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();//8M外部晶振,170M系统主频

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_HRTIM1_Init();//HRTIME初始化,PWM频率为50K,占空比50%,PB14:HRTIM1_CHD1
  /* USER CODE BEGIN 2 */
  HAL_HRTIM_WaveformOutputStart(&hhrtim1, HRTIM_OUTPUT_TD1);//启动波形输出的函数调用,TD1输出波形
  HAL_HRTIM_WaveformCounterStart(&hhrtim1, HRTIM_TIMERID_TIMER_D);//启动定时器D的波形计数功能
  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

3.测量波形结果

通过示波器测量PB14引脚,可以看到PWM输出是50Khz,占空比50%。
在这里插入图片描述

五.小结

STM32G474RET6通过HRTIM实现1/256微步控制,适用于CNC机床和3D打印机‌,支持PMSM电机磁场定向控制,用于无人机和电动工具驱动,通过多个定时器同步控制机械臂协同运动,在数字电源开发中表现突出,其HRTIM模块的184ps分辨率可实现纳秒级时序控制‌。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐