Using HCS08 TPM Timer Module to generate 1 second interrupt

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Using HCS08 TPM Timer Module to generate 1 second interrupt

Jump to solution
4,819 Views
Coderunner
Contributor III

Hello,

 

I am trying to use TPM1 Module on MC9S08JM60 to generate an interrupt every second.

I am operating in PEE mode using 12MHz external crystal and bus frequency of 24MHz.

But since 24MHz seems too high to get 1 second interrupt usint TPM I'm using "Fixed system clock" source for TPM which runs at 1.5MHz since RDIV value is 8.

So, I figured, if I set TPM prescaler to divide by 32: 1.5MHz/32=46,875 or 0xB71B, all I need is to set Modulo value to 0xB71B and that should give me one overflow (TOF) per second?

 

No matter what value I set TPM1MOD to it seems to have no effect on terminal count. I mean, looking at TPM1CNT in emulator it counts up from 0 to about 32767 then counts from -32767 to 0 and repeats???

 

  //*** SET-UP TIMER - TPM1 MODULE
  TPM1SC_TOF = 0;               //timer has not overflowed
  TPM1SC_CLKSA = 0;          //select fixed system clock (1.5MHz)
  TPM1SC_CLKSB = 1;
  TPM1SC_CPWMS =0;
  TPM1SC_PS = 0b100;         //clock source divided 16
  TPM1MOD = 0x0FFF;            //set counter modulus (terminal count)
  TPM1SC_TOIE = 1;               //enable TPM1 timer overflow interrupts

 

 

 

  //*** Configure Multi-purpose Clock Generator (MCG) for 24MHz bus frequency
  //Switching from FEI Mode to PEE Mode
  //FEI --> FBE
  MCGC2 = 0x36;           
  while(!MCGSC_OSCINIT);              //loop until crystal has been initialized, OSCINIT = 1
  DisableInterrupts;                             //disable interrupts so no extra steps occur in 1.5MHz range
  MCGC1 = 0x98;                                 //CLKS=10 (Ext. ref); RDIV=011 (12MHz/8=1.5MHz)
  while(MCGSC_IREFST == 1);        //loop until IREFST = 0; Ext. reference is source
  while(MCGSC_CLKST != 0b10);   //loop until external ref. clock is selected to feed MCGOUT
  //FBE --> BLPE
  MCGC2 = 0x3E;                                 //LP = 1; BLPE MODE ON
  EnableInterrupts;
  MCGC3 = 0x48;                                 //1.5MHz*32=48MHz; PLL is selected (prepared for PBE)
  while(!MCGSC_PLLST);                  //loop until current source for PLLS clock is PLL; PLLST=1
  //BLPE --> PBE
  MCGC2 = 0x36;                                 //LP = 0; BLPE MODE OFF, PBE MODE ENTERED
  while(!MCGSC_LOCK);                   //loop until PLL acquired lock; LOCK=1
  //PBE --> PEE
  MCGC1 = 0x18;                                 //CLKS = 00; output of PLL or FLL is selected
  while(MCGSC_CLKST != 0b11);   //loop until PLL output is selected to feed MCGOUT  

Labels (1)
0 Kudos
1 Solution
1,018 Views
bigmac
Specialist III

Hello, and welcome to the forum.

 

What you are observing is correct, but with TPM1CNT shown as a signed value within the emulator.  If you were to observe TPM1CNT as an unsigned value, you would see the value go from zero to 65535, and then back to zero (for a free running counter).

 

I have some further comments about your coding:

  1. Perhaps the bus clock should be initialised prior to initialising your timing processes.
  2. When writing to the TPM1SC register, write all bits simultaneously, rather than individual bit values in succession.  The one exception is the clearing process for the overflow flag, which might be done after the other bits are initialised.
  3. The prescale value that you have selected is 16, rather than the intended 32.
  4. The new TPM1MOD value perhaps should be set prior to starting the timer.

Maybe the following code:

 

 

TPM1MOD = 46874; // For a terminal count of 46875

TPM1SC = 0x55;   // Fixed sys clock, prescale 32

TPM1SC_TOF = 0;  // Ensure flag is cleared

 

 

Personally, I might choose to generate an interrupt at a much faster rate, say 10 to 100 milliseconds period, and use a static variable within the ISR as a counter for the one second interval.

 

 

static byte count = 100;

count--;

if (!count) {

   count = 100;

 

   // Other code here

}

 

 

 

Regards,

Mac

 

View solution in original post

0 Kudos
8 Replies
1,018 Views
fuma
Contributor I
Hi, I have a similar problem for generate with a 1sec interrupt whit 9S08GT32 whit 4MHz internal clock. I set TPM2SC = 0x4F TPM2SC_TOIE = 1 TPM2MODH and L at 0xFF and dont work. Is the first time that I use TPM Interrupt in C language, where is my error? Best regards fuma
0 Kudos
1,018 Views
bigmac
Specialist III

Hello,

 

Using the register values that you indicate would give a timer overflow period of approximately 2 seconds.

 

Period = prescale * 65536 / BUSCLK = 128 * 65536 / 4000000 = 2.097 seconds

 

However, TPM2SC_TOIE = 1; is unnecessary because this bit is already becomes set with TPM2SC = 0x4F;

The correct operation of the timer will also depend on the contents of the ISR function.  You will need to explicitly clear the overflow flag within the ISR.

 

Regards,

Mac

 

0 Kudos
1,019 Views
bigmac
Specialist III

Hello, and welcome to the forum.

 

What you are observing is correct, but with TPM1CNT shown as a signed value within the emulator.  If you were to observe TPM1CNT as an unsigned value, you would see the value go from zero to 65535, and then back to zero (for a free running counter).

 

I have some further comments about your coding:

  1. Perhaps the bus clock should be initialised prior to initialising your timing processes.
  2. When writing to the TPM1SC register, write all bits simultaneously, rather than individual bit values in succession.  The one exception is the clearing process for the overflow flag, which might be done after the other bits are initialised.
  3. The prescale value that you have selected is 16, rather than the intended 32.
  4. The new TPM1MOD value perhaps should be set prior to starting the timer.

Maybe the following code:

 

 

TPM1MOD = 46874; // For a terminal count of 46875

TPM1SC = 0x55;   // Fixed sys clock, prescale 32

TPM1SC_TOF = 0;  // Ensure flag is cleared

 

 

Personally, I might choose to generate an interrupt at a much faster rate, say 10 to 100 milliseconds period, and use a static variable within the ISR as a counter for the one second interval.

 

 

static byte count = 100;

count--;

if (!count) {

   count = 100;

 

   // Other code here

}

 

 

 

Regards,

Mac

 

0 Kudos
1,018 Views
Coderunner
Contributor III

bigmac,

 

Whats the difference generating a faster interrupt and counting up to a second vs 1 second interrupt?

 

Thanks

0 Kudos
1,018 Views
bigmac
Specialist III

Hello,

 


Coderunner wrote:

 

Whats the difference generating a faster interrupt and counting up to a second vs 1 second interrupt?


 

It really depends on the specific requirements of a project, but making use of shorter tick period for the timer overflow interrupt means that it is potentially feasible to use a single timer for multiple timing periods that may be required, where each period would correspond to an integral multiple of the chosen tick period.  With a faster TPM clock rate, this may also be more convenient for making use of the TPM channels for other timing purposes, in addition to the overflow interrupt.

 

An alternative approach may be to use a TPM channel (software only output compare interrupt) to generate the tick period, instead of the TPM overflow, and leave the TPM modulo value in free running mode.  This would simplify the use of other TPM channels for different timing purposes, including input capture events.

 

Regards,

Mac

 

0 Kudos
1,018 Views
Coderunner
Contributor III

Got it! Thank you very much.

0 Kudos
1,018 Views
Coderunner
Contributor III

I also realized that fixed system clock is not 1.5MHz but 750kHz since its divided by 2 after being synchronized to bus clock.

0 Kudos
1,018 Views
Coderunner
Contributor III

Hello and thank you bigmac. I appreciate your help. Now its clear to me and thanks for structural tips.

0 Kudos