STM32G474单片机开发入门(二十七)HRTIME高精度定时器的PWM(50KHZ)输出实战
本文对高精度定时器HRTIME做了个简单介绍,通过STM32G474RET6单片机进行PWM波形输出,输出50KHZ,50%占空比的PWM。
文章目录
一.概要
我们在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分辨率可实现纳秒级时序控制。
更多推荐



所有评论(0)