|
Hierodule 1.6.2
Utility module set for STM32 MCUs
|
This module can be roughly divided into two parts:
You can use the provided PWM routines to
The module does not address peripheral configuration and initialization, it is assumed those are performed beforehand. Also, it's best to set a proper prescaler value for the timer you're going to work with, since frequency and period changes are performed by updating the ARR value in relation to the peripheral bus clock and PSC.
Here's the basic use of PWM related routines:
You can really call the routines in any order you want and get results accordingly.
While using an advanced timer, you might need to enable main output to get the output channels to function properly. You can simply enable the MOE bit of a timer via:
If you'd like to reset the counter of the timer after a frequency or period update, do so via:
Finally, if you'd like to have the channel outputs automatically re-enabled after a break interrupt once the break flag is cleared, set the AOE bit via:
All enabler routines cited above are paired with their disabler counterparts. Likewise, "set" functions come with their "get" counterparts.
You can define macro constants instead of using mere integers to select output channels if you prefer those to really stand out in the code.
Keep in mind that not all timers have same the set of status flags, identical control registers or the same number of output channels. Consult the device manual to verify the peripheral's features.
The main goal of this section is to facilitate the assignment of an ISR to an IRQ through a single, straightforward call.
Also notice that the Timer IRQs are defined in the module's source file. The compiler will throw a multiple definition error if an IRQ is defined somewhere else.
Here's the code to basically bind "Some_ISR_Function" to the counter update interrupt request of TIM1 and enable the interrupt:
The same routine can be called anywhere during runtime and different interrupt service routines may be assigned.
To clear the ISR pointer, simply invoke the routine with a null pointer instead of a function pointer:
You might consider clearing the interrupt flag before enabling an interrupt, since an interrupt flag may be set even though the interrupt is disabled and the program won't branch to the IRQ routine. For example, the update and capture compare flags will still get set if the timer counter is enabled, even in case of a break-input where the PWM outputs are disabled. Configure the peripherals and implement your ISR taking flag states into account.
Keep in mind that the interrupt flag is automatically cleared before the program leaves the IRQ body, regardless of whether an ISR has been assigned or not. Likewise, if the IRQ is defined for multiple flags, the flag checks are performed automatically.
If you prefer to manually manage the flag handling, simply comment out the macro constant definition HIERODULE_TIM_CONVENIENT_IRQ in the header file, like so:
HIERODULE_TIM_HANDLE_IRQ is still required to be defined for this approach.
You need to use a different sort of assignment routine if you take this route:
No timer parameter is needed in this case, since the assignment is performed per IRQ, explicitly.
Also provided are routines that let you toggle the timer interrupts and check or clear the interrupt flags, as you would make use of while implementing the ISR.
Notice that you'll need to check and clear multiple flags if the IRQ function is wired to be branched to on multiple interrupts. Advanced timers usually have different IRQs for break, update and capture compare interrupts but basic timers tend to have all of them lumped together within a single IRQ. Furthermore, some devices use the same IRQ for a combination of flags from different timers, such as TIM1_TRG_COM_TIM11_IRQHandler for STM32F401xC.
If you do not want the IRQs defined within the timer module source file, simply comment out the macro constant definition HIERODULE_TIM_HANDLE_IRQ in the header file, like so:
It is irrelevant whether HIERODULE_TIM_CONVENIENT_IRQ is defined or not at this point.
In this case, you need to define your IRQs somewhere else. You can still use the interrupt related routines except the assignment ones.
Finally, you can use HIERODULE_TIM_SetRepetition to extend the effective period of your timer.
As for the given example, your capture compare interrupts will still be triggered only once every period, but your update interrupt will be triggered after 9 additional periods, which is in effect multiplying the UPD interrupt period by ten.
This feature is usually limited to advanced timers.
If your system works on FreeRTOS, you'll probably use a timer as the timebase for HAL, since FreeRTOS uses SysTick, which is the usual timebase for HAL.
Which means, the IRQ of the timer HAL uses will be defined somewhere else, ergo, the compiler will throw a multiple definition error. You can use HIERODULE_TIM_RESERVED for such cases.
The constant's defined as 0 by default, which doesn't do anything. Simply, define the constant with its value as the problematic timer's number, and its IRQ won't be compiled within the module. Define it as 1, for Timer 1, for example.
Again, remember that IRQs of some timers are joined into a single routine.