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 MSP432P401R



Hi, im trying to understand the timer A code in library. I need to set the frequency as well as the duty cycle but there is no explanation/comment in the code. can anyone tell me where do i need to change the number so i can put my desired frequency and duty cycle? also, where do i need to set the LED pin as my output ? for example, im using P1.0 for red LED. I've tried to look up some examples online but there is so little info about msp432. in this case, there is no led lit up. where can i set something like P1DIR = 0x00? for led P1.0. I want to see the LED lights up

#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

/* Standard Includes */
#include <stdint.h>
#include <stdbool.h>

//![Simple Timer_A Config]
/* Timer_A PWM Configuration Parameter */
Timer_A_PWMConfig pwmConfig =
{
        TIMER_A_CLOCKSOURCE_SMCLK,
        TIMER_A_CLOCKSOURCE_DIVIDER_1,
        32000,
        TIMER_A_CAPTURECOMPARE_REGISTER_1,
        TIMER_A_OUTPUTMODE_RESET_SET,
        3200
};
//![Simple Timer_A Config]

int main(void)
{
    /* Halting the watchdog */
    MAP_WDT_A_holdTimer();

    //![Simple Timer_A Example]
    /* Setting MCLK to REFO at 128Khz for LF mode
     * Setting SMCLK to 64Khz */
    MAP_CS_setReferenceOscillatorFrequency(CS_REFO_128KHZ);
    MAP_CS_initClockSignal(CS_MCLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    MAP_CS_initClockSignal(CS_SMCLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_2);
    MAP_PCM_setPowerState(PCM_AM_LF_VCORE0);

    /* Configuring GPIO2.4 as peripheral output for PWM  and P6.7 for button
     * interrupt */
    MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4,
            GPIO_PRIMARY_MODULE_FUNCTION);
    MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);
    MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);

    /* Configuring Timer_A to have a period of approximately 500ms and
     * an initial duty cycle of 10% of that (3200 ticks)  */
    MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
    //![Simple Timer_A Example]

    /* Enabling interrupts and starting the watchdog timer */
    MAP_Interrupt_enableInterrupt(INT_PORT1);
    MAP_Interrupt_enableSleepOnIsrExit();
    MAP_Interrupt_enableMaster();

    /* Sleeping when not in use */
    while (1)
    {
        MAP_PCM_gotoLPM0();
    }
}

/* Port1 ISR - This ISR will progressively step up the duty cycle of the PWM
 * on a button press
 */
void PORT1_IRQHandler(void)
{
    uint32_t status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);

    if (status & GPIO_PIN1)
    {
        if(pwmConfig.dutyCycle == 28800)
            pwmConfig.dutyCycle = 3200;
        else
            pwmConfig.dutyCycle += 3200;

        MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
    }
}

  • Halimatus,

    Have you seen this example?
    dev.ti.com/.../

    The MSP432P401R LaunchPad out of box code also is usefull and has a good PWM example:
    dev.ti.com/.../

    Please investigate these code examples and see how you can use the PWM and if you have any more questions, let us know.
  • Yes i have looked at it! I didnt know where to change the frequency and duty cycle. Mind to explain?

  • I still dont know where to change the frequency and duty cycle. Also where do i need to change the Led pin number? I want to use the red led P1.0
  • Halimatus,

    You can change the frequency by changing your clock source/clock source frequency for Timer A. This is up to you which clock you want to use and how to set it up. You can find more examples on clock source in the same place, labeled "cs_...".

    As far as duty cycle, you change the duty cycle in the Timer_A_PWMConfig struct. Please review the Driverlib API Guide for more information:
    dev.ti.com/.../

    Go to datastructures and then _Timer_A_PWMConfig for more information.
  • im still confused where to put for example 60 hz and duty cycle of 25?

    /* DriverLib Includes */

    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>

    /* Standard Includes */

    #include <stdint.h>

    #include <stdbool.h>

    //![Simple Timer_A Config]

    /* Timer_A PWM Configuration Parameter */

    Timer_A_PWMConfig pwmConfig =

    {

           TIMER_A_CLOCKSOURCE_SMCLK,

           TIMER_A_CLOCKSOURCE_DIVIDER_1,

           32000,

           TIMER_A_CAPTURECOMPARE_REGISTER_1,

           TIMER_A_OUTPUTMODE_RESET_SET,

           3200

    };

    //![Simple Timer_A Config]

    int main(void)

    {

       /* Halting the watchdog */

       MAP_WDT_A_holdTimer();

       //![Simple Timer_A Example]

       /* Setting MCLK to REFO at 128Khz for LF mode

        * Setting SMCLK to 64Khz */

       MAP_CS_setReferenceOscillatorFrequency(CS_REFO_128KHZ);

       MAP_CS_initClockSignal(CS_MCLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);

       MAP_CS_initClockSignal(CS_SMCLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_2);

       MAP_PCM_setPowerState(PCM_AM_LF_VCORE0);

       /* Configuring GPIO2.4 as peripheral output for PWM  and P6.7 for button

        * interrupt */

       MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4,

               GPIO_PRIMARY_MODULE_FUNCTION);

       MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);

       MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);

       MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);

       /* Configuring Timer_A to have a period of approximately 500ms and

        * an initial duty cycle of 10% of that (3200 ticks)  */

       MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);

       //![Simple Timer_A Example]

       /* Enabling interrupts and starting the watchdog timer */

       MAP_Interrupt_enableInterrupt(INT_PORT1);

       MAP_Interrupt_enableSleepOnIsrExit();

       MAP_Interrupt_enableMaster();

       /* Sleeping when not in use */

       while (1)

       {

           MAP_PCM_gotoLPM0();

       }

    }

    /* Port1 ISR - This ISR will progressively step up the duty cycle of the PWM

    * on a button press

    */

    void PORT1_IRQHandler(void)

    {

       uint32_t status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);

       MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);

       if (status & GPIO_PIN1)

       {

           if(pwmConfig.dutyCycle == 28800)

               pwmConfig.dutyCycle = 3200;

           else

               pwmConfig.dutyCycle += 3200;

           MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);

       }

    }

  • Also, please refer to the datasheet and TRM for information on the Clock System.

    Datasheet:www.ti.com/.../msp432p401r.pdf
    TRM: www.ti.com/.../slau356g.pdf

    Also, on changing the pin you wish to use, you will have to port map a timer A output to P1.0.

    Port mapping example that actually does some PWM also: dev.ti.com/.../
  • can you give an example? i mean i want to use frequency of 60 hz and duty cycle of 25?
    i read some notes online and they say CCR0,CCR1,CCR2,CCR3 has its own duty cycle?
  • since i want to use 60hz then the equation will be 24000000(24MHz) /60(Hz) ?
  • Halimatus,

    Have you read the Technical Reference Manual on Timer A and referred to the API documentation? It helps explain a lot of the questions you are asking.

    That said, to give you an idea on how the code example you've pointed to above, let me walk you through it and you can go ahead and make the changes that you need to do whatever you want. 

    Halimatus Karim said:

    Timer_A_PWMConfig pwmConfig =

    {

           TIMER_A_CLOCKSOURCE_SMCLK,

           TIMER_A_CLOCKSOURCE_DIVIDER_1,

           32000,

           TIMER_A_CAPTURECOMPARE_REGISTER_1,

           TIMER_A_OUTPUTMODE_RESET_SET,

           3200

    };

    This is the Timer_A_PWM config structure. Here you can set a variety of things such as the source clock for Timer A, which will help you create your PWM, the period, and the duty cyle. Please refer to the API documentation I've linked above for more information. 

    Halimatus Karim said:

       /* Setting MCLK to REFO at 128Khz for LF mode

        * Setting SMCLK to 64Khz */

       MAP_CS_setReferenceOscillatorFrequency(CS_REFO_128KHZ);

       MAP_CS_initClockSignal(CS_MCLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);

       MAP_CS_initClockSignal(CS_SMCLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_2);

    Here you are setting MCLK to REFO at 128KHz and setting SMCLK (which is the source of Timer A above) to 64kHz (because of the CS_CLOCK_DIVIDER_2 128/2 = 64).

    Halimatus Karim said:

       /* Configuring GPIO2.4 as peripheral output for PWM  */

       MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4,

               GPIO_PRIMARY_MODULE_FUNCTION);

    Here is the output of your PWM which will come out on P2.4 pin.  

    Halimatus Karim said:

       /* Configuring Timer_A to have a period of approximately 500ms and

        * an initial duty cycle of 10% of that (3200 ticks)  */

       MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);

    Here is the start of the Timer which sets it to be a PWM. You notice that you have a period of approx 500ms (2Hz). Which is 32000(period set in pwm config struct)/64KHz(timer a source clock) = 500ms period. With a 10% duty cycle, they have set the number of ticks to 3200 in the pwm config struct (.10*32000). 

    To get to 60Hz with a duty of 25%, you will have to manipulate the PWM config struct appropriately according to your clock settings that source Timer A. 

    1/60Hz = period = x/64000 where x is the number of ticks Timer A needs to count for 1 period at 64kHz clock source frequency. 

    .25 * x = y where y is your number of ticks for your duty cycle for x. 

    X and Y will then go into your pwm config struct in the appropriate places. 

    I hope this helps you understand better to generate your PWM. Please feel free to ask any questions. 

  • Oh yes, thank you. i feel better now . Im currently working on getting led blinking on the board but human's eyes cannot see it but when i record using camera i can see the blinking (after extracting the frames) . i believe our eyes can only see up to 24fps ~30 fps and the frequency is 60hz. Also, from what I understand from some research 20% duty cycle at 100 hz will look steady compared to 20%duty cycle at 10hz which will look like it on and off. I also read somehwere online that if 75% duty cycle the LED does not blink at all compared to 50% duty-cycle. can you explain more about this? do i need to change the duty cycle or the frequency to make the led only visible to camera but not to our eyes?
  • Halimatus,

    That sounds cool! To be honest, I'm not exactly sure that I can provide more detail on your question without the resource you are describing. All i can say is that 75% duty cycle will effectively be off half as long as anything with a 50% duty cycle by nature, so it may appear on, when it is actually flickering. All of this depends upon the period of your pwm of course though.

    If I've answered the post to your liking for now, please verify an answer. If you have any more questions, on this or anything else, please feel free to ask/create another thread on a new topic if you have one.

**Attention** This is a public forum