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.

CC2540 Timer3 problem

Other Parts Discussed in Thread: CC2540, CC2530

 I am using TI keyfob CC2540 dev-kit. I would like to drive a LED blink by using Timer3 in period.  I let timer3 is working in modulo mode and the interruption will drive led on or off. However, I find that I can not go into timer interrupt. I paste my code here, please help me!

void ledInit(void)
{
   P1_5 = 1;                   //led output
   T3CTL = 0xee;           // tick frequency/128, overflow interrupt is enabled, clear counter,modulo mode
   TIMIF &= ~0x07;       //clear timer 3 interrupt
   T3CC0=0xf0;             //set the counter
   IEN1 |= 0x08;            ///enable interrput of Timer3   
   EA = 1;                      //enable all interrupt
   T3CTL |= 0x10;         //start timer3
}
#pragma vector = T3_VECTOR
__interrupt void T3_ISR(void)
{
   P1_5 = !P1_5;      //convert led state
}

 

 

  • Vincent Lau said:
    T3CC0=0xf0;             //set the counter

    Timer 3 is 8-bit so i think you set the compare register to 0?

    Never mind.

  • Dear Albert,

        I don't use timer 3 in compare mode. It is in module mode. I read 10.2.3 chapter in document literature number SWRU191C. It says that 8-bit counter starts at 0x00 and increaments at each active clock edge. After the count has reached the period value held in register txcc0, the counter is reset to 0x00 and continues to increment.

     

    Thanks a lot!

     

    Vincent

     

  • Yes, and 10.8 suggests T3CC0 only has 8 bits to assign. Now that would mean you set the period time to 0, because the high byte of the line I pointed out will simply be ignored, no? Try changing it to 0x0F or smaller.

    Sorry, too little coffee.

  • I tried T3CC0 as 0x0f and 0x04. It still doesn't work. In fact, I am using simpleBLEPeripheral demo code and I add ledInit() in SimpleBLEPeripheral_Init( uint8 task_id ) that is defined in simpleBLEPeriphiral.c

  • I'm not sure but I got a few ideas,

    2.5.1 recommends not using &= for clearing the interrupt flags, this should not be a problem in your case, but it also got me wondering something else: in some code I have been using, the interrupt flags are cleared manually, in the ISR. Have you tried this? Also that code has #pragma register_bank=2 right before the ISR declaration.

  • Hello Vincent Lau,

    In IAR, you can watch the interrupts for Timer3 and see if it is being cleared.

    Have you enabled P1_5 to an output somewhere in your code?

    Look at the hal_LED.c and Buzzer.c files.  You should try to use the naming convention from the HAL, it will make debugging and future coding easier.

    Here is how the PWM is set up from the Buzzer.c, you can make changes for P1_5 and having it interrupt instead.

    void PWM_Init(void)
    {
        // PWM connected at P1_7
        // We will use Timer 3 Channel 1 at alternate location 2
        // Channel 1 will toggle on compare with 1 and counter will
        // count in up/down mode to T3CC1.

        PERCFG |= 0x20;         // Timer 3 Alternate location 2
        P1DIR |= 0x80;              // P1_7 = output
        P1SEL |= 0x80;             // Peripheral function on P1_7

        T3CTL &= ~0x10;          // Stop timer 3 (if it was running)
        T3CTL |= 0x04;              // Clear timer 3
        T3CTL &= ~0x08;          // Disable Timer 3 overflow interrupts
        T3CTL |= 0x03;              // Timer 3 mode = 3 - Up/Down

        T3CCTL1 &= ~0x40;        // Disable channel 0 interrupts
        T3CCTL1 |= 0x04;            // Ch0 mode = compare
        T3CCTL1 |= 0x10;            // Ch0 output compare mode = toggle on compare

    }


    You can use the PWM function to change the frequency of the LED blinking from the Buzzer.c file as well:

    /** \brief    Starts PWM
    *
    * Starts the PWM with given frequency
    *
    * \param[in]       frequency
    *     The frequency in Hertz to output
    * @return  1 successful - 0 if frequency invalid
    */
    uint8 PWM_Frequency(uint16 frequency)
    {
       uint8 prescaler = 0;

        // Get current Timer tick divisor setting
        uint8 tickSpdDiv = (CLKCONSTA & 0x38)>>3;

        // Check if frequency too low
    //    if (frequency < (244 >> tickSpdDiv)){   // 244 Hz = 32MHz / 256 (8bit counter) / 4 (up/down counter and toggle on compare) / 128 (max timer prescaler)
    //        return 0;
    //    }

        // Calculate nr of ticks required to achieve target frequency
        uint32 ticks = (8000000/frequency) >> tickSpdDiv;      // 8000000 = 32M / 4;

        // Fit this into an 8bit counter using the timer prescaler
        while ((ticks & 0xFFFFFF00) != 0)
        {
            ticks >>= 1;
            prescaler += 32;
        }

        // Update registers
        T3CTL &= ~0xE0;
        T3CTL |= prescaler;
        T3CC0 = (uint8)ticks;

        // Start timer
        T3CTL |= 0x10;
    //#endif

        return 1;
    }

    Here is an example of an interrupt service routine:

    /***************************************************************************************************
     *                                    INTERRUPT SERVICE ROUTINE
     ***************************************************************************************************/

    /**************************************************************************************************
     * @fn      halKeyPort1Isr
     *
     * @brief   Port1 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/

    HAL_ISR_FUNCTION( halKeyPort1Isr, P0INT_VECTOR )
    {
      if (HAL_KEY_LS_PXIFG & HAL_KEY_LS_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_LS_PXIFG = ~(HAL_KEY_LS_BIT); /* Clear Interrupt Flag */
        CHANGE_VALUE = TRUE;
      }
      /*
        Clear the CPU interrupt flag for Port_1
        PxIFG has to be cleared before PxIF
      */
      HAL_KEY_LS_PXIFG = 0;

      HAL_KEY_CPU_PORT_1_IF = 0;
    }

  • Hi, all

    I use Timer3 as follow code, and I can go to timer interrupt. It reference as CC2530 code as they are almost same register

    #include <ioCC2540.h>

     #include "Led.h"

    unsigned int counter = 0;

     

    #define TIMER34_INIT(timer)   \   

    do {                       \      

     T##timer##CTL   = 0x06; \      

    T##timer##CCTL0 = 0x00; \      

     T##timer##CC0   = 0x00; \      

    T##timer##CCTL1 = 0x00; \      

     T##timer##CC1   = 0x00; \   

     } while (0)

    #define TIMER34_ENABLE_OVERFLOW_INT(timer,val) \  

         (T##timer##CTL =  (val) ? T##timer##CTL | 0x08 : T##timer##CTL & ~0x08)

    #define TIMER34_START(timer,val)                         \    

     (T##timer##CTL = (val) ? T##timer##CTL | 0X10 : T##timer##CTL&~0X10)

    #define TIMER34_SET_CLOCK_DIVIDE(timer,val)            \  

    do{                                                     \      

    T##timer##CTL &= ~0XE0;                              \      

    (val==2) ? (T##timer##CTL|=0X20):                   \      

     (val==4) ? (T##timer##CTL|=0x40):                   \      

     (val==8) ? (T##timer##CTL|=0X60):                   \      

     (val==16)? (T##timer##CTL|=0x80):                   \      

    (val==32)? (T##timer##CTL|=0xa0):                   \      

    (val==64) ? (T##timer##CTL|=0xc0):                  \      

    (val==128) ? (T##timer##CTL|=0XE0):                 \      

     (T##timer##CTL|=0X00);             /* 1 */          \  

     }while(0)

    #define TIMER34_SET_MODE(timer,val)                \  

    do{                                             \    

     T##timer##CTL &= ~0X03;                               \   

      (val==1)?(T##timer##CTL|=0X01):  /*DOWN            */ \   

      (val==2)?(T##timer##CTL|=0X02):  /*Modulo          */ \   

      (val==3)?(T##timer##CTL|=0X03):  /*UP / DOWN       */ \    

     (T##timer##CTL|=0X00);           /*free runing */     \

      }while(0)

    void ledInit(void)

    {

     #if defined ( CC2540_MINIDK )

    P1_5 = 1;   TIMER34_INIT(3);                  

     TIMER34_ENABLE_OVERFLOW_INT(3,1);

     EA = 1;   T3IE = 1;     

     TIMER34_SET_CLOCK_DIVIDE(3,128);       

     TIMER34_SET_MODE(3,0);                  

    TIMER34_START(3,1);      

    #endif

    }               

     

    #pragma vector = T3_VECTOR  __interrupt void T3_ISR(void)

     {      

      IRCON = 0x00;       

      if (counter<2441)     

     counter++;   

     else   

     {     

    counter=0;     

     P1_5 = !P1_5;   

    }   

      }

     

    Using writing Timer3 can go into timer interrupt. However, as osal layer may interface the timer. the led can blink 3 or 4 times then go into sleep mode.  

    In the end, I use osal_start_timerEx() funcation follow osal instrucation and add an SBP_LED_EVT event flag in process event. That is all!

     

    Thanks to anyone helps me!

     

    Vincent