Freescale Semiconductor Application Note AN2701 Rev. 0, 10/2004 PWM Generation with the HC08 Timer by: Alban Rampon 8/16-bit Division East Kilbride Introduction All HC08 microcontrollers (MCUs) include at least one timer module (TIM). This module is very useful for generating or capturing time-dependent signals. The data sheet describes what the timer module is capable of and how to use it. This application note gives further explanation of how the TIM behaves in the following situations. • Unbuffered pulse width modulation (PWM) signal generation • Rolling PWM generation • Timer activity during Break and software interrupts PWM signals are used in many applications from dimmers (duty cycle variation gives more/less light from LEDs) to IR transceivers (modulation/demodulation). An example illustrating rolling generation is included, with sample code, in the appendix at the end of this document. © Freescale Semiconductor, Inc., 2004. All rights reserved. Introduction Principle of PWM Generation Using Timers The generation of a PWM signal using the dedicated HC08 PWM module is based on hardware comparisons between register values and a free-running hardware counter. The HC08 TIM offers similar hardware comparison in the form of output compare circuitry. The contents of channel registers are continuously compared to the master free-running timer. When a match occurs, a hardware output event can be configured to take place, and/or an interrupt can then call a service routine. The timer module has from two to six compare registers and can thus be configured to toggle the port pin on each of two to six comparison values, with no core overhead. Each PWM signal requires a dedicated timer channel with output compare capability. Any channel with this function along with the associated interrupt vector may be used to generate a PWM signal, using the methods described. Functional Description Features of the TIM can include • Two to six input capture/output compare channels – Rising-edge, falling-edge or any-edge input capture trigger – Set, clear or toggle output compare action • Buffered and unbuffered pulse width modulation (PWM) signal generation • Programmable TIM clock input – Seven frequency internal bus clock prescaler selection – External TIM clock input (4 MHz maximum frequency) • Free-running or modulo up-count operation • Toggle any channel pin on overflow • TIM counter Stop and Reset bits Block Diagram Figure 1 shows the structure of the TIM, taken from an MC68HC908GZ60 (two channels represented out of the six available). The central component of the TIM is the 16-bit counter, which can operate as a freerunning counter or a modulo up-counter. The TIM counter provides the timing reference for the input capture and output compare functions. The TIM counter modulo registers, TMODH:TMODL, control the modulo value of the timer counter. Software can read the TIM counter value at any time without affecting the counting sequence. In the case of the HC908GZ60, the six timer channels are programmable independently as input capture or output compare channels. In other devices, the number of channels may vary from two to six; however, the rest of the module remains identical. PWM Generation with the HC08 Timer, Rev. 0 2 Freescale Semiconductor Introduction TCLK PTD6/T2CH0 PRESCALER SELECT INTERNAL BUS CLOCK PRESCALER TSTOP PS2 TRST PS1 PS0 16-BIT COUNTER TOF TOIE INTERRUPT LOGIC 16-BIT COMPARATOR T2MODH:T2MODL CHANNEL 0 ELS0B ELS0A TOV0 CH0MAX 16-BIT COMPARATOR T2CH0H:T2CH0L CH0F 16-BIT LATCH MS0A CHANNEL 1 ELS1B MS0B ELS1A TOV1 CH1MAX 16-BIT COMPARATOR T2CH1H:T2CH1L CH0IE CH1F 16-BIT LATCH MS1A CH1IE PTD6 LOGIC T2CH0 INTERRUPT LOGIC PTD7 LOGIC T2CH1 INTERRUPT LOGIC Figure 1. HC08 Generic Timer Module Block Diagram Timer Counter Prescaler The timer clock source can be one of the seven prescaler outputs or the timer clock pin (PTD6/T2CH0 on HC908GZ60). The prescaler generates seven clock rates from the internal bus clock. The prescaler select bits, PS[2:0], in the timer status and control register select the timer clock source (see Table 1). PWM Generation with the HC08 Timer, Rev. 0 Freescale Semiconductor 3 PWM Generation Table 1. Timer Prescaler Values(1) PS[2:0] TIM2 Clock Source 000 Internal Bus Clock ÷ 1 001 Internal Bus Clock ÷ 2 010 Internal Bus Clock ÷ 4 011 Internal Bus Clock ÷ 8 100 Internal Bus Clock ÷ 16 101 Internal Bus Clock ÷ 32 110 Internal Bus Clock ÷ 64 111 T2CH0 NOTES: 1. Not all timers allow all possible values; refer to the device data sheet. PWM Generation Initialization Procedure To ensure correct operation when generating unbuffered or buffered PWM signals, follow the procedure as stated in the data sheet: 1. In the TIMx status and control register (TxSC): a. Stop the TIMx counter by setting the TIMx stop bit, TSTOP. b. Reset the TIMx counter and prescaler by setting the TIMx reset bit, TRST. 2. In the TIMx counter modulo registers (TxMODH:TxMODL) write the value for the required PWM period. 3. In the TIMx channel y registers (TxCHyH:TxCHyL) write the value for the required pulse width. 4. In TIMx channel y status and control register (TxSCy): c. d. e. Write 0:1 (for unbuffered output compare or PWM signals) or 1:0 (for buffered output compare or PWM signals) to the mode select bits, MSxB:MSxA. Write 1 to the toggle-on-overflow bit, TOVx. Write 1:0 (to clear output on compare) or 1:1 (to set output on compare) to the edge/level select bits, ELSxB:ELSxA. The output action on compare must force the output to the complement of the pulse width level. NOTE IMPORTANT: Do not use direct assignment instructions, such as MOV #0x1A, 0x25, or STA 0x25, for channel status and control registers. PWM Generation with the HC08 Timer, Rev. 0 4 Freescale Semiconductor PWM Generation Assignment must be done sequentially (using BSET 4,+ 0x25, for example) following the steps of the PWM Initialization procedure described above. Table 2. Mode, Edge, and Level Selection MSxB MSxA ELSxB ELSxA x 0 0 0 Mode Configuration Pin under port control; initial output level high Output Preset x 1 0 0 Pin under port control; initial output level low 0 0 0 1 Capture on rising edge only 0 0 1 0 0 0 1 1 Capture on rising or falling edge 0 1 0 0 Software compare only 0 1 0 1 0 1 1 0 0 1 1 1 1 x 0 1 1 x 1 0 1 x 1 1 Input Capture Output Compare or PWM Capture on falling edge only Toggle output on compare Clear output on compare Set output on compare Buffered Output Compare or Buffered PWM Toggle output on compare Clear output on compare Set output on compare If this procedure is not followed, the PWM signal generated will not be as expected. PWM Generation with the HC08 Timer, Rev. 0 Freescale Semiconductor 5 PWM Generation Channel 1: PWM signal generated Channel 2: Events Figure 2. Timer Erroneous Initialization Figure 2 shows what the resulting PWM signal may look like. In this case, the full register has been written instead of setting the bits in proper order. The first pulse on Channel 2 is just after the direct assignment to the timer status and control register is complete. The second pulse follows the instruction to start the timer. Between these two events, the software initializes other modules. The first pulse of the PWM appears to be quite long and earlier than expected. Its length also depends on the code executed between the initialization and the free-running counter startup. Figure 3 shows the PWM signal being generated correctly when the recommended procedure is followed. PWM Generation with the HC08 Timer, Rev. 0 6 Freescale Semiconductor PWM Generation Channel 1: PWM signal generated Channel 2: Events Figure 3. Timer Correct Initialization PWM Generation Without CPU Load In many applications, it is useful to be able to generate a PWM signal and then not have to worry about it. For example, to control LEDs illuminating a dashboard, the duty cycle and frequency do not have to be constantly changed or monitored. The HC08 timer can generate such a signal, without loading the MCU. This mode is called unbuffered PWM generation. After the setup is done, the PWM signal is generated whatever is being executed (except Reset, Break, and if the timer is stopped), without requiring any interrupt or instruction to be executed. The modulo counter value represents the period of the signal. The ratio between the values in the output compare and modulo registers represents the duty cycle. This method is simple to use and can be implemented as follows. If the timer is configured to be reset on output compare and to toggle on overflow, the timer output state when it starts to count will be logic 0. When the output compare value is reached, the output is already at logic 0 and will only toggle to logic 1 when the first overflow occurs. The user should be aware that the first pulse may appear to be missing. It is possible to have this pulse earlier by inverting the signal. If the timer sets the output on output compare (bit ELSxA at logic 1 in the timer status and control register — see Table 2) instead of resetting it (keeping toggle-on-overflow bits MSxA and MSxB at logic 0), then the greater the duty cycle, the earlier the first pulse occurs. PWM Generation with the HC08 Timer, Rev. 0 Freescale Semiconductor 7 PWM Generation Channel 1: PWM signal generated Channel 2: Events Figure 4. Set on Output Compare The major advantage of this method is that it works separately from the CPU activity and the rest of the software. However, it also means the timer used for the PWM generation has its modulo counter (i.e. signal period) fixed for all its other channels. Therefore, generation of multiple signals with different periods will be impossible on the same module; only different duty cycles will be possible. Flexible PWM Rolling Generation Principle The solution described above is easy to set up and use, but could lack flexibility. Using the following method will increase the possibility that the timer can generate any PWM signal on any channel. However, it will also increase the complexity and size of the code. The principle used here is to not rely on the modulo counter to determine the period, as only one is available for all channels of the same timer. References to the master timer modulo register, TxMODH:TxMODL, are avoided by simply adding consecutive mark (logic 1) and space (logic 0) values to the timer compare register on successive ISR function calls, as shown in the following equations. Timer roll-over is seamless when using unsigned integer addition. Using the previous compare value as a reference for generating the next compare value allows precise output timing, even though the ISR latency may vary. PWM Generation with the HC08 Timer, Rev. 0 8 Freescale Semiconductor PWM Generation During Break or Software Interrupt Bus Frequency PWM Period (timer ticks) = --------------------------------------------------------------------------------------------Timer Prescaler × PWM Frequency Eq. 1 Period × Duty Cycle (as an integer percentage)PWM Mark Time (timer ticks) = PWM -------------------------------------------------------------------------------------------------------------------------------------------100 Eq. 2 PWM Space Time (timer ticks) = PWM Period – PWM Mark Time Eq. 3 Once the timer channel is configured, the PWM signal can be generated using the timer channel interrupt. This should be configured to call the channel interrupt service routine (ISR), loading the timer compare register with its current value added to the length desired (mark or space). This is achieved by identifying whether the last action was a negative or positive edge (the port pin toggles on output compare), and loading the compare register with the next appropriate value. If the port pin is at logic one (or zero), a mark (or space) is to be added. NOTE In this case, the overflow flag and interrupt are not relevant as the counter is used as free-running with roll-over. The sample code in the appendix at the end of this document gives an example of how to apply this principle. Limitations The MCU must be able to service the timer PWM interrupts in time for the next edge to be configured. This sets an upper limit on the frequency/resolution of PWM signal that can be reproduced, and will vary from system to system depending on the MCU application. It is the responsibility of the system designer to ensure that the core can update the compare registers in sufficient time using the ISR under maximum core loading conditions. A secondary limitation is that using the timer module incurs a greater degree of core overhead, as the timer module has to be serviced at every edge transition (interrupt). This does not happen with the unbuffered PWM via modulo counter, as the toggling mechanism is independent of the core and code execution. The described method of PWM generation is likely to be more suited to slower rate PWM requirements, due to the overhead generated by having to service an interrupt for each edge of each PWM signal. PWM Generation During Break or Software Interrupt The HC08 data sheet states that the timer is stopped during a break. It is important to distinguish a Break from a software interrupt (SWI) instruction. The Break Module (BRK) is primarily used in a debugging/development context. For example, breakpoints in monitor mode are generated using this module. This explains why the debugger stops program execution when an address match or BRKA bit-mask is performed. PWM Generation with the HC08 Timer, Rev. 0 Freescale Semiconductor 9 PWM Generation During Break or Software Interrupt This module could also be used in normal operation to allow for future code enhancements. For example, on a ROM device with EEPROM (like the HC08AZ60A, the GZ family does not include EEPROM), a developer can expect either to have to add a routine not available when the part is produced, or to have to manage future upgrades. The break instruction would call the non maskable software interrupt (vector $FFFC:$FFFD), and the interrupt subroutine would reside in EEPROM. If the program is using the timer to generate a PWM signal, the Break interrupt will hold the timer counter, to resume after its execution. Therefore, the PWM signal is affected by the interrupt, and this may present a problem if the Break interrupt execution time is significant. Figure 5 shows how the PWM signal on Channel 1 is irregular and delayed by the activity of the interrupt (Channel 2 high when Break interrupt is being executed). Channel 1: PWM signal generated Channel 2: High during Break ISR execution Figure 5. PWM Generation During a Break Note that the user also must allow status bits to be changed (by modifying the BFCR_BCFE bit at $FE03), for them to be updated. For further details, please refer to the System Integration Module (SIM) Chapter in the device data sheet. The Break interrupt shares its vector with the software interrupt (SWI) and the data sheet states that the Break function fetches an SWI. However, the SWI instruction does not 'freeze' any function of the MCU. A PWM signal configured with toggle-on-overflow without using interrupt (unbuffered PWM) will not be influenced in any way by an SWI (see Figure 6). PWM Generation with the HC08 Timer, Rev. 0 10 Freescale Semiconductor Conclusion Channel 1: PWM signal generated Channel 2: High during SWI ISR Figure 6. PWM Generation During and SWI To summarize, when this interrupt has to be used in normal operation, it is advisable to use an SWI instruction, instead of a Break, to minimize the impact on the microcontroller operations (timer and other modules). NOTE The Break (BRK) and Software Interrupt (SWI) share the same interrupt vector. Therefore, the effect really depends on how the ISR is called and not on its content. Conclusion The HC08 timer is easy to use and can be used in a myriad of applications. However, the user must take care to set it up properly to ensure that the desired function is achieved. Depending on the user’s priority (code size, complexity, resource utilization, for example), it will be possible to find a solution to suit the application. PWM Generation with the HC08 Timer, Rev. 0 Freescale Semiconductor 11 APPENDIX APPENDIX Program Flowchart Channel ISR called N Increase the channel register of a space value Port Pin at Logic 1? Y Increase the channel register of a mark value Sample Code /****************************************************************************** * COPYRIGHT (c) FREESCALE SEMICONDUCTOR 2004 * ALL RIGHTS RESERVED * FILE NAME: AN2701_timerISR.c * * PURPOSE: HC908GZ60 Sample Code for the Timer Interrupt Sub Routine * ******************************************************************************* ******************************************************************************* ** THIS CODE IS ONLY INTENDED AS AN EXAMPLE FOR THE METROWERKS COMPILER AND ** **THE MMDS0508/EM08QA24 EVB AND HAS ONLY BEEN GIVEN A MIMIMUM LEVEL OF TEST. ** ** IT IS PROVIDED 'AS SEEN' WITH NO GUARANTEES AND NO PROMISE OF SUPPORT. ** ******************************************************************************* ******************************************************************************* * * DOCUMENTATION SOURCE: EKB Apps * * TARGET DEVICE: HC908GZ60 * * COMPILER: Metrowerks for HC08 VERSION: v5.2.1149 * PWM Generation with the HC08 Timer, Rev. 0 12 Freescale Semiconductor APPENDIX * DESCRIPTION: This ISR describe how to use rolling PWM generation, not to tie * all channels from a Timer to the same period. * * AUTHOR: A.RAMPON LOCATION: EKB LAST EDIT DATE: 15/08/04 * * UPDATE HISTORY * REV AUTHOR DATE DESCRIPTION OF CHANGE * -----------------------------------* 1.0 A.Rampon 11/08/04 Initial Release ******************************************************************************/ #ifndef __AN2701_TIMER_ISR_C #define __AN2701_TIMER_ISR_C /* if this H file not included, include */ #include "hc08gz60.h" /********************************************************************** Function Name : _PWMTimerChan0ISR Engineer : A.Rampon Date : 01/04/04 Parameters : NONE Returns : NONE Notes : Interrupt service routine for Rolling PWM Generation on Channel 0. **********************************************************************/ #pragma TRAP_PROC void _PWMTimerChan0ISR(void) { /* if channel is set to generate rising edge */ /* On MC908AZ60A, TBCH0 is PTF4 */ /* If after toggled output is set, */ /* a mark is beginning */ if (PTF4 == 1) { /* set up timer compare for mark time */ /* relative to the last transition */ TBCH0 += Mark[0]; } else { /* set up timer compare for space time */ /* relative to the last transition */ TBCH0 += Space[0]; } } PWM Generation with the HC08 Timer, Rev. 0 Freescale Semiconductor 13 How to Reach Us: Information in this document is provided solely to enable system and software implementers to use Freescale Semiconductor products. There are no express or implied copyright licenses granted USA/Europe/Locations not listed: Freescale Semiconductor Literature Distribution P.O. Box 5405, Denver, Colorado 80217 1-800-521-6274 or 480-768-2130 hereunder to design or fabricate any integrated circuits or integrated circuits based on the information in this document. Freescale Semiconductor reserves the right to make changes without further notice to any products herein. Freescale Semiconductor makes no warranty, representation or guarantee regarding the Japan: Freescale Semiconductor Japan Ltd. SPS, Technical Information Center 3-20-1, Minami-Azabu Minato-ku Tokyo 106-8573, Japan 81-3-3440-3569 suitability of its products for any particular purpose, nor does Freescale Semiconductor assume any liability arising out of the application or use of any product or circuit, and specifically disclaims any and all liability, including without limitation consequential or incidental damages. “Typical” parameters which may be provided in Freescale Semiconductor data sheets and/or specifications can and do vary in different applications and actual performance may vary over time. All operating parameters, including “Typicals” must be validated for each customer application by customer’s technical experts. Asia/Pacific: Freescale Semiconductor H.K. Ltd. 2 Dai King Street Tai Po Industrial Estate Tai Po, N.T. Hong Kong 852-26668334 Freescale Semiconductor does not convey any license under its patent rights nor the rights of others. Freescale Semiconductor products are not designed, intended, or authorized for use as components in systems intended for surgical implant into the body, or other applications intended to support or sustain life, or for any other application in which the failure of the Freescale Semiconductor product could create a situation where personal injury or death may occur. Should Buyer purchase or use Learn More: For more information about Freescale Semiconductor products, please visit http://www.freescale.com Freescale Semiconductor products for any such unintended or unauthorized application, Buyer shall indemnify and hold Freescale Semiconductor and its officers, employees, subsidiaries, affiliates, and distributors harmless against all claims, costs, damages, and expenses, and reasonable attorney fees arising out of, directly or indirectly, any claim of personal injury or death associated with such unintended or unauthorized use, even if such claim alleges that Freescale Semiconductor was negligent regarding the design or manufacture of the part. Freescale™ and the Freescale logo are trademarks of Freescale Semiconductor, Inc. All other product or service names are the property of their respective owners. © Freescale Semiconductor, Inc. 2004. AN2701 Rev. 0, 10/2004