2021-01-08 05:41 PM
I am using a STM32H7 micro in an application where I need to assert a signal at a time that I determine in software. I am using the output compare from a timer for this signal and setting the CCR register to the time I want the output to be asserted. In this case, the timer always counts up and does not roll over. This seems to work fine when the CCR is set to a time > CNT, however, it is possible that the software determines the time for assertion has already elapsed. It appears that if I set CCR < CNT, then the output compare is not asserted. Is there a good description of exactly how the timer outputs work in the various modes? Is this behavior expected and is there a way to get it to behave such that if I set CCR to a value < CNT, it still asserts the output? If not, is there a way to detect this situation and set CCR to a value that will cause the output to be asserted as soon as possible? Preferably without introducing a race condition.
2021-01-08 05:56 PM
Which compare mode?
Sounds like set/clear on match. PWM would behave differently.
JW
2021-01-08 06:25 PM
> Is there a good description of exactly how the timer outputs work in the various modes?
The reference manual goes into detail on how the various modes operate.
> Is this behavior expected and is there a way to get it to behave such that if I set CCR to a value < CNT, it still asserts the output?
Seems like PWM mode would do exactly what you want. From the RM:
In PWM mode (1 or 2), TIMx_CNT and TIMx_CCRx are always compared to determine
whether TIMx_CCRx ≤ TIMx_CNT or TIMx_CNT ≤ TIMx_CCRx (depending on the direction
of the counter).
2021-01-09 05:25 PM
Originally Output Compare. I tried PWM and did not think it worked properly, but I was testing quickly, so maybe I missed something. It does seem like PWM mode 2 should do what I want.
2021-01-09 05:45 PM
Thanks. Yes, I have been looking at the Reference Manual (this is a 745, which is different from what you linked). Maybe it's just me, but the info I need often seems quite buried and hard to locate.
Do you know if this will also trigger the CC1 interrupt in the case where CCR is set to a value < CNT? I forgot to mention it, but I was also wanting an interrupt to fire when the output becomes asserted. The description of the CC1IF but sounds like maybe it would not generate an interrupt in this case:
If channel CC1 is configured as output: this flag is set when the content of the counter
TIMx_CNT matches the content of the TIMx_CCR1 register.
2021-01-10 02:33 AM
> will also trigger the CC1 interrupt in the case where CCR is set to a value < CNT?
No (until it reaches CC1 again after wraparound, of course).
> Originally Output Compare.
All output compare modes are output compare... Please use terminology given by RM, here given by description of TIM_CCMRx.CCxM bits. I admit it's not perfect either, but at least providing a common point, as not everybody uses Cube/CubeMX.
You've probably used some of the Active/Inactive On Match modes. That's what I've used, too. However, I would also check for the corner case, ie. for CCR<CNT, "manually", in the code, after setting the new value for CCR (also taking into account the corner-corner case, i.e. that the CCx flag in SR is already set due to CCR being > CNT at the moment of setting it), and if so, I would set CCMR.CCxM to Force Active/Inactive as appropriate (that of course requires to set it back to Active/Inactive On Match before the next required transition). That ensures the proper output level unfortunately not the interrupt, so you'd need to handle that "manually" too.
Yes it's tedious and complicated and all possible cases have to be taken into account. Alternatively, you can stop the timer, set CCR appropriately and reenable it, if the application allows for the timer to be stopped/restarted. Or, if the new CCR values are known up front (i.e. they are not calculated from external signals' occurence), they can be put into a table and fed to timer by DMA; this also has the risk of missing a transition but the "risk time window" is one order of magnitude (or if you use Cube and low compiler optimization, maybe even two) shorter. Another option is to set CCR to be preloaded, set it not relative to current CNT but to 0, and then force Update event which clears CNT and loads the preloaded CCR; again this disrupts continuous timer so if this is viable depends on the particular application.
JW