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.

missing pwm signal in msp430g2553 in up/down mode

Other Parts Discussed in Thread: MSP430G2553

Dear all

please let me know how to update the pwm duty cycle in msp430g2553 in up/down mode. with duty cycle array which is like pwmduty[]={0, 31, 59, 81, 95, 100, 95, 81, 59, 31}. i am using TAIF in timer interrupt to update the duty cycle but in some points like the values from 31 to 0 it's giving invalid pwm.

  • Most probably this is coding error
  • Dear 

    Can you please show some sample codes how to update that pwm values in timer interrupt of TAIF. how can we synchronize timer speed with cpu speed for the pwm update.

  • Hi Sun!

    Have a look at this example:

    It is for the MSP430G2553 and uses the timer module's hardware PWM. The update for the new duty-cycle happens when TAIFG causes an interrupt.


    Dennis

  • Dear Dennis,

    Thanks for your help. i tried your code with some modifications still that pwm is missing. can you please go through my code.

    thanks.

    #include "msp430G2553.h"
    #include <stdint.h>

    unsigned int const pwm[10]=={0, 31, 59, 81, 95, 100, 95, 81, 59, 31};
    unsigned int index=0;

    void main( void )
    {
    WDTCTL = (WDTPW | WDTHOLD); // Stop watchdog timer

    BCSCTL1 = CALBC1_16MHZ; // Set range to 8MHz
    DCOCTL = CALDCO_16MHZ; // Set DCO step and modulation to 8MHz

    P1SEL = 0x40; // Set special function of P1.6 (LED2) to timer module
    P1DIR = 0x40; // Set P1.6 (LED2) to output direction

    TA0CCR0 = (125 - 1); // Frequency 10kHz
    TA0CCR1 = 0; // Duty cycle 5%
    TA0CCTL1 = OUTMOD_6; // Reset / set
    TA0CTL = (TASSEL_2 | ID_0 | MC_3 | TACLR | TAIE); // SMCLK, divider 1, up-mode, clear, interrupt enabled

    _BIS_SR( GIE ); // Enable global interrupts

    while( 1 ); // Endless loop
    }

    // Timer0 A1 interrupt service routine
    #pragma vector = TIMER0_A1_VECTOR
    __interrupt void Timer0_A1_ISR( void )
    {
    static int duty = 0;
    TA0CTL &= ~TAIFG;
    if (index < 10)
    {
    duty = pwm[index];
    index++;
    }
    else
    {
    duty = pwm[0];
    index = 1;
    }
    TA0CCR1 = duty;
    }
  • SUN POST said:
    unsigned int const pwm[10]=={0, 31, 59, 81, 95, 100, 95, 81, 59, 31};

    Doesn't the compiler complain about this line?

    If you want to assign something you use the single '='. You use the double '==' to compare the value.

    Additionally you should change your comments to match the code, otherwise it is misleading because one cannot say if you want the code to do to what the code lines say, or if you wanted the code to behave like mentioned in the comments, but you just did it wrong.

    #include "msp430G2553.h"
    #include <stdint.h>
    
    unsigned int const pwm[10] == {0, 31, 59, 81, 95, 100, 95, 81, 59, 31}; // < ERROR: USE '=' INSTEAD OF '=='
    unsigned int index = 0;
    
    void main( void )
    {
      WDTCTL = (WDTPW | WDTHOLD);                       // Stop watchdog timer
    
      BCSCTL1 = CALBC1_16MHZ;                           // Set range to 8MHz                                    < WRONG
      DCOCTL = CALDCO_16MHZ;                            // Set DCO step and modulation to 8MHz                  < WRONG
    
      P1SEL = 0x40;                                     // Set special function of P1.6 (LED2) to timer module
      P1DIR = 0x40;                                     // Set P1.6 (LED2) to output direction
    
      TA0CCR0 = (125 - 1);                              // Frequency 10kHz                                      < WRONG
      TA0CCR1 = 0;                                      // Duty cycle 5%                                        < WRONG
      TA0CCTL1 = OUTMOD_6;                              // Reset / set                                          < WRONG
      TA0CTL = (TASSEL_2 | ID_0 | MC_3 | TACLR | TAIE); // SMCLK, divider 1, up-mode, clear, interrupt enabled  < WRONG
    
      _BIS_SR( GIE );                                   // Enable global interrupts
    
      while( 1 );                                       // Endless loop
    }

    Dennis

  • Dear Dennis

    Thanks for your reply. may be that == sign comes after i pasted the code in the blog editor sorry for that.
    can you check the code now.


    Thanks.

    #include "msp430G2553.h"
    #include <stdint.h>

    unsigned int const pwm[10]={0, 31, 59, 81, 95, 100, 95, 81, 59, 31};
    unsigned int index=0;

    void main( void )
    {
    WDTCTL = (WDTPW | WDTHOLD);

    BCSCTL1 = CALBC1_16MHZ;
    DCOCTL = CALDCO_16MHZ;

    P1SEL = 0x40;
    P1DIR = 0x40;

    TA0CCR0 = (125 - 1);
    TA0CCR1 = 0;
    TA0CCTL1 = OUTMOD_6;
    TA0CTL = (TASSEL_2 | ID_0 | MC_3 | TACLR | TAIE);

    _BIS_SR( GIE );

    while( 1 );
    }

    // Timer0 A1 interrupt service routine
    #pragma vector = TIMER0_A1_VECTOR
    __interrupt void Timer0_A1_ISR( void )
    {
    static int duty = 0;
    TA0CTL &= ~TAIFG;
    if (index < 10)
    {
    duty = pwm[index];
    index++;
    }
    else
    {
    duty = pwm[0];
    index = 1;
    }
    TA0CCR1 = duty;
    }
  • Deleting all comments is one of the possible options :)
    Do you have an oscilloscope to have a look at the signal output?
  • Dear Dennis,

    Please check the file.

    Thanks.

  • Dear Dennis,

    please check the wave form and advise me.

    thanks.
  • Sun,

    do you have to use the up/down mode for PWM generation? If yes, then did you already look at the code examples for the MSP430G2553 processor? You can download them here and they also contain one example about the up/down mode PWM generation:

    • msp430g2xx3_ta_19.c                        Timer_A, PWM TA1, Up/Down Mode, DCO SMCLK

    Then having a second look at the user's guide may not the worst idea. You find it here, chapter 12 is about the timer. There are graphs that show the timer's operation in it's different modes - for up/down mode it looks like this:

    Maybe you explain in detail what you expect from your program. What shall it do?

    Dennis

  • Dear Dennis,

    everything you send to me is ok. but i don't know why my pwm output showing some unwanted widths.


    Thanks.
  • Dear Dennis,

    I checked that file and this is the code available on that file
    #include <msp430.h>

    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1DIR |= 0x0C; // P1.2 and P1.3 output
    P1SEL |= 0x0C; // P1.2 and P1.3 TA1/2 options
    CCR0 = 128; // PWM Period/2
    CCTL1 = OUTMOD_6; // CCR1 toggle/set
    CCR1 = 32; // CCR1 PWM duty cycle
    TACTL = TASSEL_2 + MC_3; // SMCLK, up-down mode

    __bis_SR_register(LPM0_bits); // Enter LPM0
    }
    in that where i will update the pwm values.
  • The value in CCR1 will change your PWM duty-cycle. The period normally stays fixed. But this depends on your application, of course.
  • Dear Dennis,

    This is the thing that i asked in the starting can you help me to trace why the pwm having unwanted width i already send the code and wave form to you. i am again attaching the same for your reference. this is the code

    #include "msp430G2553.h"

    #include <stdint.h>

    unsigned int const pwm[10]={0, 31, 59, 81, 95, 100, 95, 81, 59, 31};

    unsigned int index=0;

    void main( void )

    {

    WDTCTL = (WDTPW | WDTHOLD);

    BCSCTL1 = CALBC1_16MHZ;

    DCOCTL = CALDCO_16MHZ;

    P1SEL = 0x40;

    P1DIR = 0x40;

    TA0CCR0 = (125 - 1);

    TA0CCR1 = 0;

    TA0CCTL1 = OUTMOD_6;

    TA0CTL = (TASSEL_2 | ID_0 | MC_3 | TACLR | TAIE);

    _BIS_SR( GIE );

    while( 1 );

    }

    // Timer0 A1 interrupt service routine

    #pragma vector = TIMER0_A1_VECTOR

    __interrupt void Timer0_A1_ISR( void )

    {

    static int duty = 0;

    TA0CTL &= ~TAIFG;

    if (index < 10)

    {

    duty = pwm[index];

    index++;

    }

    else

    {

    duty = pwm[0];

    index = 1;

    }

    TA0CCR1 = duty;

    }

    and this is the scope out. please advise.

    thanks.

  • What do you want the PWM to look like?
  • Dear Dennis,

    Please look the output wave form. my pwm values are 0, 31, 59, 81, 95, 100, 95, 81, 59, 31 but the wave form is having some unwanted widths.

    thanks.

  • Hi Sun!

    SUN POST said:
    but the wave form is having some unwanted widths.

    So which of the widths are correct and which are not? The processor does what you tell him, so you should explain what it shall look like.

    Dennis

  • Dear Dennis,

    Please have a look on the image the arrow mark shows the unwanted PWM

    Thanks.

  • Can you sort the number of your CCR value to the unwanted cycles?
  • Dear Dennis,

    Sorry I didn't understand what you mentioned.


    Thanks.
  • Which of your CCR values causes the unwanted output?
  • Dear Dennis,

    It may be 31 or 0


    Thanks.
  • If I were you I would test it to know for sure.

  • In your code, the timer generated interrupts too often and the CPU cannot handle them in time. The resulting waveform at P1.6 is difficult to predict.

    I slowed down the timer clock by a factor of 8x8=64. The result looks fine to me (but may not what you expect).

    #include "msp430G2553.h"
    #include <stdint.h>
    
    unsigned int const pwm[10]={0, 31, 59, 81, 95, 100, 95, 81, 59, 31};
    unsigned int index=0;
    
    void main( void )
    {
    WDTCTL = (WDTPW | WDTHOLD);
    
    DCOCTL = CALDCO_16MHZ;                                      //swap these 2 lines  
    BCSCTL1 = CALBC1_16MHZ;                                     //for safer clocking
    BCSCTL2 = DIVS_3;                                           //SMCLK is DCO/8
    
    
    P1SEL = 0x40;
    P1DIR = 0x40;
    
    TA0CCR0 = (125 - 1);
    TA0CCR1 = 0;
    TA0CCTL1 = OUTMOD_6;
    TA0CTL = (TASSEL_2 | ID_3 | MC_3 | TACLR | TAIE);           //clock by SMCLK/8
    
    _BIS_SR( GIE );
    
    while( 1 );
    }
    
    // Timer0 A1 interrupt service routine
    #pragma vector = TIMER0_A1_VECTOR
    __interrupt void Timer0_A1_ISR( void )
    {
    static int duty = 0;
    TA0CTL &= ~TAIFG;
    if (index < 10)
    {
    duty = pwm[index];
    index++;
    }
    else
    {
    duty = pwm[0];
    index = 1;
    }
    TA0CCR1 = duty;
    }

  • Dear,

    Thank you.
  • So with OCY's changes it works now as expected?
  • Dear

    I changed the pwm mode from MC_3 to MC_1 and adjusted my program.

    Thanks.
  • But this is a complete other mode of operation. I thought you wanted up/down mode?
  • Dear Dennis,

    I changed my pwm structure to mode to up mode . actually i need in up/down mode. if you can please correct my code and advise me.

    Thanks.

**Attention** This is a public forum