EK-LM3S9B90 pwm generation with Timer 1

I am trying to generate a pair of pwms with the EK-LM3S9B90 using a timer (Timer 1 specifically). The following code is used to setup the timer to yield two 10 kHz 50% duty cycle signals and output to pins PC4 and PC 5. When only one signal is generated, I get a neat 10 kHz 50% duty cycle signal. While trying to generate two signals one of the signals is unstable (looks like it is driven high with a pwm signal superimposed) and the other does not show any signal whatever. Sometimes, though the one pin shows a clean signal while the other continues to show a pwm superimposed on a "high" output. I tried using separate ports (Port E and Port C) to output the signal but faced the same problem. Would adding a few delay cycles help when initializing pins? The code is being compiled with CCS v4.

Once initialized the code runs an infinite loop and is periodically interrupted at intervals of 1 second to update the LED and UART.

 

 

void Init(void)

{

//

    // Set the clocking to run directly from the crystal to 80MHz.

    //

    ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |

                       SYSCTL_XTAL_16MHZ);

 

    //

    // Initialize the UART.

    //

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    GPIOPinConfigure(GPIO_PA0_U0RX);

    GPIOPinConfigure(GPIO_PA1_U0TX);

    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    UARTStdioInit(0);

 

    //

    // Initialize LED (Port D Pin 0)

    //

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0);

 

 

    //

    //Initialize Timer0

    //

    //

    // Enable the peripherals used by this example.

    //

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    //ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);

    //

    // Enable processor interrupts.

    //

    ROM_IntMasterEnable();

 

    //

    // Configure the Timer0 for 32 bit timer operation, Timer1 for 10kHz 50% duty cycle PWM signals.

    //

    ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER);

    ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_16_BIT_PAIR | TIMER_CFG_A_PWM);

    ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_16_BIT_PAIR | TIMER_CFG_B_PWM);

    ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, ROM_SysCtlClockGet());

    ROM_TimerLoadSet(TIMER1_BASE, TIMER_A, 8000);

    ROM_TimerLoadSet(TIMER1_BASE, TIMER_B, 8000);

    ROM_TimerMatchSet(TIMER1_BASE, TIMER_A, 4000);

    ROM_TimerMatchSet(TIMER1_BASE, TIMER_B, 4000);

    //ROM_TimerControlLevel(TIMER1_BASE, TIMER_A, true);

    //ROM_TimerControlLevel(TIMER1_BASE, TIMER_B, false);

 

 

    ROM_GPIOPinConfigure(GPIO_PC4_CCP2);

    ROM_GPIOPinTypeTimer(GPIO_PORTC_BASE,GPIO_PIN_4);

    ROM_GPIOPinConfigure(GPIO_PC5_CCP3);

    ROM_GPIOPinTypeTimer(GPIO_PORTC_BASE,GPIO_PIN_5);

 

    //

    // Setup the interrupts for the timer timeouts.

    //

    ROM_IntEnable(INT_TIMER0A);

    ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

 

    // 

    // Setup the interrupt for pushbutton press (pull down)

    //

    ROM_GPIODirModeSet(GPIO_PORTB_BASE, GPIO_PIN_4, GPIO_DIR_MODE_HW);

    ROM_GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

 

    //

    // Setup the interrupt for pushbutton press.

    //

    ROM_GPIOIntTypeSet(GPIO_PORTB_BASE, GPIO_PIN_4, GPIO_LOW_LEVEL);

    ROM_IntEnable(INT_GPIOB);

 

    //

    // Set interrupt priorities

    //

    ROM_IntPrioritySet(INT_GPIOB, 0x00);

    ROM_IntPrioritySet(INT_TIMER0A, 0x00);

 

 

 

    //

    // Enable the timers.

    //

    ROM_TimerEnable(TIMER0_BASE, TIMER_A);

    ROM_TimerEnable(TIMER1_BASE, TIMER_A);

    ROM_TimerEnable(TIMER1_BASE, TIMER_B);

 

    g_uscount = 0;

    UARTprintf("\rcount = %d", g_uscount);

}

 

//*****************************************************************************

//

// The interrupt handler for the TIMER0 interrupt.

//

//*****************************************************************************

void

Timer0IntHandler(void)

{

    //

    // Clear the timer interrupt.

    //

    ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

 

    //

    // Toggle the flag for the first timer.

    //

    HWREGBITW(&g_ulFlags, 0) ^= 1;

 

    //

    // Update the interrupt status on the display.

    //

    ROM_IntMasterDisable();

    if(++g_uscount > 9)

    {

    g_uscount = 0;

    }

    UARTprintf("\rcount = %d", g_uscount);

 

    ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, ~ROM_GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_0)); //Flip LED each second 

    ROM_IntMasterEnable();

}

 

  • Hi,

    I have duplicated your issue.  In the process of debugging it, the issue is the GPIOAFSEL and GPIOPCTL registers are being incorrectly written.  The way you code is written, it should work.  I am looking into why the API is not setting it correctly.  The order of them in you code shouldn't cause an issue, as the write should be ORed in.  I will continue working on this and send a update and recommendation. 

    Lela

  • In reply to Lela Garofolo:

    I finally got it working...Te issue with the GPIOAFSEL and GPIOPCTL registers, came from another API overwriting it them that I had inserted in the debugging process.  The issue is the API ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_16_BIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PWM);  You have it twice, once for A_PWM and the second for B_PWM.  Evidently...you have OR the TIMER_CFG_A_PWM | TIMER_CFG_B_PWM in the same TimerConfigure API or the 2nd write will write over the first one.  Again, I would have thought it wouldn't matter...but in stepping through the code, and the driverlib code I found that the A and B pair need to be done in the same API call.

    I took everything out of your code that did not pertain to the issue...the working code for PC4 and PC5 is:

     ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
      
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
     GPIOPinConfigure(GPIO_PA0_U0RX);
     GPIOPinConfigure(GPIO_PA1_U0TX);
     ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
     UARTStdioInit(0);
     
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
     ROM_IntMasterEnable();

        ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_16_BIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PWM);
    // ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_16_BIT_PAIR | TIMER_CFG_A_PWM);
    //    ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_16_BIT_PAIR | TIMER_CFG_B_PWM);
       
        ROM_TimerLoadSet(TIMER1_BASE, TIMER_A, 8000);
        ROM_TimerLoadSet(TIMER1_BASE, TIMER_B, 8000);
        ROM_TimerMatchSet(TIMER1_BASE, TIMER_A, 4000);
        ROM_TimerMatchSet(TIMER1_BASE, TIMER_B, 4000);

        GPIOPinConfigure(GPIO_PC4_CCP2);
        GPIOPinTypeTimer(GPIO_PORTC_BASE,GPIO_PIN_4);
        GPIOPinConfigure(GPIO_PC5_CCP3);
        GPIOPinTypeTimer(GPIO_PORTC_BASE,GPIO_PIN_5);


        ROM_TimerEnable(TIMER1_BASE, TIMER_A);


        ROM_TimerEnable(TIMER1_BASE, TIMER_B);
       
     while (1)
     {}   

    Please let me know if you have any other issues.

    Lela

  • In reply to Lela Garofolo:

    Thanks for that. Couple of questions:

    - When debugging how did you watch the values of the registers? I included the lm3s9b90.h and tried to add the appropriate register to the watch window, but it wont recognize the register. Even adding watch variables didnt cut it. How did you do it? 

    -Can I invert one of Timer 1A and Timer1b and not the other? I tried using ROM_TimerControlLevel(TIMER1_BASE, TIMER_A, true) and then TIMER1_CTL_R |= (1 <<6); to do it but either of them wasnt successful. What am I doing wrong?

  • In reply to newtothis:

    Well I figured out the register bit (view drop down menu !). Sorry about that, but still cant get the active low/high combination working.

  • In reply to newtothis:

    Yes, you can invert Timer 1A and not Timer1B...All you need to do is ROM_TimerControlLevel(TIMER1_BASE, TIMER_A, true).   I inserted it into the code that I pased above, and it worked for me.

    Let me know if you continue to have an issue.

    Lela

  • In reply to Lela Garofolo:

    Hi Lela,

    I am facing a similar problem trying to implement the a PWM from timer0 on portF on part LM4F120H5QR used in the stellaris launchpad EK-LM4F120XL. I have been searching the posts and forum for somebody to find out what am I doing wrong but no luck yet. I had a version of this code perform PWM through interrupts where state of LED changed at match and at timeout, but I should have to use interrupts and I want to get a free running PWM multiplexed to a GPIO directly (PF1 in this case)

    data sheet for LM4F120H5QR mentions that I can configure PF1 to be T0CCP1 and redirect the PWM output from timer0B to that pin, that pin is connected to an LED that would help me see the PWM in action since I dont have a scope handy. below is my code and the loop runs but nothing is happening on the LED, I am suspecting something in the configuration of the pins is not in order. please see my code snippet.

    //#define PART_LM4F120H5QR
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_gpio.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/gpio.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/timer.h"
    #include "driverlib/pin_map.h"

    int main (void)

    {

    unsigned long ulPeriod;

    SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2|GPIO_PIN_3);
    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2|GPIO_PIN_3,0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    GPIOPinConfigure(GPIO_PF1_T0CCP1);
    GPIOPinTypeTimer(GPIO_PORTF_BASE,GPIO_PIN_1);
    TimerConfigure(TIMER0_BASE, TIMER_CFG_B_PERIODIC|TIMER_CFG_B_PWM);

    ulPeriod = SysCtlClockGet() / 40;
    TimerLoadSet(TIMER0_BASE, TIMER_B, ulPeriod-1);
    TimerMatchSet(TIMER0_BASE,TIMER_B, ulPeriod-30000);

    TimerEnable(TIMER0_BASE, TIMER_A);

    while(1)
    {


    }
    }

    any hints on what am I doing wrong would be appreciated. 

  • In reply to Bakr Younis:

    Bakr,

    Apologies for the delayed response...

    You code had a couple issues, PF2 and PF3 are on Timer 1, had Timer 0 in your code.  TIMER_CFG_PERIODIC sets ulConfig for a Full-width periodic timer.  For PWM mode on timer A and B, you want to set it for two half-width timers using parameter, TIMER_CFG_SPLIT_PAIR.    Then the value based on ulPeriod and system clock is greater than 16 bits for both ulValue writes to API's TimerLoadSet and TimerMatchSet.  It will still do the write, but will only write 16-bits.  Bits 24:16 need to be handled by writing to the prescale registers.

    Your code working...

     SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

     SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); 
     SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
     
     GPIOPinConfigure(GPIO_PF2_T1CCP0);
     GPIOPinConfigure(GPIO_PF3_T1CCP1);

     GPIOPinTypeTimer(GPIO_PORTF_BASE,GPIO_PIN_2 | GPIO_PIN_3);
     
     TimerConfigure(TIMER1_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PWM);

    ulPeriod = SysCtlClockGet() / 40;
    TimerLoadSet(TIMER1_BASE,TIMER_A, ulPeriod-1);
    TimerPrescaleSet(TIMER1_BASE,TIMER_A,0xF);
    TimerLoadSet(TIMER1_BASE, TIMER_B, ulPeriod-1);
    TimerPrescaleSet(TIMER1_BASE,TIMER_B,0xF);
    TimerMatchSet(TIMER1_BASE,TIMER_A, ulPeriod-30000);
    TimerMatchSet(TIMER1_BASE,TIMER_B, ulPeriod-30000);
    TimerPrescaleMatchSet(TIMER1_BASE,TIMER_A,12);
    TimerPrescaleMatchSet(TIMER1_BASE,TIMER_B,12);


    TimerEnable(TIMER1_BASE, TIMER_A | TIMER_B);


    while(1)
    {}
    }

  • In reply to Lela Garofolo:

    no worries, 

    I know you guys are helping people all the time with more complicated issues, I did find the solution on another thread after digging into the rgb.c shipped with stellarisware for the EK-LM4F120XL board. The split pair is what got me and obviously the way I was handling the 16 bits matchset was also problematic for accurate timing but know its more clear and I thank you for that. I noticed that when I was debugging that only the 16 bit mattered and I should have scaled accordingly. I never used the prescalares before but ill read up on them and I again thank you for your dedication and most valued help.

    Bakr

  • In reply to Lela Garofolo:

    Hello Lela,

    I have the similar issue on my stellaris launchpad. After whole day coding with no effect I start googling and found this thread.

    I just copy and paste your code above and only BLUE LED blinking by PWM. If I change last line to

    TimerEnable(TIMER1_BASE, TIMER_B);

    I can see GREEN LED blinking, but can't make them blinking together..

    Please help to investigate.

    Regards,

    Roman

  • In reply to roman kovalev:

    Hello,

    My apologizes for post above. Your example works correctly, it's too late, I did'nt see green LED...

    thanks.

    Roman