This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Timer is skipping?? MSP430FR5379

I have the following program to generate a train of modulated voltage pulses from P1.0 based on the values of a sequence stored in an array.

If it is 1, then the pin output is low for 750ns before changing to high. If it is 0, then output is low for 250ns before changing to high. The pulses must occur at a rate of 128kHz. P1.0 output is automatically controlled by TimerA0 whenever CCR0 or CCR1 is reached.

However, when tested using breakpoints, elements in the array are skipped when TA0CCR0 < approx. 100. When its value is increased, the sequence is read properly, but an oscilloscope shows that the length of each pulse is almost completely random, sometimes pulses are just skipped out all together. The elements skipped seems to change depending on minor changes e.g. whether 'position' or the array type is an integer or a character

This is a section of a larger program where 4 timers are being used simultaneously. Is it an issue with stack overflow, or am I just trying to change the values of TA0CCR1 in too short a space of time?

I can't see any reason for it to be doing this, is it possible that the MCU has been damaged at some point?

--------------------------------------------------

char ElectrodeSequence[32] =  {1,1,1,1,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0};

char position;

void main (void)

{

CSCTL0_H = 0xA5; // Unlock register
CSCTL1 = DCOFSEL_3; // Set DCO = 8MHz
CSCTL2 = SELA_1 + SELS_3 + SELM_3; // ACLK = vlo; SMCLK and MCLK = DCO
CSCTL3 = DIVA_0 + DIVS_0 + DIVM_0; // No Divider
CSCTL0_H = 0x01; // Lock Register

//Set P1.0 to be controlled by TimerA
P1DIR |= BIT0;
P1OUT &= ~BIT0;

P1SEL1 &= ~BIT0;
P1SEL0 |= BIT0;

TA0CTL = TACLR; //Reset TimerA
TA0CCTL0 = CCIE; //Enable interrupt
TA0CCTL1 = OUTMOD_3 + CCIE; //output mode set/reset and compare capture interrupt enable

TA0CCR0 = 63; //Read sequence at  approx. 128kHz
TA0CCR1 = 6; //First character is always 1 = 750ns

position = 0; //Start with first element in array


//Start timer//
TA0CTL = TASSEL_2 + MC_1; //SMCLK, count up to TA0CCR0

//Electrode pulse sequence//

while (position < 32); //Repeat until every digit has been read
TA0CTL = MC_0; //Stop timer

position = 0; //Reset position to 0

}

#pragma vector = TIMER0_A1_VECTOR
__interrupt void Timer_A1_ISR (void)
{
switch(TA0IV){

case 2:
{
if (ElectrodeSequence[position+1] == 1) //Read next digit in Sequence
{
TA0CCR1 = 6;
}

else if (ElectrodeSequence[position+1] == 0)
{
TA0CCR1 = 2; //Define interval for next digit depending on whether it is 1 or 0
}

TA0CCTL1 &= ~CCIFG; //Manually reset flag to prevent stack overflow
}

break;

}

}


#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0_ISR (void)
{
position++; //Move along Sequence

TA0CCTL0 &= ~CCIFG; //Manually reset to prevent stack overflow
}

  • Does the program output the correct timings when no breakpoints are set, or is it always producing the wrong results?

  • I only started using the breakpoints after I noticed how incorrect the oscilloscope trace was, so it doesn't work no matter what.

  • You're only giving yourself 63 clocks to get through Timer_A1_ISR (as well as one trip through Timer_A0_ISR), which is very tight -- you're probably overrunning (losing interrupts), at least sometimes.

    "position" should be "volatile" to avoid running past the end of the ElectrodeSequence[] array. More to the point, detecting end-of-array outside the ISR is hazardous, particularly since almost all of your CPU time is going to the ISR.

    Manually clearing the IFG is (in general) hazardous. Reading the TAIV (and getting the appropriate value) clears the IFG, so doing it again may clear an event you don't intend.

    It would be tempting to pre-compute the CCR1 values, and do nothing in the ISR but bump the pointer and stuff the value into CCR1. You might also get some breathing room by increasing your DCO speed to 16MHz.

**Attention** This is a public forum