on 2025-02-11 6:53 AM
This article is a step-by-step guide on how to use the half and interleaved modes of the STM32G4 HRTIMER (high-resolution timer). The examples in this article are demonstrated using the B-G474E-DPOW1 board but can be tailored to any other STM32G4 board of your choice.
The HRTIMER (high-resolution timer) on the STM32 microcontrollers is a sophisticated timer peripheral designed to provide precise high-resolution timing and advanced control capabilities. Each HRTIMER is equipped with a master timer and six independent timers (A-F), each with 16-bit counters and two outputs. This results in a total of 12 outputs from this IP.
The purpose of the master timer is to synchronize the other timer units and control the set or reset event states of the 12 output channels. The 6 independent counters can operate independently or with other timers, including the master timer. Each unit controls two outputs, with set/reset events triggered by its compare registers, the master timer, other timers, or external events.
Common use cases include:
B-G474E-DPOW1 discovery board.
STM32CubeIDE v1.17.0 or later.
STM32Cube MCU Package for STM32G4 series v1.6.0 or later for generating the HAL/LL code using STM32CubeIDE.
USB A to USB Micro B cable.
Logic analyzer or oscilloscope.
Half mode is a feature that allows the reduction of computational burden when a precise 50% duty cycle PWM waveform must be generated. This mode is very useful in applications where a 50% duty cycle must be maintained while the operating frequency is continuously adjusted in real time.
When the HALF bit in the HRTIM_TIMxCR register is set to 1, any write access to the HRTIM_PERxR (period register) automatically computes the Compare 1 register with the value of HRTIM_PERxR/2. This feature is especially beneficial when the timer operates in continuous mode. It allows the period register to be updated while maintaining a 50% duty cycle instantaneously.
This article illustrates how to use half mode, change the period value, and how Compare Unit 1 automatically computes the value of HRTIM_PERxR / 2, updating the waveform in real time.
We start this demonstration by creating a new project for the B-G474E-DPOW1 discovery board using STM32CubeIDE, configuring the clocks and the HRTIM peripheral. Here are the steps to perform the initial configurations.
Open the STM32CubeIDE application.
Choose [File] -> [New] -> [STM32 Project].
Search for B-G474E-DPOW1 under board selector tab and click on the shown board selection and then click [Next].
Choose a name for the project and click on [Finish].
A popup appears, click on [No] to deny keeping all the peripherals present on the board in their default mode
Once the .ioc file is open, click on [Clear Pinouts] under the [Pinout & Configuration] drop-down menu to start the peripheral initialization from scratch.
Navigate to the clock configuration settings and ensure that the APB2 peripheral clocks, which the HRTIMER is connected to, is set to run at 170 MHz.
In the [Pinout & Configuration] tab, navigate to the timers drop-down menu, click on HRTIM1, and activate the timer D outputs.
The HRTIMER can be clocked at a maximum clock of 170MHz using the APB2 bus. It supports a clock prescaler that can multiply the APB clock value by 1, 2, 4, 8, 16, or 32, or divide the APB clock value by 2 or 4. Therefore, the maximum fHRTIM clock achievable is 5.44 GHz when using a multiplication prescaler of 32 with an APB2 base clock of 170 MHz. Conversely, the lowest frequency attainable, given an APB2 clock of 170 MHz, is 42.5 MHz when using a prescaler divider of 4.
In this example, we run the HRTIMER at the maximum frequency by using a multiplier prescaler of 32.
The maximum value that the period register can support varies when using multiplication prescaler values, as the least significant bits become insignificant.
The maximum programmable period values for each multiplication factor are shown in the table below
CKPSC[2:0] |
Multiplier value |
Maximum period value |
000 |
x32 |
0xFFDF |
001 |
x16 |
0xFFEF |
010 |
x8 |
0xFFF7 |
011 |
x4 |
0xFFFB |
100 |
x2 |
0xFFFD |
101 |
x1 |
0xFFFD |
In this example, since we are using a multiplier prescaler value of 32, the maximum period value is 0xFFDF. We use the period value as 0xFFDF which results in the following PWM frequency:
Continue configuring the HRTIMER by selecting [Enable] in Compare Unit 1 under the [Timer D] tab.
Next, we configure timer D to operate in half mode. This setting can be enabled under the Interleaved Mode option in the Timing Unit section. Note that half mode can only be activated if Compare Unit 1 is enabled. Otherwise, the option is grayed out and unavailable. Additionally, it is normal for the compare value to disappear from the Compare Unit 1 section, as the value is automatically computed internally.
Since we are updating the period value in real time, we enable the preload feature. Keep in mind that when preload is enabled, all writes to the HRTIM_PERxR register are made to the preload register, not the active register. Therefore, an update event must be enabled to transfer the content from the preload register to the active register.
Although HRTIM supports various update events, for simplicity, we use the [Update by Timer reset/roll-over enabled] option.
Next, we configure the set and reset events for the outputs TD1 and TD2. Consider TD1 and TD2 to be complementary outputs.
OUTPUT | Set event | Reset event |
TD1 | Timer D period | Timer D compare unit 1 event |
TD2 | Timer D compare unit 1 event | Timer D period |
Change the number of active set and reset sources to 1, and assign the set/reset events accordingly, as demonstrated in the table above.
With all configurations complete, we can now generate the code by clicking on the [Device Configuration Tool Code Generation] icon.
The code to add in-between the respective user code comments for the main.c file is mentioned below:
/* USER CODE BEGIN 2 */
HAL_HRTIM_WaveformOutputStart(&hhrtim1, HRTIM_OUTPUT_TD1 + HRTIM_OUTPUT_TD2);
HAL_HRTIM_WaveformCountStart(&hhrtim1, HRTIM_TIMERID_TIMER_D);
HAL_Delay(5000); //5 second delay
__HAL_HRTIM_SETPERIOD(&hhrtim1,0x3,0x2710);
/* USER CODE END 2 */
This code runs timer D with a period of `0xFFDF` for the first 5 seconds and then changes the period to `0x2710` (10000 in decimal).
The second argument, `0x03`, of the macro `__HAL_HRTIM_SETPERIOD` represents the selection of timer D. The values range from `0x0` to `0x5` for timers A-F, and `0x6` for the master timer.
Connect your board to the PC using a USB cable. Compile, load and debug the binary file by clicking on the button shown below. The programming process should complete without any errors.
Connect the logic analyzer or oscilloscope probes to pins PB14 and PB15. Then, click on the [Run] icon to start the process.
Now, when you analyze the scope captures, you observe that the PWM signal has approximately 50% duty cycle.
Period value | Resulting PWM frequency in Hz (170Mz / period value) | Resulting PWM time period in μs (1 / PWM frequency) | 50% duty cycle time period in μs |
0xFFDF / 65503 | 83050 | 12.04 | 6.02 |
0x2710 / 10000 | 544000 | 1.8 | 0.9 |
Scope capture at the start:
Scope capture after 5 seconds:
This mode is used to implement interleaved topologies, which are commonly used in power electronics to improve the performance of power converters. The available modes are:
Triple interleaved (120°): Three phases with 120-degree phase shift.
Quad interleaved (90°): Four phases with 90-degree phase shift.
The specific compare registers and their corresponding values are automatically calculated based on the chosen interleaved mode.
Compare register values |
Triple interleaved 120° |
Quad interleaved 90° |
CMP1 value |
Period / 3 |
Period /4 |
CMP2 value |
2x (period /3) |
Period /2 |
CMP3 value |
Not affected |
3 x (period /4) |
We utilize the previously demonstrated half-mode project in this article to showcase the dynamic behavior of quad interleaved mode. This involves observing how the HRTIM automatically recalculates different compare register values in response to changes in the value of `HRTIM_PERxR`.
Open the .ioc file while keeping the clock configurations the same, and make the following changes to the .ioc configuration file.
In the HRTIM1 section, enable Compare unit 2 and 3 of timer.
Change the interleaved mode to [Quad]. Similar to the configuration of half mode, the compare value portion of the compare units now disappears. These values are computed internally and not required to be manually updated on our end.
TD1 and TD2 are complementary outputs and change the active Set/Reset sources as shown below.
With all configurations complete, we can now generate the code by clicking on the [Device Configuration Tool Code Generation] icon.
Given the absence of code changes from the Half_mode project, establish a USB connection between your board and PC. Subsequently, initiate the compilation, loading, and debugging of the binary file by clicking the provided button. The programming operation should conclude without any errors or exceptions.
Connect the logic analyzer or oscilloscope probes to pins PB14 and PB15. Then, click on the [Run] icon to start the process.
The scope captures give us the results as expected.
When preload is enabled, writes to the period register are first stored in the preload registers. The contents of the preload registers are then transferred to the active registers upon the occurrence of an update event. Conversely, when preload is disabled, all writes to the period registers are immediately reflected in the active registers and sometimes this might lead to indeterministic results.
Make sure that there is an update event that is configured when the preload is enabled. For the half and interleaved modes to work the period must be greater than or equal to 6 periods of the fHRTIM clock.
Due to hardware-driven updates of compare registers, half and interleaved modes are incompatible with other modes that depend on those same registers.
Depending on the mode being used to the respective compare registers are not manually controllable, and any attempts to write to those registers are overwritten by the internally computed value. Additionally, the user-accessible compare registers are not updated with the internally computed values.
You now have the knowledge to utilize the STM32G4's HRTIMER in both half and interleaved modes effectively. Best of luck with your development!
Here are some useful links that can help with your development: