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.

ASYNC two software timers on different hardware timers?

Hello everyone,

I wrote a little code for my MSP432 to use two software timers on two separate hardware timers.

The first hardware timer runs on SMCLK 3Mhz/64 and counts to 46875 before the interrupt. That is 1 second. And on that timer runs a software timer that counts 2 seconds, and then it triggers a red LED.

The second hardware timer runs on SMCLK 3Mhz and counts to 3000 before the interrupt. That is 1 m second. And on that timer runs a software timer that counts 500 m seconds, and then it triggers a blue LED.

So after i run the program the blue and red LED should both turn off after 4 seconds. But after a few minutes the 2 LEDS get async and i dont know why.

Does someone have an explanation?

I think its because no 2 hardware timers can be in sync.

  • I forgot to add the code 

    //*****************************************************************************
    //
    // MSP432 main.c template - Empty main
    //
    //****************************************************************************
    
    /* Ukljucenja */
    #include "msp.h"
    #include "driverlib.h"
    
    /* Definicije */
    #define ZASTAVA_GORE		1
    #define ZASTAVA_DOLE		0
    
    #define DEAKTIVIRAN			0
    #define TAJMER1s			1
    #define	TAJMER1ms			2
    
    #define MAX_BROJ_TAMJMERA	8
    #define TIMER_PERIOD_1s		46875				// 3MHz/64
    #define TIMER_PERIOD_1ms	3000				// 3MHz/1000
    
    /* Definicije tipova */
    typedef struct softTajmer_s{
    	uint8_t		aktiviran;
    	uint8_t		zastava;
    	uint16_t	brojac;
    	uint16_t	broj;
    } softTajmer;
    
    /* Prototipovi */
    void AktivirajSoftTajmer(uint8_t redniBroj, uint16_t broj, uint8_t tajmer);
    void DektivirajSoftTajmer(uint8_t redniBroj);
    void ResetujSoftTajmer(uint8_t redniBroj);
    
    
    const Timer_A_UpModeConfig upConfig1s =
    {
            TIMER_A_CLOCKSOURCE_SMCLK,				// SMCLK Clock Source
            TIMER_A_CLOCKSOURCE_DIVIDER_64,			// SMCLK/1 = 3MHz
            TIMER_PERIOD_1s,
            TIMER_A_TAIE_INTERRUPT_DISABLE,			// Disable Timer interrupt
            TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE,		// Enable CCR0 interrupt
            TIMER_A_DO_CLEAR						// Clear value
    };
    
    const Timer_A_UpModeConfig upConfig1ms =
    {
            TIMER_A_CLOCKSOURCE_SMCLK,				// SMCLK Clock Source
            TIMER_A_CLOCKSOURCE_DIVIDER_1,			// SMCLK/1 = 3MHz
            TIMER_PERIOD_1ms,
            TIMER_A_TAIE_INTERRUPT_DISABLE,			// Disable Timer interrupt
            TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE,		// Enable CCR0 interrupt
            TIMER_A_DO_CLEAR						// Clear value
    };
    
    softTajmer	tajmeri[MAX_BROJ_TAMJMERA];
    uint8_t		brojPrekida;
    
    #define BROJAC1 1
    #define BROJAC2	500
    
    uint16_t	brojac1;
    uint16_t	brojac2;
    
    void main(void)
    {
    	/* Stop WDT  */
    	MAP_WDT_A_holdTimer();
    
    	/* Konfigurisi P1.0 kao izlaz */
    	MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
    	MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
    	/* Konfigurisi P2.2 kao izlaz */
    	MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2);
    	MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN2);
    
    	MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P4,
    	            GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
    
    	/* Podesi tajmere da rade u UpMode */
    	MAP_Timer_A_configureUpMode(TIMER_A0_BASE, &upConfig1s);
    	MAP_Timer_A_configureUpMode(TIMER_A1_BASE, &upConfig1ms);
    
    	/* Odobri prekide */
    	MAP_Interrupt_enableSleepOnIsrExit();
    	MAP_Interrupt_enableInterrupt(INT_TA0_0);
    	MAP_Interrupt_enableInterrupt(INT_TA1_0);
    
    	/* Aktiviraj odredjene sofverske tajmere */
    	AktivirajSoftTajmer(0, 2, TAJMER1s);			// Radice po tajmeru za 1s
    	AktivirajSoftTajmer(1, 500, TAJMER1ms);			// Radice po tajmeru za 1ms
    
    	/* Pokreni tajmer */
    	MAP_Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UP_MODE);
    	MAP_Timer_A_startCounter(TIMER_A1_BASE, TIMER_A_UP_MODE);
    
    	brojac1 = BROJAC1;
    	brojac2 = BROJAC2;
    
    	/* Odobri GLAVNI prekid */
    	MAP_Interrupt_enableMaster();
    
    	/* Spavaj kada se ne koristi */
    	while (1)
    	{
    		MAP_PCM_gotoLPM0();
    	}
    }
    
    void AktivirajSoftTajmer(uint8_t redniBroj, uint16_t broj, uint8_t tajmer)
    {
    	tajmeri[redniBroj].aktiviran = tajmer;
    	tajmeri[redniBroj].zastava = ZASTAVA_DOLE;
    	tajmeri[redniBroj].brojac = broj;
    	tajmeri[redniBroj].broj = broj;
    }
    
    void DektivirajSoftTajmer(uint8_t redniBroj)
    {
    	tajmeri[redniBroj].aktiviran = DEAKTIVIRAN;
    }
    
    void ResetujSoftTajmer(uint8_t redniBroj)
    {
    	tajmeri[redniBroj].brojac = tajmeri[redniBroj].broj;
    }
    
    void TA0_0_1s_RukovaocPrekida(void)
    {
    	/*int i;
    	MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A0_BASE,
    					TIMER_A_CAPTURECOMPARE_REGISTER_0);
    	for(i=0; i<MAX_BROJ_TAMJMERA; i++)
    	{
    		if(tajmeri[i].aktiviran == TAJMER1s)
    		{
    			tajmeri[i].brojac--;
    			if(tajmeri[i].brojac == 0)
    			{
    				tajmeri[i].zastava = ZASTAVA_GORE;
    				brojPrekida++;
    				ResetujSoftTajmer(i);
    				MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
    				//izadji iz LP
    			}
    		}
    	}*/
    	MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A0_BASE,
    						TIMER_A_CAPTURECOMPARE_REGISTER_0);
    	brojac1--;
    	if(brojac1 == 0)
    	{
    		MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
    		brojac1 = BROJAC1;
    	}
    }
    
    extern void TA1_0_1ms_RukovaocPrekida(void)
    {
    	/*int i;
    	MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE,
    					TIMER_A_CAPTURECOMPARE_REGISTER_0);
    	for(i=0; i<MAX_BROJ_TAMJMERA; i++)
    	{
    		if(tajmeri[i].aktiviran == TAJMER1ms)
    		{
    			tajmeri[i].brojac--;
    			if(tajmeri[i].brojac == 0)
    			{
    				tajmeri[i].zastava = ZASTAVA_GORE;
    				brojPrekida++;
    				ResetujSoftTajmer(i);
    				MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN2);
    				//izadji iz LP
    			}
    		}
    	}*/
    	MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE,
    						TIMER_A_CAPTURECOMPARE_REGISTER_0);
    	brojac2--;
    	if(brojac2 == 0)
    	{
    		MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN2);
    		brojac2 = BROJAC2;
    	}
    }
    

  • You need to subtract 1 from TIMER_PERIOD_[1s,1ms] so the timer counts properly.

    As it is, each is off by 1 tick, but since the "1ms" timer cycles more often, it drifts faster than the "1s" timer.
  • I thought that was the error but it cant be. It first decrements, and then I check if it equals zero. That is the software timer, aha. You mean for the hardware timers... I will check it now. Thanks

**Attention** This is a public forum