Hello,
I have a question regarding the Enhanced capture timer. I am using the ECT as interrupt timer. I set the TC1 to fire the interrupt at a specific compare output. The sequence of the instruction is as below:
ECT_TCNT = 0;
asm BSET ECT_TSCR1, #0x80 //timer started
ECT_TC1 = ECT_TCNT + 6400;
asm BSET ECT_TIE, #0x02 //interrupt enable
Presumably the interrupt will fire when the timer counted from 0 to 6400. What I noticed is that the first interrupt was triggered right away, which is not what I expected. Thereafter the interrupt triggered at regular interval, which is what I expected.
If I change the ECT_TCNT's initial value, for example,
ECT_TCNT = 10000; //---------changed this initial value
asm BSET ECT_TSCR1, #0x80 //timer started
ECT_TC1 = ECT_TCNT + 6400;
asm BSET ECT_TIE, #0x02 //interrupt enable
Then everything works fine. The first interrupt was not triggered right away.
Can anybody explain to me why the initial value of ECT_TCNT makes the difference? I think I read about this in the manual somewhere, but I cannot find it anymore.
Yours sincerely,
Huck
Solved! Go to Solution.
Hi,
or another approach, just do not start timer before you add a first value into the OC register.
For example, see bellow. However, as Edward says and I can confirm it is good approach if you clear interrupt flags before interrupt is enabled to avoid servicing accidental flag.
******************************************************************************
Description: SW-XET256-ECT-OC-CW47
Documentation: MC9S12XEP100RMV1.pdf
This software is classified as Engineering Sample Software.
******************************************************************************
- the board includes 16MHz crystal / the MCU's bus frequency 8MHz is used
- the sample software does:
. TC0 interrupt is set to be generated with constant period.
==============================================================================*/
//******************************************************************************
#include <hidef.h>
#include <MC9S12XET256.h>
#pragma LINK_INFO DERIVATIVE "mc9s12xet256"
//******************************************************************************
//==============================================================================
// SETUP DEFINITIONS
//==============================================================================
#define INTERVAL 50000
//==============================================================================
// COMMON DEFINITIONS
//==============================================================================
#define UBYTE unsigned char
#define UWORD unsigned int
//==============================================================================
// FUNCTION PROTOTYPES
//==============================================================================
void ECT_Init(void);
//==============================================================================
// Variables section
//==============================================================================
// NA
//==============================================================================
// CODE section
//==============================================================================
void ECT_Init(void)
{
ECT_TSCR2 = 0x07; // TOV disable, no reset timer from T7, prescaller=128
//--- channel 0 setup ---------------
ECT_TCTL1 = 0x00; // timer 7~4 no output compare action
ECT_TCTL2 = 0x01; // timer 3~1 no output compare action, T0 toggle on compare
ECT_TIOS = 0x01; // channel 0 is output compare
ECT_OCPD = 0xFE; // enable OC at timer 0 port
//-----------------------------------
ECT_TC0 = (UWORD) (INTERVAL + ECT_TCNT); // base setup of the first OC at T0
//-----------------------------------
ECT_TIE = 0x01; // enable interrupt from channel 0
//---------------------------------
ECT_TSCR1 = 0xE0; // enable timer,stop in wait,stop in freeze, no fast flag clear, legacy timer
}
//******************************************************************************
#pragma CODE_SEG NON_BANKED
//-------------------------------------
interrupt 8 void TC0_Isr(void)
{
ECT_TC0 = INTERVAL + ECT_TCNT; // set new period end
ECT_TFLG1 = 0x01; // clear interrupt flag
}
//-------------------------------------
#pragma CODE_SEG DEFAULT
//******************************************************************************
// void main(void)
//******************************************************************************
void main(void)
{
//----------------------------------------
ECT_Init();
//----------------------------------------
EnableInterrupts;
//----------------------------------------
for(;;)
{
}
}
//******************************************************************************
Best regards,
Ladislav
Hi,
or another approach, just do not start timer before you add a first value into the OC register.
For example, see bellow. However, as Edward says and I can confirm it is good approach if you clear interrupt flags before interrupt is enabled to avoid servicing accidental flag.
******************************************************************************
Description: SW-XET256-ECT-OC-CW47
Documentation: MC9S12XEP100RMV1.pdf
This software is classified as Engineering Sample Software.
******************************************************************************
- the board includes 16MHz crystal / the MCU's bus frequency 8MHz is used
- the sample software does:
. TC0 interrupt is set to be generated with constant period.
==============================================================================*/
//******************************************************************************
#include <hidef.h>
#include <MC9S12XET256.h>
#pragma LINK_INFO DERIVATIVE "mc9s12xet256"
//******************************************************************************
//==============================================================================
// SETUP DEFINITIONS
//==============================================================================
#define INTERVAL 50000
//==============================================================================
// COMMON DEFINITIONS
//==============================================================================
#define UBYTE unsigned char
#define UWORD unsigned int
//==============================================================================
// FUNCTION PROTOTYPES
//==============================================================================
void ECT_Init(void);
//==============================================================================
// Variables section
//==============================================================================
// NA
//==============================================================================
// CODE section
//==============================================================================
void ECT_Init(void)
{
ECT_TSCR2 = 0x07; // TOV disable, no reset timer from T7, prescaller=128
//--- channel 0 setup ---------------
ECT_TCTL1 = 0x00; // timer 7~4 no output compare action
ECT_TCTL2 = 0x01; // timer 3~1 no output compare action, T0 toggle on compare
ECT_TIOS = 0x01; // channel 0 is output compare
ECT_OCPD = 0xFE; // enable OC at timer 0 port
//-----------------------------------
ECT_TC0 = (UWORD) (INTERVAL + ECT_TCNT); // base setup of the first OC at T0
//-----------------------------------
ECT_TIE = 0x01; // enable interrupt from channel 0
//---------------------------------
ECT_TSCR1 = 0xE0; // enable timer,stop in wait,stop in freeze, no fast flag clear, legacy timer
}
//******************************************************************************
#pragma CODE_SEG NON_BANKED
//-------------------------------------
interrupt 8 void TC0_Isr(void)
{
ECT_TC0 = INTERVAL + ECT_TCNT; // set new period end
ECT_TFLG1 = 0x01; // clear interrupt flag
}
//-------------------------------------
#pragma CODE_SEG DEFAULT
//******************************************************************************
// void main(void)
//******************************************************************************
void main(void)
{
//----------------------------------------
ECT_Init();
//----------------------------------------
EnableInterrupts;
//----------------------------------------
for(;;)
{
}
}
//******************************************************************************
Best regards,
Ladislav
Hello Ladislav,
thanks for the tips. I will switch my sequence to enable the timer after setting the OC register.
Yours sincerely,
Huck
TCNT is free running counter, which you can't alter in normal operating modes. In special operating modes write to TCNT resets TCNT to 0. (BDM debugger usually uses special single chip mode).
I think you need to clear TFLG1 flag before unmasking TIE interrupt:
TFLG1 = (1<<1); // clear n=1 channel interrupt flag, mask = 1<< n
TIE |= (1<<1); // unmask interrupt
Since it seems you are new to S12, please note that following would clear ALL TFLG1 flags, not just channel 1 flag:
TFLG1 |= (1<<1);
BSET TFLG1, #1<<1
Hello Edward,
thanks for the useful information. I will make sure I do not make the mistake when using the ECT.
I do clear the interrupt flag immediately in the ISR.
Do you have any information as far as why the interrupt gets trigger right away when the TCNT was set to 0?
Yours sincerely,
Huck
Interrupt is fired when both TIE and TFLG1 are set. So it must be set flag in TFLG1. Though documentation states TFLG1 is all 0 out of reset, I always clear TFLG1 before enabling TIE interrupts. No problems so far.
Hello Edward,
ok, thanks for the tips. I will check my code to see if I am missing something.
Yours sincerely,
Huck