Input Capture of the PWM problems

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Input Capture of the PWM problems

806 Views
22992113
Contributor I

I have some question about PWM Input Capture from 9S12XDT256.

I want to measure the duty of the IC7 PWM. but the duty is wrong when the PWM input frequence is 1000Hz. but when the PWM input frequence is lower then 500Hz . the duty is right.    

This is my code. I need a help.

 

interrupt 15 void TC7_FUN(void)
{


 if(PTIT_PTIT7 == 1)
//rising edge came
{
if(measuring_in_progress == 1)
//we have all values and we can calculate duty_cycle now
{
rising_edge_temp = TC7;
rising_edge = TC7 + (overflow << 16);

length_zero = rising_edge - falling_edge_temp;

duty_cycle = (unsigned char)((100 * length_one) / (length_one + length_zero));

//PORTB = ~duty_cycle; //show duty_cycle on LED

rising_edge = rising_edge_temp;
}

else
//we start with measuring now
{
rising_edge = TC7; //save value of input edge
measuring_in_progress = 1;
}
}

else
//faling edge came
{
if(measuring_in_progress == 0)
{
//do nothing
//we are waiting for rising edge in condition that there was DC signal
//logic one now. We start measuring after rising edge
}
else
//now we can calculate length of signal in logic one
{
falling_edge_temp = TC7;
falling_edge = TC7 + (overflow << 16); //save value

length_one = falling_edge - rising_edge; //calculate length of signal in logic one
}
}

overflow = 0;

//TFLG1 = 0x80; //clear interrupt flag

TFLG1_C7F = 1; 

}

//==============================================================================
// Timer Overflow Interrupt
//==============================================================================
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt 16 void TOI_ISR(void)
{
overflow++;

if(overflow > MAX_OVERFLOW) //there is not periodic signal on thi pin
{
if(PTIT_PTIT7 == 1)
{
duty_cycle = 100; //pin is still in logic one
//PORTB = ~duty_cycle; //show on LED duty_cycle 100%
}
else
{
duty_cycle = 0; //pin is still in logic zero
//PORTB = ~duty_cycle; //show on LED duty_cycle 0%
}
overflow = 0; //restart measuring
measuring_in_progress = 0; //restart measuring
}

TFLG2 = 0x80; //clear interrupt flag
}


//==============================================================================
// InitInputCapture
//==============================================================================
void InitInputCapture(void)
{
PPST_PPST7 = 0; //set pull-up
PERT_PERT7 = 0; //enable pull-up
DDRT_DDRT7 = 0; //PT0 as input


TSCR1 = 0xE0; //enable timer, stop timer during wait and freeze, disable fast flag clear
TIOS = 0x0F; //channel 0 as an input capture
TCTL3 = 0xD0; //capture on any edge (rising or falling) 
TIE_C7I = 1; //enable interrupt on channel 1 
TSCR2 = 0x87; //timer overflow interrupt enable, timer prescaler is 0

DLYCT=0x01; //Delay Counter is 1024 bus clock cycles
ICOVW=0xff; //The related capture register or holding register cannot be written by an event unless they are empty
ICSYS=0x00; //Normal operation;The timer flags C3F&C0F in TFLG1 are set when a valid input capture transition on the corresponding port pin occurs.
TFLG1=0xc0; //Clear all interrupt flag
TFLG2=0x80; //Clear main timer overflow flag

TIE_C6I=TC6MODE>>2; 

ICPAR_PA0EN=TC0MODE>>3; //Pulse Accumulator PACN0
ICPAR_PA1EN=TC1MODE>>3; //Pulse Accumulator PACN1 `
ICPAR_PA2EN=TC2MODE>>3; //Pulse Accumulator PACN2
ICPAR_PA3EN=TC3MODE>>3; //Pulse Accumulator PACN3

}

0 Kudos
1 Reply

755 Views
lama
NXP TechSupport
NXP TechSupport

There is no possibility to check the application logic without entire project.  Moreover, it is out of our scope to solve application issues caused by SW logic. For this purpose paid support should be contacted.

 

The best solution to get  duty cycle (for example left aligned) is to:

- If frequency is constant then enable interrupt on both edges and calculate period between rising and falling edge. The calculation can be then done anytime in dependence on current interrupt (whether it is from rising or falling edge.)

- If the frequency is variable then, if it is possible, it is good to connect to two inputs and set one for rising edge and the other one for falling edge. The calculation and processing is then easier.

- If the frequency is variable then, if it is possible, it is good to connect to two inputs and set one for rising edge and the other one for falling edge. The calculation and processing is then easier.

- If we have the only one input then we should set interrupt for both edges. The issue can be for small duty cycle when processing time is longer then time between two edges.

Plus, in all items above, there is additional issue with timer overflow processing. It adds some necessary conditions and calculations

 

The first issue I see is interrupt clearing.

Correct is TFLG1 = 0x80;  // Clears interrupt flag from C7F only even more flags are set to 1.

See also https://community.nxp.com/message/1321059?commentID=1321059#comment-1321059

 

I can be wrong but I am not sure of period calculation.

I have attached a frequency measurement example together with calculations. You can compare with your and/or test in the first approach.

It is different MCU but the same peripheral (a little bit different names)

If you enable both edges and implement rising/falling edge logic you can easily adjust the code.

best regards,

Ladislav

0 Kudos