I am attempting to create a pulse using the output compare function on the MC9S08AC16.
I measure an incoming pulse for example - 3 msec and I would like to set the out going pulse to be longer - say 5 msec. The outgoing pulse has to begin on the rising edge of the incoming pulse.
I am using TPM3CH0 to measure the incoming pulse - this appears to work correctly.
I am using TPM1CH0 to create the outgoing pulse - does not work
On the rising edge of the incoming pulse I set PTE2 (TPM1CH0).
On the falling edge of the incoming pulse, I set the compare value and enable clear on compare function and enable the compare interrupt.
TPM1C0V = TPM1CNT + delta
delta is the 2 msec that would be added to the 3 to give 5msec
The output compare does not happen at any predictable time
Any suggestions?
Thank You
Hello,
It is always more helpful if you include a code snippet to show the problem area. It is unclear whether you require an output pulse width 2ms greater than the input pulse width, or a fixed output pulse width of 5ms, independent of the input pulse width.
I will assume that you might be using TPM channel interrupts, rather than polling, to control the pulse generation. Note that, unless you gate the input pulse externally to the MCU, the start of the output pulse will be delayed by a number of bus cycles from the transition edge of the input pulse. This is the time required to allow for the latency of the input capture ISR and to update the output compare register of the second channel. I would recommend that you use two channels from the same TPM module, say TPM1Ch0 and TPM1Ch1, rather than from different TPM modules.
A possible procedure, within the input capture channel ISR, might be to -
Read TPM1CNT value, and set TPM1C1V (the output compare channel) to this value, plus a few TPM clock cycles. This is to make sure that, by the time that the register is updated, the TPM1CNT value is not already greater than the required time. The output compare transition should generate the positive edge of the output pulse.
For a fixed output pulse period, you would wait until the ouput compare event occurs (the channel flag becomes set), and then set the TPM1C!V value for the required pulse width beyond the previous channel register setting, with with a low output state for the next output compare event. Then exit the ISR.
For extending the input pulse width by a fixed amount, you would set the next input capture event for a negative transition, and exit the ISR. When the next interrupt occurs, set the TPM1C1V value to the required delay beyond the current TPM1C0V capture value, with the next output compare event to a low state. Revert to a positive edge for the next input capture event, and exit the ISR. You will need to keep track whether the current execution of the ISR is for a positive or negative input capture edge.
Interrupts on TPM1Ch1 are not required for the pulse generation. Note that the TPM overflow period must be greater than the delay you are attempting to create, to avoid additional complication to the code.
Regards,
Mac
I have attached 3 files.
I used PE to setup the micro clock and the input capture
I manually setup the output compare
There are 2 paths for pulse generation. The first path generates a duplicate of the incoming pulse and this works. It does not use output compare.
I hope my comments in the code are clear.
Thank You for responding,
Forest
Hi Forest,
I think your problem is you are writing theTPM1C0SC register immediately after setting the compare value. Believe it or not, this should NOT be done. This is an undesireable aspect of all the TPM modules in the processors.
// read the count in TPM1 and add the delta to it TPM1C0V = TPM1CNT + uiOC0delta; // clear any pending interrupt A = TPM1C0SC; // and turn on OC TPM1C0SC = 0x58; // terminate pulse on compare
Do whatever you need to do to TPM1C0SC first, then set the compare value. Another way around it is to set the compare value first, then wait until you see the timer value (TPM1CNT) change, then you can change the control register. The latter way is not always desireable in an interrupt service routine however.
Here is what I think happens, but also see their explanation below from the manual. When you load the compare value, it has to get synchronized with the clock to the timer and writing both bytes of the 16-bit compare value coherently. That is done with a "coherency mechanism" that employs a "latching mechanism" in the TPM. Any write to a TPMxCxSC register will reset the latching mechanism, and possibly leave an incorrect value in the compare register. I said above, "what I think happens" but I should have said, "what I KNOW happens" since I have verified this situation. Read the two paragraphs below from their manual. These are easy to miss, but are absolutely critical to getting a correct compare value. The second paragraph is the most important one, especially the bolded text.
In output compare or PWM modes, writing to either byte (TPMxCnVH or TPMxCnVL) latches the value into a buffer. After both bytes are written, they are transferred as a coherent 16-bit value into the timer-channel registers according to the value of CLKSB:CLKSA bits and the selected mode...
The latching mechanism may be manually reset by writing to the TPMxCnSC register (whether BDM mode is active or not). This latching mechanism allows coherent 16-bit writes in either big-endian or little-endian order which is friendly to various compiler implementations.
What results if you do NOT do things correctly is the coherency mechanism gets messed up and the compare register gets what looks like a random value. In my code, I opted to make sure my compare value would be at least a few timer counts greater than the current timer value (TPM1CNT), then I set the control register, and lastly set the compare register value. My control register enabled interrupts, but I could guarantee I would not get one immediately since the compare value was at least a few timer counts later. The way I had to do it seems totally backwards to my normal way of thinking about things, but it worked.
Sorry I did not see your post earlier, and I hope you see this reply. It cost me a lot of time figuring this one out, and I really want to help others avoid this same problem. It is a strange problem that I think is the result of a poor design. If any of the hardware designers read this post (unlikely) I would recommend they figure out a way to not reset the coherency/latching mechanism on writes to the control register. There's gotta be a way to do that. And if they are not going to change the hardware, at least they could highlight or emphasize that area in the manual to show how critical it is, and not leave it as a two sentence paragraph in a discussion on the channel value registers.
Hope this takes care of your problem.
Lou