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