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.

PWM Timer 1 output for CC2530

Other Parts Discussed in Thread: CC2530, REMOTI, Z-STACK, TIMAC, SIMPLICITI

Hello,

I am working on CC2530 PWM output Timer 1 on P0_2 port but when I start a program below ,I don't get pwm signals on P0_2.

This is my code :

P0DIR |= 0x04;   //  P0_2 port
P0SEL &= ~0x04;

P0_2 ^= 1; //  P0_2 set to be output

T1CTL |= 0x0f; // divide with 128 and to do i up-down mode

T1CC0L = 0xff;   // PWM signal period
T1CC0H = 0x7f;

T1CC1L = 0x78;  // PWM duty cycle
T1CC1H = 0x10;


T1CCTL1 |= 0x1c;

PERCFG |= 0x00;

Please can someone tell me what I am doing wrong and where is mistake...Thank You

  • I can see several errors here:

    First, you seem to be using Timer 1 channel 1. That channel can not be output on P0_2. It can be output at P0_3, though. Alternatively, you can use channel 0, which can be output at P0_2, but then you have fewer possibilities, since channel 0 is also the timer period.

    Second, you do P0SEL &= ~0x04;. This will set P0_2 to GPIO, not controlled by Timer 2. In order to set P0_2 to peripheral, set P0SEL |= 0x04;. In order to set P0_3 to peripheral, set P0SEL |= 0x08;

    Third, you need to set up the priority, otherwise you will get the UART output, not Timer 1. Do P2DIR = (P2DIR & ~0xC0) | 0x80; in order to set priority for Timer 1 channel 0-1.

    Besides, you do not need to set P0DIR or P0_2 when you use it as a peripheral output. Your last statement (PERCFG |= 0x00;) does nothing.

    The following code should work (I haven't tested it, though). Note that the output will be on P0_3 , not P0_2.

    PERCFG &= ~0x40; // Select Timer 1 Alternative 0 location
    P2DIR = (P2DIR & ~0xC0) | 0x80; // Give priority to Timer 1
    P0SEL |= 0x08;  // Set P0_3 to peripheral

    T1CC0L = 0xff;   // PWM signal period
    T1CC0H = 0x7f;

    T1CC1L = 0x78;  // PWM duty cycle
    T1CC1H = 0x10;

    T1CCTL1 = 0x1c;

    T1CTL |= 0x0f; // divide with 128 and to do i up-down mode

  • Thank You for Your fast answer.Code that You wrote works perfectly :)

  • Another question..If I want to send pwm out at the same time on Port P0_2,P0_3,P0_4 and P0_5 what should I do? How to write code for that?

  • You then have to use several Timer 1 channels. Do you want the same or different PWM signals? Note that since P0_2 is controlled by Channel 0, it has limited PWM possibilities, because it is also the timer period, meaning that it is difficult to get anything other than 50% duty cycle. So you should consider to use P0_6 instead of P0_2.

    Each of the channels need to be set up similar to channel 1. The pins have to be selected as peripheral using P0SEL. (P0SEL |= 0x3C; to use P0_2-P05, P0SEL |= 0x78 to use P0_3-P0_6.) In order to get priority for all the Timer 1 pins, you will need to move both UART0 and UART1 to Alternative 2 location, i.e. PERCFG |= 0x03;.

  • In my project it's used p0_2 to P0_5...For now I use the same pwm signal for all ports.But If it isn't difficult to You toi explain to me how to write code with same PWM on every port and different PWM.Tnakn You

  • Again, on P0_2 you can only get 50% duty cycle unless you can use free-running mode, which will limit the available settings for the period. The period you are using now is 131 ms, provided that you use the maximum tick speed (32 MHz). If you change to free running mode, you have to choose between a period of 65.5 ms and 262 ms using the maximum tick speed. But if you use a tick speed of 16 MHz, you can get a period of 131 ms in free-running mode using a presacler of 32. See the CLKCONCMD register on how to change the tick speed.

    If you want more concrete advice on this, please let me know what your requirements are for the period and the duty cycle.

    A program can look something like this. Here, I have set up the same duty cycle on all channels except channel 0. To use different duty cycle for some of the channels, just change the value of T1CCnL/T1CCnH for those channels.

    PERCFG &= ~0x40; // Select Timer 1 Alternative 0 location
    PERCFG |= ~0x03; // Move USART0 and USART1 to Alternative 2 location to allow all Timer 1 channels on P0
    P2DIR = (P2DIR & ~0xC0) | 0x80; // Give priority to Timer 1
    P0SEL |= 0x3C;  // Set P0_2-P0_5 to peripheral

    T1CC0L = 0xff;   // PWM signal period
    T1CC0H = 0x7f;

    T1CCTL0 = 0x1c; // Channel 0 in compare mode, Set output on compare-up, clear on 0 (50% duty cycle)

    T1CC1L = 0x78;  // PWM duty cycle, Channel 1 (P0_3)
    T1CC1H = 0x10;

    T1CCTL1 = 0x1c; // Channel 1 in compare mode, Set output on compare-up, clear on compare-down

    T1CC2L = 0x78;  // PWM duty cycle, Channel 2 (P0_4)
    T1CC2H = 0x10;

    T1CCTL2 = 0x1c; // Channel 2 in compare mode, Set output on compare-up, clear on compare-down

    T1CC3L = 0x78;  // PWM duty cycle, Channel 3 (P0_4)
    T1CC3H = 0x10;

    T1CCTL3 = 0x1c; // Channel 3 in compare mode, Set output on compare-up, clear on compare-down

    T1CC4L = 0x78;  // PWM duty cycle, Channel 4 (P0_5)
    T1CC4H = 0x10;

    T1CCTL4 = 0x1c; // Channel 4 in compare mode, Set output on compare-up, clear on compare-down

    T1CTL |= 0x0f; // divide with 128 and to do i up-down mode

  • Thank You again for Your fast answer. But code that You send me doesn't works.What Do you think what is wrong? If I need more advise I ask You :)

  • It seems I made a mistake on the second line of code. It is supposed to be

    PERCFG |= 0x03; // Move USART0 and USART1 to Alternative 2 location to allow all Timer 1 channels on P0

    i.e., lose the '~'.

    I still haven't tried the code, but I hope it is better now...

     

  • Thank You :)...Code is working and as You said on Port P0_2 duty cycle is 50%..I need 25% duty cycle so I know how that to change and how to play with.Thank You again vry much for helping me and fast answers.If I wuold have so questions I ask.

  • I have one more question. With this code T1CTL |= 0x0f I selected to work in up down mode and 32Mhz I divide with 128 so I get 250kHz..My question is how to select that pwm signal is working on 50kHz frequency?

  • It is not possible to get an update rate of 50 kHz, as you can only divide by powers of 2. But you can get below 250 kHz. To  do this, you need to use the TICKSPD feature, cf. Section 4.5 of the data sheet. For instance you can set the tick speed to 8 MHz and the prescaler to 128, which will give you an update rate of 62.5 kHz. Note that this will reduce the tick speed for Timer 3 and 4 as well as for Timer 1. The following instruction will set the tick speed to 8 MHz:

    CLKCONCMD = (CLKCONCMD & ~0x38) | 0x10;

  • Sorry for my late answer,thank You for your quick answer again, my LED's works fine :)

    I have another question. I need that duty cycle change automatically. For exaple to be at first 10% after 2second 20 % and that goes until gets 90%.Afterwords it goes to decrease duty cycle on same duty cycles but in different course. And to do that all the time to increase and decrease duty cycle. I hope that You can help me.Thanks

  • To do this, you need to set up an interrupt and let that interrupt update the duty cycle (update the T1CCnL/T1CCnH). One option is to set up an overflow interrupt on Timer 1. You will then get an interrupt for each period of the signal. You can update a counter in that ISR and change the duty cycle when the counter expires. The disadvantage of this solution is that you will get interrupts more frequently than strictly needed.

    Another way  is to use a different timer to time the updates. The best options are the sleep timer or Timer 2. The sleep timer uses a different clock source, so the duty cycle updates will not be synchronous to the PWM. You should be careful about using Timer 2, as it is normally used for the radio (e.g. if you are using Z-stack, RemoTI, TIMAC, or SimpliciTI). However, if that timer is free, it is long enough to generate interrupts every 2 seconds.

  • In SampleAPP i wrote this but it doesn't work,what I do wrong:

     if ( events & TOGGLE_TIMER_EVENT )
      {
       
        static int togle = 0;
        static short T1CC1 = 0x0240;
      
           if (togle == 0 && T1CC1 > 0x0020)
        {
          T1CC1 += 20;
       
        } else {
          togle = 1;
          }
      
         if (togle == 1 && T1CC1 < 0x0240)
        {
          T1CC1 = T1CC1 + 20;
       
        } else {
          togle = 0;
          }
          
            
        osal_start_timerEx( SampleApp_TaskID, TOGGLE_TIMER_EVENT , 2000);
          
     
        // return unprocessed events
        return (events ^ TOGGLE_TIMER_EVENT);
      }
      // Discard unknown events
      return 0;
    }

  • I want to PWM starts from 10% and go to 90% and then backwords

  • I have not worked with PWM using Timer1 so I hesitate to comment on your use of the T1CC1 register except: your static short T1CC1 = 0x0240; statement is working on a static variable that has the same name as the timer register -- probably not what you intended.

  • Which Timer You used and how do You solved that PWM is changing Duty cycle from exaple from 10% to 90%?

  • Hi,

        How can I modify code if I want  to output PWM signal on P1.3? Thanks.

  • Have a look in the User's Guide chapter 7.

    /Fredrik

  • I am using following code to get timer signal at P0_3.   It is working OK.

    But it takes 2ms for 1 time ON and 1 time OFF.  I need  that it will take 2ms for 5 times ON and 5 times OFF.

    For better understanding I have attached file.

    PERCFG  &= ~0x40;                 //select Timer  1 Alternative at Port 0 Location                                                                        
    PERCFG  |=  0x03;                 //Move USART0 and USART1 to Alternative 2 Location                                                                        
    P2DIR   = (P2DIR & ~0xC0) | 0X80; //Give priority to Timer 1                                                                        
    P0SEL   |=  0x08;                 // SET P0_3 AS PERIPHERAL                                                                        
    T1CC0L  = 0xFF;           //PWM signal period                                                           
    T1CC0H  = 0x7F;                                                                        
    T1CC1L  = 0x00;         //PWM Duty Cycle, Channel 1 (P0_3)                                                                        
    T1CC1H  = 0x01;                                                                        
    T1CCTL1 = 0x34;         //Channel 1 in compare Mode, Set output on Compare down,                                                                     
    T1CTL |= 0x01;        //Start the timer in free running Mode

    Waiting for beneficial reply.

    Thanks6012.5824.TIMER SPEED.xls

  • Hi All,

    This is Karthik and i am being working on cc2530ZDK now and i need to generate the four different pwm signals at the same time at four different GPIO ..I am posting the code below

    #define MAX_PWM_VAL 2047

     /* setup P1.0 as PWM output of CCR channel 2 */
      PERCFG |= 0x40; // T1CFG = 1: Timer 1 Alternative 2 location
      P1DIR |= 0x01; // P1.0 set to output
      P1SEL |= 0x01; // set P1.0 to peripheral function

      /* setup timer module */
      T1CC0H = HI_UINT16(MAX_PWM_VAL);
      T1CC0L = LO_UINT16(MAX_PWM_VAL);
      T1CTL |= 0x06 ; // 0000 01 10 -> 32MHz/8 = 4MHz, mode=modulo
      T1CCTL2 = 0x34; // 00 110 1 00 -> no interrupt, ch 2 compare = 6, compare mode, no capture



    #ifdef ZDO_COORDINATOR
      // set ADC module reference
      HalAdcSetReference(HAL_ADC_REF_AVDD);  
    #endif

    //NEXT FUNCTION

      UINT16 pwm_value;

     pwm_value = brightness * (MAX_PWM_VAL / 100);
     
      // set the new PWM value
      T1CC2H = HI_UINT16(pwm_value);
      T1CC2L = LO_UINT16(pwm_value);
    }

    As Mentioned above P1.0 is been used to generate the pwm signal using timer 1.It is Successful and i am able to see the output at IO_LED1 (Green LED) that is p1.0

    Similarly i am doing it for P1.1 and P1.4 but i am unable to generate the pwm signal .

    I would like to have some detailed information regarding this issue.

    Expecting the solution asap,

    Advance Thanks for the help

    Regards,

    KARTHIK V

  • i have a 16 bit values from 20 to 30 and i have to use pwm to control the speed of a dc motor .. i am using cc2530dk kit .. the problem is i am not able to find the function for using the pwm and i have no idea ... any comments pl 

  • Hi Dhileep,

    Have you looked at the user guide I linked to in my previous post? Everything you need to know about the timers is described there.

    Cheers,
    Fredrik

  • i couldnt find it sir !!! i needed to control the duty cycle with the digital values i have from 20 to 30 

  • Ok, I see that my original link is dead. Here is it again: http://www.ti.com/lit/pdf/swru191

    Have a look in chapters 9 and 10.