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.

CCS/TM4C1290NCPDT: Multiple timers issue

Part Number: TM4C1290NCPDT


Tool/software: Code Composer Studio

Hi, I was using 4 timers to generate 4  square signals at diferent frequencies (8 9 10 and 11 KHz) from PC4 PC5 PC6 PC7 pins, every thing was ok, so I tried to use more timers to generate more square signals from other pins PH0 PH1 PH2 PH3 (8.5 9.5 10.5 and 11.5 KHz), so I tried to use the subtimers, here is the code:

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"+
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"

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

uint32_t g_ui32SysClock;            // System clock rate in Hz.
uint32_t g_ui32FlagsN;              // Flags that contain the current value of the interrupt indicator as displayed on the UART.
uint32_t g_ui32FlagsF;              // Flags that contain the current value of the interrupt indicator as displayed on the UART.
uint32_t g_ui32FlagsP;              // Flags that contain the current value of the interrupt indicator as displayed on the UART.
uint32_t g_ui32FlagsB;              // Flags that contain the current value of the interrupt indicator as displayed on the UART.
uint32_t g_ui32FlagsC;              // Flags that contain the current value of the interrupt indicator as displayed on the UART.
uint32_t g_ui32FlagsH;              // Flags that contain the current value of the interrupt indicator as displayed on the UART.

uint32_t leBandera = 0;
//*****************************************************************************
void Timer0IntHandler(void)                                         // The interrupt handler for the first timer interrupt.
{
    ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);             // Clear the timer interrupt.
    HWREGBITW(&g_ui32FlagsN, 0) ^= 1;                               // Toggle the flag for the first timer.
    HWREGBITW(&g_ui32FlagsC, 4) ^= 1;                               // Toggle the flag for the first timer.
    GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, g_ui32FlagsN);        // Use the flags to Toggle the LED for this timer
    GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_4, g_ui32FlagsC);        // Use the flags to Toggle the LED for this timer

}

//*****************************************************************************
void Timer1IntHandler(void)                                         // The interrupt handler for the second timer interrupt.
{
    ROM_TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);             // Clear the timer interrupt.
    HWREGBITW(&g_ui32FlagsN, 1) ^= 1;                               // Toggle the flag for the second timer.
    HWREGBITW(&g_ui32FlagsC, 5) ^= 1;                               // Toggle the flag for the first timer.

    GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, g_ui32FlagsN);        // Use the flags to Toggle the LED for this timer
    GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_5, g_ui32FlagsC);        // Use the flags to Toggle the LED for this timer

}
//*****************************************************************************
void Timer2IntHandler(void)                                         // The interrupt handler for the second timer interrupt.
{
    ROM_TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT);             // Clear the timer interrupt.
    HWREGBITW(&g_ui32FlagsF, 4) ^= 1;                               // Toggle the flag for the second timer.
    HWREGBITW(&g_ui32FlagsC, 6) ^= 1;                               // Toggle the flag for the first timer.

    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, g_ui32FlagsF);        // Use the flags to Toggle the LED for this timer
    GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_6, g_ui32FlagsC);        // Use the flags to Toggle the LED for this timer

}
//*****************************************************************************
void Timer3IntHandler(void)                                         // The interrupt handler for the second timer interrupt.
{
    ROM_TimerIntClear(TIMER3_BASE, TIMER_TIMA_TIMEOUT);             // Clear the timer interrupt.
    HWREGBITW(&g_ui32FlagsF, 0) ^= 1;                               // Toggle the flag for the second timer.
    HWREGBITW(&g_ui32FlagsC, 7) ^= 1;                               // Toggle the flag for the first timer.

    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, g_ui32FlagsF);        // Use the flags to Toggle the LED for this timer
    GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_7, g_ui32FlagsC);        // Use the flags to Toggle the LED for this timer

}
//*****************************************************************************
//*****************************************************************************
void Timer0IntHandlerB(void)                                         // The interrupt handler for the first timer interrupt.
{
    ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMB_TIMEOUT);             // Clear the timer interrupt.
    HWREGBITW(&g_ui32FlagsH, 0) ^= 1;                               // Toggle the flag for the first timer.
    GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_0, g_ui32FlagsH);        // Use the flags to Toggle the LED for this timer

}

//*****************************************************************************
void Timer1IntHandlerB(void)                                         // The interrupt handler for the second timer interrupt.
{
    ROM_TimerIntClear(TIMER1_BASE, TIMER_TIMB_TIMEOUT);             // Clear the timer interrupt.
    HWREGBITW(&g_ui32FlagsH, 1) ^= 1;                               // Toggle the flag for the first timer.
    GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_1, g_ui32FlagsH);        // Use the flags to Toggle the LED for this timer

}
//*****************************************************************************
void Timer2IntHandlerB(void)                                         // The interrupt handler for the second timer interrupt.
{
    ROM_TimerIntClear(TIMER2_BASE, TIMER_TIMB_TIMEOUT);             // Clear the timer interrupt.
    HWREGBITW(&g_ui32FlagsH, 2) ^= 1;                               // Toggle the flag for the first timer.
    GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_2, g_ui32FlagsH);        // Use the flags to Toggle the LED for this timer

}
//*****************************************************************************
void Timer3IntHandlerB(void)                                         // The interrupt handler for the second timer interrupt.
{
    ROM_TimerIntClear(TIMER3_BASE, TIMER_TIMB_TIMEOUT);             // Clear the timer interrupt.
    HWREGBITW(&g_ui32FlagsH, 3) ^= 1;                               // Toggle the flag for the first timer.
    GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_3, g_ui32FlagsH);        // Use the flags to Toggle the LED for this timer

}
//*****************************************************************************
//*****************************************************************************
// This example application demonstrates the use of the timers to generate
// periodic interrupts.
//*****************************************************************************
int main(void)
{
    g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |            // Set the clocking to run directly from the crystal at 120MHz.
                                             SYSCTL_OSC_MAIN |
                                             SYSCTL_USE_PLL |
                                             SYSCTL_CFG_VCO_480), 120000000);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);                        // Enable the GPIO port that is used for the on-board LEDs.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);                        // Enable the GPIO port that is used for the on-board LEDs.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);                        // Enable the GPIO port that is used for the on-board LEDs.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);                        // Enable the GPIO port that is used for the on-board LEDs.


    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1);     // Enable the GPIO pins for the LEDs (PN0 & PN1).
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);// Enable the GPIO pin for the LED (PF4).
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);


    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);                       // Enable the peripherals used by this example.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);
//    ROM_IntMasterEnable();                                                  // Enable processor interrupts.

    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);                        // Configure the two 32-bit periodic timers.
    TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);
    TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC);
    TimerConfigure(TIMER3_BASE, TIMER_CFG_PERIODIC);


    ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, 2*(g_ui32SysClock/8000));
    ROM_TimerLoadSet(TIMER1_BASE, TIMER_A, 2*(g_ui32SysClock/9000));
    ROM_TimerLoadSet(TIMER2_BASE, TIMER_A, 2*(g_ui32SysClock/10000));
    ROM_TimerLoadSet(TIMER3_BASE, TIMER_A, 2*(g_ui32SysClock/11000));

    ROM_TimerLoadSet(TIMER0_BASE, TIMER_B, 2*(g_ui32SysClock/8500));
    ROM_TimerLoadSet(TIMER1_BASE, TIMER_B, 2*(g_ui32SysClock/9500));
    ROM_TimerLoadSet(TIMER2_BASE, TIMER_B, 2*(g_ui32SysClock/10500));
    ROM_TimerLoadSet(TIMER3_BASE, TIMER_B, 2*(g_ui32SysClock/11500));


    ROM_IntEnable(INT_TIMER0A);                                             // Setup the interrupts for the timer timeouts.
    ROM_IntEnable(INT_TIMER1A);
    ROM_IntEnable(INT_TIMER2A);
    ROM_IntEnable(INT_TIMER3A);

    ROM_IntEnable(INT_TIMER0B);
    ROM_IntEnable(INT_TIMER1B);
    ROM_IntEnable(INT_TIMER2B);
    ROM_IntEnable(INT_TIMER3B);


    ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    ROM_TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
    ROM_TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
    ROM_TimerIntEnable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);

    ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMB_TIMEOUT);
    ROM_TimerIntEnable(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
    ROM_TimerIntEnable(TIMER2_BASE, TIMER_TIMB_TIMEOUT);
    ROM_TimerIntEnable(TIMER3_BASE, TIMER_TIMB_TIMEOUT);



    ROM_TimerEnable(TIMER0_BASE, TIMER_A);                                  // Enable the timers.
    ROM_TimerEnable(TIMER1_BASE, TIMER_A);
    ROM_TimerEnable(TIMER2_BASE, TIMER_A);
    ROM_TimerEnable(TIMER3_BASE, TIMER_A);

    ROM_TimerEnable(TIMER0_BASE, TIMER_B);
    ROM_TimerEnable(TIMER1_BASE, TIMER_B);
    ROM_TimerEnable(TIMER2_BASE, TIMER_B);
    ROM_TimerEnable(TIMER3_BASE, TIMER_B);

    IntMasterEnable();

    while(1)
    {
        // Loop forever while the timers run.
    }
}

When I run this code the output of pins PC4 PC5 PC6 and PC7 are reduced in frequency (to 2000 KHz aprox ), and using the debuger I see that the interrupts of Timer0IntHandlerB, Timer1IntHandlerB, Timer2IntHandlerB, Timer3IntHandlerB never happen, I do not know why this is not working, my objetive is to generate 8 square signals at diferent frequencies... what migth be the problem??,
The start up file was updated to support the interruptions of the 8 timers.

  • Hello Sergio

    When using the Sub timers you need to configure the Timers with the parameter TIMER_CFG_SPLIT_PAIR

    Please see the example

    D:\ti\TivaWare_C_Series-2.1.3.156\examples\peripherals\timer\periodic_16bit.c
  • That works, thanks AMit
  • Hello Sergio and readers,

    Further to Amit's spot on reply:

    I have seen this doubt before. It is important to understand that each of the timers (as in Timer0, Timer1...) is controlled by a block of registers. The "sub timers" - as in TimerA and TimerB - reside inside the same register group. The Tivaware Timer API functions access the registers using the parameters passed, and for most of them, if you "accidently" call a configuration for TimerB after you did it for TimerA, you are actually overriding the first call.

    In other words, you would disconfigure TimerA when you later set your TimerB. That is what the TIMER_CFG_SPLIT_PAIR is about. To fully understand it, one can open the timers.c file and see what the Tivaware actually does there, and compare to the registers documentation on the datasheet.

    By the way, there is no right or wrong - but you can also use PWM to generate your square signals - and they are actually more convenient for that.

    Regards

    Bruno