HC12 Basic Timer System ME 4370/5370, ECE 4240 Introduction: (From Cady and Sibigtroth, 2000). The M68HC12 timer system is based on the 16-bit freerunning counter called TCNT. This counter uses the M-clock (the system clock) as its source and a prescaler of 1,2,4,8, or 16 to provide time information to the HC12. The prescaler can be controlled by seting the three bits, PR2:PR0 in the Timer Interrupt Mask Register 2 (TMSK2) (see the fig. below). The default setting is a prescaler of 1. The TCNT register can be read at any time to provide this time information. When the register reaches a count of 65,536 pulses ($FFFF), the counter overflows and is reset to 0 ($0000). At this point, a timer overflow flag (TOF) is set, which can be used to record longer periods of time. Note that with a 4 MHz clock and a prescaler of 1, the timer will go from $0000 to $FFFF in 0.0164 seconds. The counter is reset when the MCU is reset and runs continuously in general. The counter cannot be set when the MCU is operating in normal mode. The following paragraphs describe the procedure to use the timer in its most basic form. Step 1: Turn on the timer: The timer is enabled by setting the MSB of the TSCR (timer system control register). TSCR1 -- $0006 – Timer System Control Register 1 Bit 7 TEN Reset 0 6 TSWAI 0 5 TSBCK 0 4 TFFCA 0 3 0 0 2 0 0 1 0 0 bit 0 0 0 with TEN: Timer enable; 0 disables the timer including TCNT (default, reduces power consumption), 1 enables the timer TSWAI: Timer stops while in wait; 0 allows timer to continue running during a wait (default), 1 stops the timer while in wait mode. TSBCK: Timer stops while in background mode (same as above). TFFCA: Timer Fast Flag Clear All Step 2: Set any timer prescaling as desired on TSCR2 (Timer interrupt mask register 2) Timer System Control Register 2 (TSCR2) TOI = Timer overflow interrupt enable (1 enables interrupt when timer overflow flag is set) PR2, PR1, PR0 = Timer prescaler select bits prescale the module clock to achieve the main timer counter according to the following table 1 TCRE: Timer counter resent enable (0, counter reset is inhibited and TCNT free runs, 1, TCNT is reset to $0000 when a successful output compare occurs on timer channel 7) Step 3: Clear the timer overflow flag in TFLG2 (Timer interrupt flag 2) register (if needed) TFLG2 -- $008F – Timer Interrupt Flag 2 Bit 7 TOF Reset 0 6 0 0 5 0 0 4 0 0 3 0 0 2 0 0 1 0 0 bit 0 0 0 TOF: Timer Overflow Flag. This bit is set when the TCNT register count goes from $FFFF to $0000. The timer overlow bit is reset by writing a one to bit-7 of TFLG2. Step 4: Read the current time (contained in TCNT, timer count register), or count timer overflows (contained in TFLG2 register). TCNT -- $0084:0085 – Timer Count Register Bit 7 15 7 Reset 0 6 14 6 0 5 13 5 0 4 12 4 0 3 11 3 0 2 10 2 0 1 9 1 0 bit 0 8 0 0 Notes: 1) When timing via counting overflow flags, the TOF can be observed with polling or interrupts. Once a TOF is counted, be sure to reset it by writing to this bit (bit 7 in TFLG2). 2) If no prescale is used, then a TOF occurs every 8.19 ms (with 8MHz clock) 2 Real Time Interrupt CRGINT –CRG Interrupt Enable Register Bit 7 RTIE Reset 0 6 0 0 5 0 0 4 LockiE 0 3 0 0 2 0 0 1 SCMIE 0 bit 0 0 0 2 RTR2 0 1 RTR1 0 bit 0 RTR0 0 RTIE – Real Time Interrupt Enable 0 = Interrupt request from RTI are disabled 1 = Interrupt will be requested whenever RTIF is set RTICTL –CRG RTI Control Register Bit 7 0 Reset 0 6 RTR6 0 5 RTR5 0 4 RTR4 0 3 RTR3 0 3 system clock; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 10 4.26667E-05 8.53333E-05 0.000128 0.000170667 0.000213333 0.000256 0.000298667 0.000341333 0.000384 0.000426667 0.000469333 0.000512 0.000554667 0.000597333 0.00064 0.000682667 11 8.53E-05 0.000171 0.000256 0.000341 0.000427 0.000512 0.000597 0.000683 0.000768 0.000853 0.000939 0.001024 0.001109 0.001195 0.00128 0.001365 24000000 In Seconds 12 0.000171 0.000341 0.000512 0.000683 0.000853 0.001024 0.001195 0.001365 0.001536 0.001707 0.001877 0.002048 0.002219 0.002389 0.00256 0.002731 13 0.000341 0.000683 0.001024 0.001365 0.001707 0.002048 0.002389 0.002731 0.003072 0.003413 0.003755 0.004096 0.004437 0.004779 0.00512 0.005461 14 0.000683 0.001365 0.002048 0.002731 0.003413 0.004096 0.004779 0.005461 0.006144 0.006827 0.007509 0.008192 0.008875 0.009557 0.01024 0.010923 15 0.001365 0.002731 0.004096 0.005461 0.006827 0.008192 0.009557 0.010923 0.012288 0.013653 0.015019 0.016384 0.017749 0.019115 0.02048 0.021845 16 0.002731 0.005461 0.008192 0.010923 0.013653 0.016384 0.019115 0.021845 0.024576 0.027307 0.030037 0.032768 0.035499 0.038229 0.04096 0.043691 13 2929.688 1464.844 976.5625 732.4219 585.9375 488.2813 418.5268 366.2109 325.5208 292.9688 266.3352 244.1406 225.3606 209.2634 195.3125 183.1055 14 1464.844 732.4219 488.2813 366.2109 292.9688 244.1406 209.2634 183.1055 162.7604 146.4844 133.1676 122.0703 112.6803 104.6317 97.65625 91.55273 15 732.4219 366.2109 244.1406 183.1055 146.4844 122.0703 104.6317 91.55273 81.38021 73.24219 66.58381 61.03516 56.34014 52.31585 48.82813 45.77637 16 366.2109 183.1055 122.0703 91.55273 73.24219 61.03516 52.31585 45.77637 40.6901 36.62109 33.2919 30.51758 28.17007 26.15792 24.41406 22.88818 In Hz: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 10 23437.5 11718.75 7812.5 5859.375 4687.5 3906.25 3348.214286 2929.6875 2604.166667 2343.75 2130.681818 1953.125 1802.884615 1674.107143 1562.5 1464.84375 11 11718.75 5859.375 3906.25 2929.688 2343.75 1953.125 1674.107 1464.844 1302.083 1171.875 1065.341 976.5625 901.4423 837.0536 781.25 732.4219 12 5859.375 2929.688 1953.125 1464.844 1171.875 976.5625 837.0536 732.4219 651.0417 585.9375 532.6705 488.2813 450.7212 418.5268 390.625 366.2109 4 #include <hidef.h> /* common defines and macros */ #include <mc9s12dp256.h> /* derivative information */ #include <stdio.h> #include "lcd.h" #pragma LINK_INFO DERIVATIVE "mc9s12dp256b" /*************************************************************** * Function prototypes ****************************************************************/ __interrupt void RealTimeInterrupt( void ); volatile int delay; //counter for interrupt volatile int d1, d2; //array index of which number to output on display volatile int counter; int counting; //0=timer stopped, 1=timer running void main( void ) { char string[17]; //initialize global variables counting = 0; //0=timer stopped, 1=timer running counter = 0; delay = 0; //set counter for interrupt to 0 //setup data direction port DDRH = 0; //allow input from pushbuttons LCD_init(); //setup realtime interrupt RTICTL = 0x28; //8MHz / (9 * 2^11) = 434.02778 MHz or 2.304 ms CRGINT |= 0x80; // enable RTI interrupt EnableInterrupts; /* Enable global interrupts */ while(PTH & 0x08); //wait for input from pushbutton 1 (sw2) counting = 1; //start timer while(1) //loop forever { if ((PTH & 0x04) == 0) //pushbutton 2(sw3) is pressed { counting = 0; //stop timer } else if ((PTH & 0x08) == 0) //pushbutton 1(sw2) is pressed { counting = 1; //start timer } sprintf(string,"%16d", counter); writeLine(string, 1); } } __interrupt void RealTimeInterrupt( void ) { 5 if (counting && delay < 434) //one second has not passed yet { delay++; //update one second delay counter } else if (counting) //update counter variable { delay = 0; //reset one second delay counter counter++; } CRGFLG = 0x80; /* clear rti flag */ } 6