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.

EK-TM4C1294XL: TM4C1294NCPDT

Part Number: EK-TM4C1294XL
Other Parts Discussed in Thread: EK-TM4C129EXL, TM4C1294NCPDT

Dear Sir,

How can I generate the "delay time" between two or more PWM generators as below photo description?

4 PWMs period all is 100kHz, duty is 10%, and the "delay time" is 2.5uS / 5uS / 7.5uS respectively.

I have tried function "PWMPulseWidthSet()", but it can not working!

  • Hi,

      Let me share one idea on how to create a phase-shifted PWM for two PWMs. You can extend to more PWMs if you want.  

      The PWM generation will be based on the PWM Count-Down mode but I suppose you should be able get it working with up/down counter mode as well. In Count-Down mod, there are four events that can affect the PWM signals: zero, load, match A down and match B down.  

      1. On the first PWM, you will use two events. For example, let's say you set up the PWM period for 100. You will then set up event A  for 'load'. When the 'load' event happens, you will set the PWM pin high. You will also set up for the 2nd event to happen when there is a compare match at 90. When a match happens,  you will clear the PWM pin at 90. This will create a 10% duty cycle PWM.

      2.For the second PWM, you can use another PWM_GEN module. For this PWM, you can set up compare match A to set the PWM pin at 80 and another compare match B at 70 to clear the PWM. 

      3. Make sure the two PWM are synchronized to each other. 

      If you look at these two PWMs, you should see the first PWM set at 100 and clear at 90 and the second PWM set a 80 and clear at 70. There is a phase shift of 10 between the two PWMs.  

  • Hi Charles,

    Thanks for your reply!

    I have tried the following codes, but it can not working.

    There are no related APIs (I am not sure)? So I am trying [HWREG(PWM0_0_GENA_R) / HWREG(PWM0_0_GENB_R)  / HWREG(PWM0_0_CMPA_R) / HWREG(PWM0_0_CMPB_R) ] to create event A / B;

    Could you help me to review my codes? Thank you!

    //*****************************************************************************
    // pwm_8ch.c
    //*****************************************************************************

    void ConfigurePWM(void)
    {
        uint32_t ui32PWMClockRate;

        // The PWM peripheral must be enabled for use.
        MAP_SysCtlPeripheralEnable(CH0_CH1_CH2_CH3_PWM_PERIPH);

        // Enable the GPIO port that is used for the PWM output.
        MAP_SysCtlPeripheralEnable(CH0_CH1_GPIO_PERIPH);

        // Configure the PWM function for this pin.
        MAP_GPIOPinTypePWM(CH0_CH1_GPIO_BASE, CH0A_GPIO_PIN | CH0B_GPIO_PIN | CH1A_GPIO_PIN | CH1B_GPIO_PIN);
        MAP_GPIOPinConfigure(CH0A_PWM_MOUDLE_PIN);
        MAP_GPIOPinConfigure(CH0B_PWM_MOUDLE_PIN);
        MAP_GPIOPinConfigure(CH1A_PWM_MOUDLE_PIN);
        MAP_GPIOPinConfigure(CH1B_PWM_MOUDLE_PIN);

        // Set the PWM clock to be SysClk / 4.
        MAP_PWMClockSet(CH0_CH1_CH2_CH3_PWM_BASE, PWM_SYSCLK_DIV_4);

        // Use a local variable to store the PWM clock rate which will be 120MHz / 4 = 30MHz. This variable will be used to set the PWM generator period.
        ui32PWMClockRate = g_ui32SysClock / 4;

        // Configure PWM0 / PWM1 / PWM2 / PWM3 to count down with synchronization.
        MAP_PWMGenConfigure(CH0_CH1_CH2_CH3_PWM_BASE, CH0_PWM_GEN, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
        MAP_PWMGenConfigure(CH0_CH1_CH2_CH3_PWM_BASE, CH1_PWM_GEN, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

        // Set the PWM period to 100KHz. To calculate the appropriate parameter use the following equation: N = (1 / f) * PWMClk.
        // Where N is the function parameter, f is the desired frequency, and PWMClk is the PWM clock frequency based on the system clock.
        MAP_PWMGenPeriodSet(CH0_CH1_CH2_CH3_PWM_BASE, CH0_PWM_GEN, (ui32PWMClockRate / 100000));
        MAP_PWMGenPeriodSet(CH0_CH1_CH2_CH3_PWM_BASE, CH1_PWM_GEN, (ui32PWMClockRate / 100000));

        // The counter matches PWM0LOAD drive pwmA High and the counter matches comparator B drive pwmA Low
        HWREG(PWM0_0_GENA_R) = 0x80C;
        // The counter matches PWM0LOAD drive pwmB High and the counter matches comparator B drive pwmB Low
        HWREG(PWM0_0_GENB_R) = 0x80C;
        // Set PWM1CMPA for PWM CH0A / CH0B with a value of 0%
        HWREG(PWM0_0_CMPA_R) = 0;
        // Set PWM1CMPA for PWM CH0A / CH0B with a value of 10%
        HWREG(PWM0_0_CMPB_R) = MAP_PWMGenPeriodGet(CH0_CH1_CH2_CH3_PWM_BASE, CH1_PWM_GEN) -     (MAP_PWMGenPeriodGet(CH0_CH1_CH2_CH3_PWM_BASE, CH1_PWM_GEN) / 10);

        // The counter matches comparator A drive pwmA High and the counter matches comparator B drive pwmA Low
        HWREG(PWM0_1_GENA_R) = 0x8C0;
        // The counter matches comparator A drive pwmB High and the counter matches comparator B drive pwmB Low
        HWREG(PWM0_1_GENB_R) = 0x8C0;
        // Set PWM1CMPA for PWM CH1A / CH1B with a value of 25%
        HWREG(PWM0_1_CMPA_R) = MAP_PWMGenPeriodGet(CH0_CH1_CH2_CH3_PWM_BASE, CH1_PWM_GEN) * 3 / 4;
        // Set PWM1CMPA for PWM CH1A / CH1B with a value of 35%
        HWREG(PWM0_1_CMPB_R) = (MAP_PWMGenPeriodGet(CH0_CH1_CH2_CH3_PWM_BASE, CH1_PWM_GEN) * 3 / 4) - (MAP_PWMGenPeriodGet(CH0_CH1_CH2_CH3_PWM_BASE, CH1_PWM_GEN) / 10);

        // Enable PWM Out Bit 0 (PF0) / Bit 1 (PF1) / Bit 2 (PF2) / Bit 3 (PF3) output signal.
        MAP_PWMOutputState(CH0_CH1_CH2_CH3_PWM_BASE, CH0A_PWM_OUT_BIT | CH0B_PWM_OUT_BIT | CH1A_PWM_OUT_BIT | CH1B_PWM_OUT_BIT);

        // Enable the PWM generator block.
        MAP_PWMGenEnable(CH0_CH1_CH2_CH3_PWM_BASE, CH0_PWM_GEN);
        MAP_PWMGenEnable(CH0_CH1_CH2_CH3_PWM_BASE, CH1_PWM_GEN);
    }

    int main(void)
    {

        // Run from the PLL at 120 MHz.
        // Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
        // later to better reflect the actual VCO speed due to SYSCTL#22.
        g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_240), 120000000);

        ConfigurePWM();

        // Loop forever while the PWM signals are generated.
        while(1)
        {
        }
    }

    //*****************************************************************************
    // pwm_8ch.h
    //*****************************************************************************

    #ifndef PWM_8CH_H_
    #define PWM_8CH_H_

    #define CH0_CH1_CH2_CH3_PWM_PERIPH SYSCTL_PERIPH_PWM0
    #define CH0_CH1_CH2_CH3_PWM_BASE PWM0_BASE
    #define CH0A_PWM_MOUDLE_PIN GPIO_PF0_M0PWM0
    #define CH0B_PWM_MOUDLE_PIN GPIO_PF1_M0PWM1
    #define CH1A_PWM_MOUDLE_PIN GPIO_PF2_M0PWM2
    #define CH1B_PWM_MOUDLE_PIN GPIO_PF3_M0PWM3
    #define CH2A_PWM_MOUDLE_PIN GPIO_PG0_M0PWM4
    #define CH2B_PWM_MOUDLE_PIN GPIO_PG1_M0PWM5
    #define CH3A_PWM_MOUDLE_PIN GPIO_PK4_M0PWM6
    #define CH3B_PWM_MOUDLE_PIN GPIO_PK5_M0PWM7
    #define CH0_PWM_GEN PWM_GEN_0
    #define CH1_PWM_GEN PWM_GEN_1
    #define CH2_PWM_GEN PWM_GEN_2
    #define CH3_PWM_GEN PWM_GEN_3
    #define CH0A_PWM_OUT PWM_OUT_0
    #define CH0B_PWM_OUT PWM_OUT_1
    #define CH1A_PWM_OUT PWM_OUT_2
    #define CH1B_PWM_OUT PWM_OUT_3
    #define CH2A_PWM_OUT PWM_OUT_4
    #define CH2B_PWM_OUT PWM_OUT_5
    #define CH3A_PWM_OUT PWM_OUT_6
    #define CH3B_PWM_OUT PWM_OUT_7
    #define CH0A_PWM_OUT_BIT PWM_OUT_0_BIT
    #define CH0B_PWM_OUT_BIT PWM_OUT_1_BIT
    #define CH1A_PWM_OUT_BIT PWM_OUT_2_BIT
    #define CH1B_PWM_OUT_BIT PWM_OUT_3_BIT
    #define CH2A_PWM_OUT_BIT PWM_OUT_4_BIT
    #define CH2B_PWM_OUT_BIT PWM_OUT_5_BIT
    #define CH3A_PWM_OUT_BIT PWM_OUT_6_BIT
    #define CH3B_PWM_OUT_BIT PWM_OUT_7_BIT
    #define CH0_CH1_GPIO_PERIPH SYSCTL_PERIPH_GPIOF
    #define CH0_CH1_GPIO_BASE GPIO_PORTF_BASE
    #define CH2_GPIO_PERIPH SYSCTL_PERIPH_GPIOG
    #define CH2_GPIO_BASE GPIO_PORTG_BASE
    #define CH3_GPIO_PERIPH SYSCTL_PERIPH_GPIOK
    #define CH3_GPIO_BASE GPIO_PORTK_BASE
    #define CH0A_GPIO_PIN GPIO_PIN_0
    #define CH0B_GPIO_PIN GPIO_PIN_1
    #define CH1A_GPIO_PIN GPIO_PIN_2
    #define CH1B_GPIO_PIN GPIO_PIN_3
    #define CH2A_GPIO_PIN GPIO_PIN_0
    #define CH2B_GPIO_PIN GPIO_PIN_1
    #define CH3A_GPIO_PIN GPIO_PIN_4
    #define CH3B_GPIO_PIN GPIO_PIN_5

    #endif /* PWM_8CH_H_ */

  • Hi Howard,

      I don't really see a problem with your code except one thing. You need to synchronize both GEN_0 and GEN_1 using PWMSYNC, 


     

  • Hi Charles,
    Thanks for your reminder.

    I did another experiment, just use the evaluation board example C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c129exl\pwm_invert to modify slightly.

    Substitute MAP_PWMGenConfigure(PWM0_BASE, PWM_GEN_1, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
                for MAP_PWMGenConfigure(PWM0_BASE, PWM_GEN_1, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);

    Substitude HWREG(PWM0_1_GENA_R) = 0x8C0;
                      HWREG(PWM0_1_CMPA_R) = 1000;
                      HWREG(PWM0_1_CMPB_R) = 500;
                 for MAP_PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, MAP_PWMGenPeriodGet(PWM0_BASE, PWM_GEN_1) / 4);

    The main purpose is how to create event A / B, but there is still no PWM output.
    Should I set anything else for the program / properties ?

    P.S.: I have included the below:
    #include "inc/hw_types.h"
    #include "inc/hw_gpio.h"
    #include "inc/tm4c1294ncpdt.h"

  • Hi Howard,

      Can you even get the TivaWare pwm_invert example to work as is without any modification?

  • Hi Charles,

    Sure, it can be worked into my EVM, EK-TM4C129EXL (TM4C1294NCPDT).

  • Hi Howard,

     Did you setup the compare A and compare B values in your modified code?

  • Hi Charles,

    Yes. As below (the same as replied on Sep 9, 2021 1:02 AM):

    HWREG(PWM0_1_GENA_R) = 0x8C0;
    HWREG(PWM0_1_CMPA_R) = 1000;
    HWREG(PWM0_1_CMPB_R) = 500;

    No any output.

  • Hi Howard,

      Can you show the CCS register window content for PWM GENA, CMPA and CMPB registers?

    For some reason if I run the below three lines of code that you have, I will get a fault. 

    HWREG(PWM0_1_GENA_R) = 0x8C0;
    HWREG(PWM0_1_CMPA_R) = 1000;
    HWREG(PWM0_1_CMPB_R) = 500;

    if I replace with the below code, then it is working. I can see the waveform on the scope. 

    #define PWM0_1_GENA *((volatile uint32_t *)0x400280A0)
    #define PWM0_1_CMPA *((volatile uint32_t *)0x40028098)
    #define PWM0_1_CMPB *((volatile uint32_t *)0x4002809C)

    PWM0_1_GENA = 0x8C0;
    PWM0_1_CMPA = 1000;
    PWM0_1_CMPB = 500;

    Edit at 11:03am 9/9/2021: Below is also working. 

    #define PWM0_1_GENA 0x400280A0
    #define PWM0_1_CMPA 0x40028098
    #define PWM0_1_CMPB 0x4002809C

    HWREG(PWM0_1_GENA) = 0x8C0;
    HWREG(PWM0_1_CMPA) = 1000;
    HWREG(PWM0_1_CMPB) = 500;

    I think the fault I'm getting is because of the MACRO expansion on HWREG. Please see below HWREG definition.

    #define HWREG(x) \
    (*((volatile uint32_t *)(x)))

    The PWM0_1_GENA_R is defined as below in tm4c1294ncpdt.h file. 

    #define PWM0_1_GENA_R           (*((volatile uint32_t *)0x400280A0))

    When you substitute PWM0_1_GENA_R for x, the MACRO expands to 

    (*((volatile uint32_t *)((*((volatile uint32_t *)0x400280A0))))) and this is wrong. 

  • Hi Howard,

      I think the correct way is below:

    #include #include "inc/hw_pwm.h"

    HWREG(PWM0_BASE + PWM_O_1_GENA) = 0x8C0; // this is correct.

    Below will also work:

    #include "inc/tm4c1294ncpdt.h"

    PWM0_1_GENA_R = 0x8C0; // this is ok.

    Below is wrong:

    #include "inc/tm4c1294ncpdt.h"

    HWREG(PWM0_1_GENA_R) = 0x8C0; // this is wrong.

  • Hi Charles,

    Thanks for your instruction. Now it's working.