Hello
I am using QD4 for a Universal IR capture algorithm.
I am using TPM1CH1 (Pin 7,alternate function is PTAD1 as GPIO).This pin is used as an Interrupt driven
counter which will measure duration of incoming pulses between rising and falling edges (interrupts).
I am using a Timeout of 90msec after the first edge intr occurs.I also use some 70 bytes for this train
of pulses.So that after acquiring 70 bytes of info I fall out of that routine.
This works fine for a RC5/6 type of protocol which has a repeatabilty of ~100msec,but with some
others like SIRC,which has repeatable w/f in ~15msec,multiple packets of data are captured.
Here as an error correction mechanism,I will lookout for a TPMCNT>my threshold,after which I skip all
the data ,so effectively only a single frame is put up for conditioning.
This is used in some Compare and Actions based on those Compares.
My Channel ISR is attached here
//TPM1 channel INTR Service Routine //-------------------------------------------------------------------------------------// //---------------------------------------------------------------------// TPM1channel 1 edge Interrupt//----------------------------------------------------------------------interrupt 6 void TPM1C1_ISR (void){ TPMC1SC; TPMC1SC_CH1F=RESET; if(i==70) { TPMC1SC_CH1IE=RESET; TPMCNT=0; TPMSC=0x00; } if(i>1) { TPM2SC=0x00; //Stop Timer2 or Stop timeout timer store[i].period[0]=TPMC1VH; store[i].period[1]=TPMC1VL; TPM2MOD=0x7000; //Timeout of 86msec. TPM2SC=0x4D; //Restart Timer } TPMCNT=0; i++; }
interrupt 10 void Timer2_Overflow_INTR(void){ TPMC1SC_CH1IE=RESET; TPMCNT=0; if(common.LEARN==SET) common.LEARN_DONE=SET; else common.ACTION_READY=SET; common.TIME_OUT=SET; TPM2SC; TPM2SC_TOIE=RESET; }
My problem is that often it will recv the waveform correctly but some of times I cannot get the
correct waveform..I am not sure if the algorithm I am using is correct.
Can someone help?..I can tell more..
Expecting help as usual..
Thanks and regards
已解决! 转到解答。
Hello,
My previous response was badly worded. The unorthodoxy that I was referring to was not the modification of the registers from within the ISR, but the stopping, starting and clearing of the TPM counter, and the changing of the TPMMOD value - it is usually possible to avoid these. The reason they should generally be avoided is they affect all channels of the TPM module, and may prevent the use of spare channels for other purposes.
For the case of TPM2, with only a single channel, this issue is probably not of importance, but I was alluding to the fact that there is an alternative way of handling the timing that avoids the issue. I did not mean to imply that your method could not be made to work, and had any bearing on your current problem.
The alternative method in more detail -
Within the TPM1 channel (input capture) ISR:
TPM2C0SC = 0x50; // Software output compare interrupt
TPM2C0V = TPM2CNT + 0x7000; // Setup timeout period
TPM2C0SC_CH0F = 0; // Clear flag (if set)
When timeout occurs, a TPM2 channel 0 interrupt would take place. Within this ISR:
TPM2C0SC = 0x00; // Disable output compare mode
TPM2C0SC_CH0F = 0; // Clear flag
Your input capture ISR code might then become something like the following -
#define RESET 0
byte i;
word store[70];
interrupt 6 void TPM1C1_ISR (void)
{
//TPM1C1SC; Unnecessary for flag clearing
TPM1C1SC_CH1F = RESET; Clear flag
if (i == 70) {
//TPMC1SC_CH1IE = RESET;
//TPMCNT=0;
//TPMSC=0x00;
TPM1C1SC = 0x00; // Disable input capture operation
TPM2C0SC = 0x00; // ?? Disable output compare operation
}
else if (i > 1) { // I presume this is what is really intended
//if (i > 1 ) {
//TPM2SC=0x00; //Stop Timer2 or Stop timeout timer
store[i] = TPM1C1V; // Simpler to handle a word value
//store[i].period[0]=TPMC1VH;
//store[i].period[1]=TPMC1VL;
TPM2C0SC = 0x50; // Software output compare interrupt
TPM2C0V = TPM2CNT + 0x7000; // Setup timeout period 86ms
TPM2C0SC_CH0F = 0; // Clear flag (if set)
//TPM2MOD = 0x7000; //Timeout of 86msec.
//TPM2SC = 0x4D; //Restart Timer
i++; // May be better placed here
}
//TPMCNT = 0;
//i++;
}
One other point about input capture operation - it may be more reliable to capture on a single edge at a time, rather than both edges. This may prevent phasing errors occurring in the event of spurious interrupts - you will always be assured of the edge polarity that each capture event represents. During the input capture ISR simply toggle to the opposite edge for the next event.
Regards,
Mac
Hello,
I wonder if it is possible that the period you are attempting to measure may exceed the overflow period for TPM1? If so the capture results will be meaningless (without also tracking overflows). Try increasing the prescale value for TPM1, and see if the problem persists. I presume that TPM1 does not have a reduced modulo setting.
I notice that you are altering TPM2 settings within the TPM1 ISR, including stopping the timer and changing the modulo value. This is rather unorthodox. The more traditional aproach would be to utilize output compare interrupt, and leave the TPM running continuously with full modulo count. From within the TPM1 ISR, simply read the current 16-bit counter value for TPM2, add the required timeout delay (0x7000), and update the TPM2 channel register. A channel interrupt will occur upon expiry of the timeout period.
Regards,
Mac
Hello Mac and thank you so much for the reply..
The TPM1 Channel interrupt is invoked on every edge (rising and falling) and in the ISR i reset the TPM2CNT,so that largely,the overall code is trying to look for a Timeout.
This is to insure that multiple packets are not processed.
Why is TPM2 altering not suitable within another ISR?
I did not understand the part where you said to add the req. timeout delay after reading the current 16-bit cnt value.
Did you mean that I subtract current cnt from the req. cnt and then add this cnt to the existing cnt?
Why is this beneficial?
Please reply
Thanks and regards
Hello,
My previous response was badly worded. The unorthodoxy that I was referring to was not the modification of the registers from within the ISR, but the stopping, starting and clearing of the TPM counter, and the changing of the TPMMOD value - it is usually possible to avoid these. The reason they should generally be avoided is they affect all channels of the TPM module, and may prevent the use of spare channels for other purposes.
For the case of TPM2, with only a single channel, this issue is probably not of importance, but I was alluding to the fact that there is an alternative way of handling the timing that avoids the issue. I did not mean to imply that your method could not be made to work, and had any bearing on your current problem.
The alternative method in more detail -
Within the TPM1 channel (input capture) ISR:
TPM2C0SC = 0x50; // Software output compare interrupt
TPM2C0V = TPM2CNT + 0x7000; // Setup timeout period
TPM2C0SC_CH0F = 0; // Clear flag (if set)
When timeout occurs, a TPM2 channel 0 interrupt would take place. Within this ISR:
TPM2C0SC = 0x00; // Disable output compare mode
TPM2C0SC_CH0F = 0; // Clear flag
Your input capture ISR code might then become something like the following -
#define RESET 0
byte i;
word store[70];
interrupt 6 void TPM1C1_ISR (void)
{
//TPM1C1SC; Unnecessary for flag clearing
TPM1C1SC_CH1F = RESET; Clear flag
if (i == 70) {
//TPMC1SC_CH1IE = RESET;
//TPMCNT=0;
//TPMSC=0x00;
TPM1C1SC = 0x00; // Disable input capture operation
TPM2C0SC = 0x00; // ?? Disable output compare operation
}
else if (i > 1) { // I presume this is what is really intended
//if (i > 1 ) {
//TPM2SC=0x00; //Stop Timer2 or Stop timeout timer
store[i] = TPM1C1V; // Simpler to handle a word value
//store[i].period[0]=TPMC1VH;
//store[i].period[1]=TPMC1VL;
TPM2C0SC = 0x50; // Software output compare interrupt
TPM2C0V = TPM2CNT + 0x7000; // Setup timeout period 86ms
TPM2C0SC_CH0F = 0; // Clear flag (if set)
//TPM2MOD = 0x7000; //Timeout of 86msec.
//TPM2SC = 0x4D; //Restart Timer
i++; // May be better placed here
}
//TPMCNT = 0;
//i++;
}
One other point about input capture operation - it may be more reliable to capture on a single edge at a time, rather than both edges. This may prevent phasing errors occurring in the event of spurious interrupts - you will always be assured of the edge polarity that each capture event represents. During the input capture ISR simply toggle to the opposite edge for the next event.
Regards,
Mac