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
Hi,
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.
Thanks,
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
Hi
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 www.mjbc.ch. 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..
Code:
/***********************/ // 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 } /**************************************************/
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 (http://www.driver2go.net).
It contains (amongst others) HCS12 drivers for the PWM and ECT,
including multimedia tutorials on how to set it up.