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.

CC2510: Timer 1 Channel 2 output compare

Part Number: CC2510

I am using Timer 1 Channel 2 as an output compare to send out a pulse each 5 seconds on P1_0.

I program the terminal cound to get us accuracy but when I enable the peripheral function of P1_0, I measure on the scope that the line already is set and not kept low until the terminal count is reached.

When the terminal count is reached, it will set the pulse as programmed but I don't know why it is already set after enabling the peripheral? 

In the manual it is stated that P1_0 does not have pull_up or pull_down capabilities and I have no impedance connected to the pin.

void main( void )
{
  EA = 0; // disable all interrupts
  P1SEL &= ~(BIT0);            // Set P1_0 as general purpose I/O
  P1DIR |= (BIT0);             // Set P1_0 as output
  P1INP &= ~(BIT0 | BIT2 | BIT4 | BIT5 | BIT7);            // Set P1_0 to pull-up/pull-down
  P2INP &= ~(P2INP_PDUP1);                                 // Set P1_0 to pull-up
  P1_0 = 0;
  
  // 1ms interrupt on timer1 (with highest priority)
  T1CTL &= ~T1CTL_CH2IF;                              // Clear Timer 1 Channel 2 interrupt flag
  T1CTL &= ~T1CTL_OVFIF;                              // Clear Timer 1 overflow interrupt flag

  T1CCTL2 &= ~T1CCTL2_IM;                             // Disbale Timer 1 Channel 2 interrupt mask
  OVFIM = 1;                                          // Enable Timer 1 overflow interrupt mask

  P2DIR = (P2DIR & ~P2DIR_PRIP0) | P2DIR_PRIP0_2;     // Order of precedense in case PERCFG assigns 2 peripherals to the same pins (Timer 1 channel 0 and 1 - USART1)
  P2SEL |= P2SEL_PRI0P1;                              // Give priority to Timer 1 over USART 0 for using port 1
  PERCFG |= PERCFG_T1CFG;                             // Timer1 to alternative location 2, P1_2  

  T1CCTL0 = (T1CCTL0 & ~T1CCTL0_CMP) | T1CCTL0_MODE | T1C0_SET_ON_CMP;  // Set Timer 1 Channel 0 to compare mode and set output on compare-up
  T1CC0L = 0xc7;                                      // Set Timer 1 Channel 0 compare value low byte
  T1CC0H = 0x32;                                      // Set Timer 1 Channel 0 compare value high byte

  T1CCTL2 = (T1CCTL2 & ~T1CCTL2_CMP) | T1CCTL2_MODE | T1C2_SET_ON_CMP; // Set Timer 1 Channel 2 to compare mode and set output on compare-up
  T1CTL = (T1CTL & ~(T1CTL_MODE | T1CTL_DIV)) | T1CTL_MODE_MODULO | T1CTL_DIV_1;  // First suspend Timer 1 operation and clear prescale divider, next set to modulo operation and divide tick frequency by 1
  T1IE = 1;                                           // Enable Timer 1 interrupt enable
  EA = 1; // enable all interrupts
  
  while(1)
  {
    ;
  }
}
__interrupt void timer1_ISR(void)
{
  if (T1CTL & T1CTL_OVFIF)
  {
    // keep this simple!
    T1CTL = (~T1CTL_OVFIF & 0xF0) | (T1CTL & 0x0F);
    timeTicker++;
	
    if(nextSyncReceivedTime.fraction > 6500) // 13000 cycles == 1 ms
    {
      if(timeTicker == nextSyncReceivedTime.time)
      {
	    // For some reason, the line also goes high after this code (which is not desired)
	    P1SEL |= BIT0;                    // P1_0 to peripheral function (Timer 1 CH 2 output, set output on next interrupt)
		
	    T1CCTL2 = (T1CCTL2 & ~T1CCTL2_CMP) | T1CCTL2_MODE | T1C2_SET_ON_CMP; // Set Timer 1 Channel 2 to compare mode and set output on compare-up
	    T1CC2L = (uint8)(nextSyncReceivedTime.fraction & 0x00ff);            // Set Timer 1 Channel 2 compare value low byte
        T1CC2H = (uint8)((nextSyncReceivedTime.fraction >> 8) & 0x00ff);     // Set Timer 1 Channel 2 compare value high byte
		timeTickClearComparePulseBeforeThisTimeTick = timeTicker + 5;
	  }
    }
	if(timeTickClearComparePulseBeforeThisTimeTick && (timeTicker >= timeTickClearComparePulseBeforeThisTimeTick))
    {
      // Enable the timer for I/O function
      P1SEL &= ~(BIT0);               // P1_0 to general purpose I/O (output was set during this interrupt)
	  P1_0 = 0;
	}
  }
}

Any assistance would be great.

  • I have found my error. If I enable the IO for peripheral use, the timer was still running on the previous setting.

    And setting the new terminal count was taking effect immediately. The error is that I did not stopped the timer, I only switch to general purpose IO.

    So to solve it I first have initialized Timer 1 Channel 2 to clear on compare and set the terminal count to 0.

    T1CCTL2 = (T1CCTL2 & ~T1CCTL2_CMP) | T1CCTL2_MODE | T1C2_CLR_ON_CMP; // Set Timer 1 Channel 2 to compare mode and clear output on compare-up
    T1CC2L = 0x0;                                      // Disable Timer 1 Channel 2 compare value low byte
    T1CC2H = 0x0;                                      // Disable Timer 1 Channel 2 compare value high byte

    If I then set the Timer 1 Channel 2 to set on compare, it will not set the line as was initialized.

    When I disable the Timer 1, I should do it completely and not only disable the peripheral function.

    if(timeTickClearComparePulseBeforeThisTimeTick && (timeTicker >= timeTickClearComparePulseBeforeThisTimeTick))
    {
      // Enable the timer for I/O function
      P1SEL &= ~(BIT0);                 // P1_0 to general purpose I/O (output was set during this interrupt)
      T1CCTL2 = (T1CCTL2 & ~T1CCTL2_CMP) | T1CCTL2_MODE | T1C2_CLR_ON_CMP; // Set Timer 1 Channel 2 to compare mode and clear output on compare-up
      T1CC2L = 0;                       // Disable Timer 1 Channel 2 compare value low byte
      T1CC2H = 0;                       // Disable Timer 1 Channel 2 compare value high byte
      P1_0 = 0;
          
      timeTickClearComparePulseBeforeThisTimeTick = 0;
    }

    This way I only see 1 pulse.