Hello,
Whenever you update the TPMxMOD or TPMxCnV registers, there is a coherency mechanism involved, before the value can change. This mechanism differs slightly for different versions of the TPM module. The update of these registers will occur more quickly if the TPM module is disabled when the values are altered, i.e TPMxSC is zero. During initialisation, TPMxSC should then be the last register to be set.
I note that you have a large prescale setting of 128, and a relatively small TPM1MOD setting. I would suggest to greatly reduce the prescale value to, say 2, and increase the TPM1MOD value by a factor of 64. This will increase the resolution of the input capture process, but retain the same overflow period. I note that you are writing individual byte values to the 16 bit registers. This is unnecessary - it is simpler to write the full 16-bit value to these registers, It is also possible that you may not have taken into account that the PWM period is actually equal to (TPM1MOD+1)
The input capture range will be zero to TPM1MOD value. The calculation of the period between input capture events must therefore compensate for the truncated range.
I note that, with TPM1C1V equal to TPM1MOD, your PWM duty setting will be very close to 100 percent, which may cause the buzzer to be inaudible. For 50 percent duty, you would require TPM1C1V = (TPM1MOD+1)/2;
Your initialisation code might then become -
TPM1MOD = 0xD4FF;
TPM1C0SC = 0x44; // Input capture on +ve edge
TPM1C1SC = 0x38; // Edge aligned PWM mode
TPM1C1V = (TPM1MOD+1)/2; // 50% duty
TPM1SC = 0x11; // Fixed system clock, prescale 2
Within your input capture ISR, you might incorporate the following code to determine the period between events -
static word oldval;
period = TPM1C0V - oldval;
oldval = TPM1C0V;
if (period >= (TPM1MOD+1))
period -= (TPM1MOD+1); // Corrected period value
...
The global (or static) word variable period would need to be defined as volatile.
Regards,
Mac