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-TM4C123GXL: Can't configure PWM

Part Number: EK-TM4C123GXL
Other Parts Discussed in Thread: TM4C123GH6PM

I'm trying to configure the PWM module without the TExaS API for academic purposes, but I'm unable to make it work. I have followed examples found on the internet and even looked at the TExaS API source code but I don't find where my code is wrong.

Specifically, I'm trying to configure PWM1, Generator 2, therefore pins: PE4, PE5 (pwm2A, pwm2B) and PD6 (pwm2fault). To avoid providing a too large code snippet, I will only describe the configuration I have for the system clock and GPIOs assuming that it is correct, since I have tested it in the past and no problems have arisen.

I configure the system clock to be provided the PLL at 20MHz (after all the divisions etc.), so this frequency matches the guide provided by the  Tiva™ TM4C123GH6PM Microcontroller datasheet, 20.4 Initialization and configuration.

I configure pins PE4 and PE5 as digital outputs, 2mA current drive, pull-down resistor, alternate function enabled. Also, assign to them the PWM function by writing a '4' in `GPIOPCTL`, in both PMC4 and PMC5.

Once the above is done, the configuration I set for PWM is the following:

typedef volatile uint32_t* const Register32_t;

const uint32_t PWM0_BASE = 0x40028000;

const uint32_t PWMENABLE_OFFSET = 0x08;
const uint32_t PWM2CTL_OFFSET = 0x0C0;
const uint32_t PWM2LOAD_OFFSET = 0x0D0;
const uint32_t PWM2CMPA_OFFSET = 0x0D8;
const uint32_t PWM2CMPB_OFFSET = 0x0DC;
const uint32_t PWM2GENA_OFFSET = 0x0E0;
const uint32_t PWM2GENB_OFFSET = 0x0E4;

static void config_PWM_clock_divisor(void)
{
  Register32_t RCC_REG = (Register32_t)(0x400FE000 + 0x060);

  // Enable the PWM clock divisor
  *RCC_REG |= (1 << 20);

  // Set the clock divider as /2 --> (0x000)
  *RCC_REG &= ~( 0x7 << 17 );
}

static void config_PWM_counter_period_and_comparators(void)
{
  Register32_t PWM2CTL_REG = (Register32_t)(PWM0_BASE + PWM2LOAD_OFFSET);
  *PWM2CTL_REG = 0x18F;

  Register32_t PWM2CMPA_REG = (Register32_t)(PWM0_BASE + PWM2CMPA_OFFSET);
  *PWM2CMPA_REG = 0x12B;

  Register32_t PWM2CMPB_REG = (Register32_t)(PWM0_BASE + PWM2CMPB_OFFSET);
  *PWM2CMPB_REG = 0x63;
}

void PWM_init(void)
{
  Register32_t RCGC0 = (Register32_t)(0x400FE000 + 0x100);

  // Enable PWM0 clock
  *RCGC0 |= 0x00100000;
  
  // This performs the GPIO configuration explained above
  init_PWM_GPIO();

  config_PWM_clock_divisor();

  Register32_t PWM2CTL_REG = (Register32_t)(PWM0_BASE + PWM2CTL_OFFSET);
  Register32_t PWM2GENA_REG = (Register32_t)(PWM0_BASE + PWM2GENA_OFFSET);
  Register32_t PWM2GENB_REG = (Register32_t)(PWM0_BASE + PWM2GENB_OFFSET);

  *PWM2CTL_REG = 0x000;
  *PWM2GENA_REG = 0x08C;
  *PWM2GENB_REG = 0x80C;

  config_PWM_counter_period_and_comparators();

  //
  // Start the timers
  //
  *PWM2CTL_REG = 1;

  //
  // Enable PWM outputs
  //
  Register32_t PWMENABLE_REG = (Register32_t)(PWM0_BASE + PWMENABLE_OFFSET);
  *PWMENABLE_REG = (3 << 2);
}

As it can be seen, I follow the steps in user manual section 20.4 exactly as they are, since my system clock matches the 20MHz used as example in the above section.

After doing all of this, I build, flash, reset and place my oscilloscope probes in PE4 and PE5 but I see nothing (always 0V). Using the UART, I have been able to double check that the value of the register PWM2COUNT is a count-down starting at 400, which is the expected. Once it reaches 0, it starts again. So this part is working.

What am I missing?

 

  • HI,

      I'm not 100%  sure what is wrong but the below few lines look suspicious. 

    In line 26 and 27 you wrote as follows. What are you trying to do here? You use PWM2LOAD_OFFSET while trying to write to PWM2CTL_REG. Are you trying to write to the PWM2LOAD register or the PWM2CTL register? It is confusing.

      Register32_t PWM2CTL_REG = (Register32_t)(PWM0_BASE + PWM2LOAD_OFFSET);
      *PWM2CTL_REG = 0x18F;
    In line 61 you wrote as follows. When you write a '1' it means that you only write to bit 0 of the PWM2CTL register but clearing all the rest of the bits in the register. You should be doing a *PWM2CTL_REG |= 1 instead, isn't?
        *PWM2CTL_REG = 1;
    Please read FAQ #4 in https://e2e.ti.com/support/microcontrollers/other/f/908/t/695568. We do not support DRM style of coding. It is prone to mistake. If you insist to use DRM then I will suggest you first create your application using the TivaWare to run it. Next, use the debugger to view the register content of the PWM2 generator and compare with your DRM code. This way you can compare which register is not configured correctly.