Kirk Humphries

Getting the Pulse Accumulator working

Discussion created by Kirk Humphries Employee on Jan 29, 2006

This message contains an entire topic ported from a separate forum. The original message and all replies are in this single message. We have seeded this new forum with selected information that we expect will be of value to you as you search for answers to your questions.


Posted: Tue Aug 23, 2005  6:49 pm




I would like to have my timers(Ch. 4 -7) interrupt me after a number of seconds have passed. It seems that the only way to do this is to use the Pulse Accumulator's clock PACLK and divide it by 65536 using the CLK1:0 bits in the PACTL.


Currently I have IOC7 through IOC4 tied to GND, and am setting PACTL to 0x7C. But my channel 4 timer isn't getting interrupts. Only when I disable the Pulse Accumulator does the channel 4 timer interrupt.


Can someone make a suggestion as to how to make this work? Or if there is another way to make the counters count for several seconds I would be interested in that too.





Posted: Tue Aug 23, 2005  8:29 pm


To only count time, you do not have to (and probably should not) use the Pulse Accumulator. All you need to do is keep track of the number of times a timer overflows or times out. Attached are two files showing how the 68HC11 timer (very much like the HC12) making 1 second ticks. I think it could easily be extended to a 9-second period by only changing the 3-byte number representing the timer tics in a period. Beyond that one would have to slow down the timer tics or extend the 3-byte number.


Another example make long periods is in Han-Way Huang's 68HC12 book on page 307-9. His Example 8.5 has both assembly and C code.



Posted: Tue Aug 23, 2005  9:41 pm


The usual way of doing this is to set the hardware timer for as large a time as possible depending on your clock. Then in the interrupt routine establish a sotware down counter to get to your overall large time. When the SW counts down to 0, reset the down counter and do your thing.



Posted: Wed Aug 24, 2005  9:31 pm



I managed to get the PA working as a timer by setting up channel 4 to generate a clock and using this clock an an input to the PA. The PA generates an interrupt when it overflows so it is easy to generate a delay by setting the PA counter to (0x0000 - delay). By setting channel 4 to generate a high or a low frequency it is possible to generate very short to quite long and very accurate delays with an interrupt at the end.


Here is a bit of code without great details. It generates 3 PWM outputs from channels 1..3 based on a 3kHz frequency at channel 4. Channel 4 output is turned on when required to drive a buzzer signal at 3kHz and also for use by the PA input to generate the desired delay.


If you would like to see the code in action there is a demo at You can download a program called 'VIPpanel' and control the contrast and backlight of the LCD (along with other things) via the Internet. The following PWMs are in use. You can also generate variable 'beep' lengths but won't be able hear it of course since the Webcam has no sound. Nevertheless you should get the idea..



/***********************/  // Initialisation  #define CONTRAST_CONTROL TC6_HI  #define BACKLIGHT_CONTROL TC4_HI  #define LED_CONTROL TC5_HI     TIOS = (IOS7 | IOS6 | IOS5 | IOS4); // enable output compare on all  channels  OC7M = (OC7M6 | OC7M5 | OC7M4); // 3 channels as output (channel  7 (buzzer) not yet)  OC7D = (OC7D6 | OC7D5 | OC7D4); // transfer on channel 7 match  (for PWM)  TSCR1 = TEN; // enable timer  TCTL1 = 0x15; // toggle output for 3 channels  CONTRAST_CONTROL = (unsigned short)ucContrastSetting; //  set default contrast setting  LED_CONTROL = 0x00ff; // set max LED intensity  BACKLIGHT_CONTROL = 0x0000; // set min backlight intensity  (off)  TC7_HI = 0x00ff; // basic frequency is 3kHz  TSCR2 = 0x0c; // enable timer div = 32        // generate 3kHz tone for a specified period, interrupt from PA when  complete     #define FIXED_FREQUENCY 3000 // fixed frequency of buzzer  output  #define PERIOD_50MS (FIXED_FREQUENCY/20) //  ((FIXED_FREQUENCY*50)/1000) // pulses in 50ms        static void fnGenerateTone(unsigned char ucLength)  {  unsigned short usPeriodPulses = 0;     TCTL1 |= 0x40; // drive buzzer output     while (ucLength--) {  usPeriodPulses -= PERIOD_50MS;  }  PACNT_WORD = usPeriodPulses;     PACTL = (PAEN | PEDGE | PAOVI); // enable interrupt on overflow  }     // Interrupt due to pulse accumulator overflow  void Acc_Overflow(void)  {  PAFLG = PAOVF; // reset interrupt  TCTL1 &= ~0x40; // remove buzzer drive  PACTL = 0; // stop pulse accumulator activity  }  /**************************************************/


Posted: Thu Aug 25, 2005  11:12 am


Especially the PWM subsystem is a tricky one to setup due to all the

clock configurations. If you'd like to save some time, you can use

Driver2Go (


It contains (amongst others) HCS12 drivers for the PWM and ECT,

including multimedia tutorials on how to set it up.