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.

MSP430F5438 - PWM Generation on TimerA0

Other Parts Discussed in Thread: MSP430F5438

I am designing a simple motion sensor driven by the MSP430F5438.  In order to make it work I need to drive a 40 kHz pwm signal into the sensor.  I used example code to first learn how the PWM signal works.  This is the code I used at first (watchdog timer disable excluded for brevity), which will drive a PWM signal out of pins 27 and 28, also denoted as P2.2/TA1.1 and P2.3/TA1.2.  Using an oscilloscope I verified the correct output. 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 P2DIR |= 0x0C;                            // P2.2 and P2.3 output
  P2SEL |= 0x0C;                            // P2.2 and P2.3 options select
  TA1CCR0 = 128;                            // PWM Period/2
 
  TA1CCTL1 = 0x80;//OUTMOD_4;                      // CCR1 toggle
  TA1CCR1 = 32;                             // CCR1 PWM duty cycle
 
  TA1CCTL2 = OUTMOD_4;                      // CCR2 toggle
  TA1CCR2 = 96;
 
  TA1CTL = TASSEL_2 + MC_1 + TACLR;         // SMCLK, up-down mode, clear TAR

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

My problem comes in that I need to use pin 22 to drive my output, which is also denoted P1.5/TA0.4.  I understand how to change my pin selections and I believe I have changed the control registers correctly yet I still get nothing out of the pin.  Below is the code I am using to try to drive it. 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

P1DIR |= 0x20;                            // P1.5 Output
 P1SEL |= 0x20;                            // P1.5 Option Selection
 
  TA0CCR0 = 128;                            // PWM Period
  TA0CCTL1= OUTMOD_4;                      // Toggle Output
  TA0CCR1 = 384;                            // CCR1 PWM duty cycle
  TA0CTL = TASSEL_2 + MC_3 + TACLR;         // ACLK, up/down mode, clear TAR

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

If anyone understands what I'm doing wrong I'd appreciate any help given. 

 

  • your code is doing 2 differnet things.. the capture register you are using is asking for a different output port than you are enabling the functions for.. if you are using ta0.4 then you need to use CCR4

  • Thanks for the reply!  I think I understand it now, since the previous code was using ta1.1 and ta1.2 then it was necessary to use CCR1 and CCR2 respectively.  Therefore, since I need to use ta0.4 I need to use CCR4, or the following code. 

     

    //////////////////Pin Selection////////////////////////////
     
      P1DIR |= 0x20;                            // P1.5 Output
      P1SEL |= 0x20;                            // P1.5 Option Selection
    ///////////////////////////////////////////////////////////
     
    //////////////////PWM Setup//////////////////////////////// 
      TA0CCR0 = 128;                            // PWM Period
     
      TA0CCTL4 = OUTMOD_4;                      // Toggle Output
      TA0CCR4 = 32;                            // CCR1 PWM duty cycle
     
      TA0CTL = TASSEL_1 + MC_3 + TACLR;         // ACLK, up/down mode, clear TAR
     
    ///////////////////////////////////////////////////////////////////////////

    I assume this is correct because I am now getting a proper pwm signal out of my pin 22.  Thanks for the help!

  • no problems.. I didn't want to give you the complete solution, but point you towards your mistake since it generally works better towards understanding.

     

     

  • Hello!

    I am newbe, and I do not understand PWM in details...

      TA1CCR0 = 128;                            // PWM Period/2
     
      TA1CCTL1 = 0x80;//OUTMOD_4;                      // CCR1 toggle
      TA1CCR1 = 32;                             // CCR1 PWM duty cycle
     
      TA1CCTL2 = OUTMOD_4;                      // CCR2 toggle
      TA1CCR2 = 96;

    I understand folowing:

    in TA1CCR0 is PWM period

    in TA1CCTL1 is 25% width pulse (which will be generated on P2.2)

    in TA1CCTL2 is 75% width pulse (which will be generated on P2.3)

     

    My questions are:

    What is frekvency of PWM (in kHz or MHZ)?

    What is frequency of microcontroller?

    What is relation betwen microcontroller frequency, PWM frequency and numbers which needs to be specified

    For example. If microcontroler is running on 8Mhz, and I want PWM of 500kHZ, 50% of pulse on, 50% of pulse off. How should I set up  TA1CCR0 , TA1CCTL1 and TA1CCTL2 ?

     

     

     

     

  • First, you need to select a clock source for Timer1. This may be ACLK, SMCLK or whatever is supported by the timer module. Then divide this clock frequency by twice the required 500kHz and subtract one. This is your TA1CCR0 value.

    What happens? Each clock impulse, TA1 is incremented by one. Once it reaches TA1CCR0, it begins to be decremented again down to 0, then up again and so on. The frequency with which it hits every stage on this ladder is TA1CLK/TA1CCR0.

    Next step is to pick a position on this ladder where you want your output shall be toggled. Once when climbing up, once when descending down.

    If you pick a place in the middle (TA1CCR0/2), you'll end up with 50% duty cycle. When you seelct a higher or lower value, your duty cycle gets higher or lower.

    It makes no difference for this whether you pick TA1CCR1 or 2 or how many CCRs are available on your processor, the mechanism is always the same. Just the CCR registers and the associated port pin change. (Don't forget to select the port pin for timer module instead of standard I/O).

    With a PWM frequency of 500KHz, you'll need a timer clock way above that to have a range to pick your desired PWM values. (1MHz/1MHz is just 1). But then, you only need 50% duty cycle, so you don't need PWM at all, just a clock output of 500KHz. So you can leave TimerA and program your ACLK to run at 500KHz. With a Qzartz or DCO clock frequency of, say, 1 MHz, just set the ACLK with a clock divider of 2 and enable the ACLK output pin. This way you'll end up with a 500MHz signal and 50% duty cycle. With 4 MHz DCO, select a divider of 8 and with 8MHz one of 16 for ACLK. If you need ACLK for something else, you can use SMCLK instead (and the SMCLK output pin)

  • Thank you for such a quick response...
     
    This is my situation. I am using MSP430 5438.
    Some other colleague wrote clock setup module.
    I can see on P11.0 (ACKL) 32 kHz, on P11.1 (MCKL) 8 MHz, and on P11.2 (SMCKL) 8 MHz.
    I connected them on oscilloscope...
    So, it is working...
     

    Now, on pins P4.5 and 4.6 I need to generate PWM signal of 500 kHz. With 50% of pulse width. And P4.5 must be inverse to P4.6. So, I made this code, but nothing happens:
     
    P4DIR |= 0x60;
    P4SEL |= 0x60;
     
     
    TB0CCR0 = 16;                /*  PWM period = 8Mhz/16 = 500 kHZ == my desired frequency*/
     
    TB0CCR1 = 8;                 /* first PWM output will cover 50% of pulse */
    TB0CCTL1 = OUTMOD_7;         /* reset/set mode */
    TB0CCR2 = 8;                 /* second PWM output will cover 50% of pulse */
    TB0CCTL2 = OUTMOD_4;         /* set/reset mode (to be inverted to first PWM) */
     
    TB0CTL = (TBSSEL_2 + MC_1 + TBCLR);  /* select SMCLK (8MHz) as clock source, up mode, clear) */
  • Well, this one seems simple:

    Setting TBCLR resets TB. This includes the counter itself, the clock divider and the count direction. This means, your setting of MC_1 is overridden with MC_0.

    Do

    TB0CTL=TBCLR;

    TB0CTL= (TBSSEL_2| MC_1);

    then it should work.

    p.s.: using '|' instead of '+' might lead to more efficient code when the values are bit combinations, depending on the compiler. Especially using x |=y|z is usually faster than x = x+y+z;

     

  • Well...

    I replaced:

    TB0CTL = (TBSSEL_2 + MC_1 + TBCLR);

    with:

      TB0CTL=TBCLR;

      TB0CTL= (TBSSEL_2| MC_1);

     

    But, nothing happend... No output on P4.5 or P4.6 (pins 48 and 49)

     

    Jens-Michael Gross said:
    p.s.: using '|' instead of '+' might lead to more efficient code when the values are bit combinations, depending on the compiler. Especially using x |=y|z is usually faster than x = x+y+z;

    Well, I am newbe...

     

  • If you want a PWM output on P4.5 and P4.6, which is TB0.5 and TB0.6, you should use TB0CCR5/6 and TB0CCTL5/6 instead of 1/2, as TB0CCR1/2 are output at P4.1 and P4.2 :)

    As for the programming thing, this is rather special knowledge. The MSP has dedicated CPU commands for setting and clearing bits. So if you use bit manipulation  functions ( '|', '&', "~"), the compiler can use these instead of reading the destination, doing some additions and storing the result back. Same is true for shift operations instead of multiplication/division by 2.

  • I configured wrong port. Newbe, newbe, newbe... It solved my problem, and now I see perfect output. It works!

    Thank you

    (You already answerd my question on topic related to microsecond delay. Thank you for that. Soon, I will have more questions about counting impulses, but I will start new topic...)

  • I am using MSP EXP430F5438 experimenter board. For me Timer A si working properly on P1.5. However, I was not able to see any Output on P4.5 or P4.6 with Timer B.

    Are there any restictions on Timer B comapred to Timer A. Any help is appreciated..

    Regards

    VR

  • There shouldn't be any differences between using TB0.5 /TB0.6 compared to TA0.4
    Neither the port logic nor the board schematics show anything that could interfere.
    Do TB0.1 to TB0.3 work? (TB0.4 is connected to the audio output)
    Did you test the correct connector pins? With P4.4 missing, P4.5 is where you would expect P4.4 etc. Well, I guess it is labeled on the board, but...

    If your problems persist, you should perhaps post your code (use the 'insert code feature' in the rich formatting editor)

**Attention** This is a public forum