Skip to main content

Microcontrollers

Section 9.6 ATmega328P Timer/Counter PWM Modes of Operation

The ATmega328P has three different configurable modes of generating pulse-width modulation (PWM) signals.

Subsection 9.6.1 Fast PWM

In fast PWM mode, the timer/counter increments from BOTTOM to TOP, and then restarts again from BOTTOM. The period of a fast PWM signal is given by (9.6.1).
\begin{equation} T_{fast PWM} = \frac{N \times (\texttt{TOP} + 1)}{f_{CLK,I/O}}\tag{9.6.1} \end{equation}
This equation can be understood by looking at how the value stored in the TCNTn register increments over time. Counting between zero and TOP requires TOP plus one intervals of time. This is depicted in Figure 9.6.1.
Value stored in a timer/counter over time. The value starts at 0, increments by 1 every interval of time and overflows back to 0 after 5 increments.
Figure 9.6.1. The value stored in a timer/counter in fast PWM mode. It takes TOP +1 intervals of time to count between BOTTOM and TOP.
Similar to the distinction between normal and CTC modes, fast PWM can either be configured to count to MAX or to a different TOP value. These options are presented for each timer/counter in Table 9.6.2. (Note that these are also the same options used in phase-correct PWM mode, described in Subsection 9.6.2.)
Table 9.6.2. Sources of TOP for each timer/counter in both fast PWM and phase-correct PWM modes.
Timer/counter 0 Timer/counter 1 Timer/counter 2
0xFF (MAX) 0xFF (8-bit mode) 0xFF (MAX)
OCR0A 0x1FF (9-bit mode) OCR2A
0x3FF (10-bit mode)
OCR1A
ICR1
The timer/counter overflow flag (TOVn) will be set each time the counter reaches TOP. This allows for the use of overflow interrupts in fast PWM mode. Output compare flags will be set each time the counter reaches the value stored in an output compare register. This allows for the use of output compare interrupts as well.
Typically, fast PWM is used to generate waveforms on one or more timer/counter output compare pin. When the compare output mode (COMnx) bits are configured to cause the output compare pin(s) to operate in non-inverting mode, the output compare pin(s) will clear on a compare match and set when the timer/counter is reset to BOTTOM. (The opposite is true in inverting mode.)
If an exact frequency is desired, that cannot necessarily be generated by changing the prescaler and using MAX, the value stored in OCRnA can be used as TOP to set a specific frequency. The output compare pin B can be used to generate the PWM waveform, with the duty cycle set by the value stored in the OCRnB register. The duty cycle in this case is defined by (9.6.2).
\begin{equation} D_{OCnB} = \frac{\texttt{OCRnB}}{\texttt{OCRnA}}\tag{9.6.2} \end{equation}
An example fast PWM waveform of this nature is shown in Figure 9.6.3.
Top graph depicts the value stored in a timer/counter over time. It starts at BOTTOM (0) and then increments through OCRnB to OCRnA, which is less than MAX. At OCRnA, the value overflows to 0. This process repeats several time. The bottom graph depicts the value on the OCnB pin. When the value in the timer/counter is between BOTTOM and OCRnB, the value on the pin is HIGH. When the value in the timer/counter is between OCRnB and OCRnA, the value on the pin is LOW.
Figure 9.6.3. Example of a fast PWM waveform generated on pin OCnB using OCRnA as TOP. The duty cycle is set by the value stored in OCRnB.
When output compare register A (OCRnA) is used as the value of TOP, output compare pin A (OCnA) cannot be used to generate a meaningful PWM waveform. This is because the pin is set every time there is a compare match, and cleared when the timer/counter resets to BOTTOM. However, if OCRnA is equal to TOP, then those two events occur simultaneously, and the value on OCnA will always be HIGH.
An exception to this is timer/counter 1, where value stored in ICR1 can be used to define TOP. In this case, the frequency can be precisely tuned using the value of ICR1 and a prescaler. In addition, both output compare pins can have independent duty cycles configured by their corresponding output compare registers, defined by (9.6.3).
\begin{equation} D_{OC1x} = \frac{\texttt{OCR1x}}{\texttt{ICR1}}\tag{9.6.3} \end{equation}
If the frequency of the PWM waveform is not as strictly circumscribed, both output compare pins can be used to generate PWM signals in any timer/counter by using MAX as the value of TOP. In timer/counter 1, MAX can be configured to operate in 8-bit mode, 9-bit mode, or 10-bit mode, as described in Table 9.6.2. Both output compare pins will have PWM waveforms of the same frequency, but each duty cycle can independently be configured by the corresponding output compare register, with a duty cycle defined by (9.6.4).
\begin{equation} D_{OCnx} = \frac{\texttt{OCRnx}}{\texttt{MAX}}\tag{9.6.4} \end{equation}
Regardless of the value of TOP, when the value in the output compare register used to create the duty cycle of the wave is equal to BOTTOM, the output will be HIGH for one clock cycle. This can be considered to be a glitch, as the output would be expected to be LOW if the output compare register is equal to zero. This is depicted in Figure 9.6.4.
Top graph depicts the value stored in a timer/counter over time. It starts at BOTTOM (0) and then increments to TOP. At TOP, it abruptly overflows back to BOTTOM. This cycle repeats several times. The bottom graph depicts the value output on the OCRnB pin. The value is mostly LOW but has a short glitch to HIGH every time the value on the timer/counter overflows.
Figure 9.6.4. Example of the output glitch that occurs in fast PWM when the output compare register is equal to BOTTOM.

Subsection 9.6.2 Phase-Correct PWM

In phase-correct PWM mode, the timer/counter increments from BOTTOM to TOP, and then decrements back to BOTTOM. The timer/counter remains at TOP for one clock cycle. The frequency of a phase-correct PWM signal is defined by (9.6.5).
\begin{equation} T_{phase-correct PWM} = \frac{2 \times N \times \texttt{TOP}}{f_{CLK,I/O}}\tag{9.6.5} \end{equation}
This equation can be understood by looking at how the value stored in the TCNTn register increments over time. Because the timer/counter only remains at TOP for one interval of time, it takes TOP plus one intervals of time to increment to TOP, but then TOP minus one intervals of time to decrement back to BOTTOM, for a total of 2×TOP intervals of time. This is depicted in Figure 9.6.5.
Value stored in a timer/counter over time. The value starts at 0, increments by 1 every interval of time until it reaches TOP. Then it decrements by 1 every interval of time until it reaches 0 again. This process repeats.
Figure 9.6.5. The value stored in a timer/counter in phase-correct PWM mode. It takes 2×TOP intervals of time to increment from BOTTOM top TOP and then decrement back to BOTTOM.
Phase-correct PWM can either be configured to count to MAX or to a different TOP value. These options are given for each timer/counter in Table 9.6.2.
The timer/counter overflow flag (TOVn) will be set each time the counter reaches BOTTOM. This allows for the use of overflow interrupts in phase-correct PWM mode. Output compare flags will be set each time the counter reaches the value stored in an output compare register. This allows for the use of output compare interrupts as well.
Phase-correct PWM can be used to generate waveforms on one or more timer/counter output compare pin. When the compare output mode (COMnx) bits are configured to cause the output compare pin(s) to operate in non-inverting mode, the output compare pin(s) will clear on a compare match when incrementing and set on a compare match when decrementing. (The opposite is true in inverting mode.) This makes spikes or glitches in the output less likely (particularly in the case where the value of TOP is changed), and is preferred when operating hardware that can be sensitive to glitches (such as motors).
Similarly to fast PWM mode, if a specific frequency is required that necessitates the use of OCRnA as TOP, then output compare pin B (OCnB) can be used to generate the PWM waveform, with the duty cycle set by the value stored in the OCRnB register. The duty cycle is defined in (9.6.2).
An example phase-correct PWM waveform of this nature is shown in Figure 9.6.6.
Top graph depicts the value stored in a timer/counter over time. It starts at BOTTOM (0) and then increments through OCRnB to OCRnA, which is less than MAX. At OCRnA, the value decrements back to 0. This process repeats several time. The bottom graph depicts the value on the OCnB pin. When the value in the timer/counter is between BOTTOM and OCRnB, the value on the pin is HIGH. When the value in the timer/counter is between OCRnB and OCRnA, the value on the pin is LOW.
Figure 9.6.6. Example of a phase-correct PWM waveform generated on pin OCnB using OCRnA as TOP. The duty cycle is set by the value stored in OCRnB.
When output compare register A (OCRnA) is used as the value of TOP, output compare pin A (OCnA) cannot be used to generate a meaningful PWM waveform. This is because the pin is cleared on a compare match when incrementing, but set on a compare match when decrementing. However, these two events occur simultaneously, and the value on OCnA will always be HIGH.
An exception to this is timer/counter 1, where value stored in ICR1 can be used to define TOP. In this case, the frequency can be precisely tuned using the value of ICR1 and a prescaler. In addition, both output compare pins can have independent duty cycles configured by their corresponding output compare registers, defined by (9.6.3).
If the frequency of the PWM waveform is not as strictly circumscribed, both output compare pins can be used to generate PWM signals in any timer/counter by using MAX as the value of TOP. In timer/counter 1, MAX can be configured to operate in 8-bit mode, 9-bit mode, or 10-bit mode, as described in Table 9.6.2. Both output compare pins will have PWM waveforms of the same frequency, but each duty cycle can independently be configured by the corresponding output compare register, with a duty cycle defined by (9.6.4).
Unlike in fast PWM, there is no glitch that occurs in phase-correct PWM when the output compare register used to set the duty cycle is equal to BOTTOM.

Subsection 9.6.3 Updating TOP Values

The value of TOP can be modified in code; it does not need to be a fixed constant. This allows for the modification of the timer/counter frequency as the code executes. In order to prevent synchronization issues, the output compare A register is double buffered in PWM modes. This means that the CPU will write the new value of TOP to a buffer register and only update the value in OCRnA when a particular timing event occurs (either reaching the previous value of TOP or upon reaching BOTTOM).
This buffering does not occur in CTC mode (or in PWM modes on timer/counter 1 when ICR1 is used to define TOP). If TOP is changed in CTC mode when the timer/counter to a value lower than the previous value of TOP and after the value in TCNTn has already become larger than the new value of TOP, then the timer/counter will increment to MAX (not TOP!) before the new value of TOP will take effect. This can be a particularly long interval of time when using timer/counter 1 and/or when using a large prescaler value.
The presence of the buffer register used with OCRnA is shown in Figure 9.6.7.
The data bus connects bidirectionally to both TCNTn and the OCRnx buffer. The OCRnx buffer writes to OCRnx. OCRnx is an input to the comparator. TCNTn is also an input to the comparator.
Figure 9.6.7. Block diagram of the timer/counter output compare register and the buffer register.
In fast PWM, writing to OCRnA will write to the buffer register. The actual OCRnA register will only be updated the next time the counter reaches a value of TOP. A waveform depicting this phenomenon is shown in Figure 9.6.8. The output waveform is also shown, depicting the change in PWM frequency with changing values of OCRnA.
Top graph shows the value stored in the TCNTn register over time. It starts at BOTTOM and increases through OCRnB to OCRnA (which is less than MAX) then abruptly overflows back to BOTTOM once it reaches OCRnA. This process repeats a second time. The value of OCRnA becomes lower during the second period of incrementing but doesn’t update until the value in TCNTn reaches the old/previous value of OCRnA. The next period to increment between BOTTOM and OCRnA is less than the preceding periods now that TOP has updated. This process repeats. THe value of OCRnA becomes higher during the fourth period of incrementing but doesn’t update until the value in TCNTn reaches the old/previous value of OCRnA. The next period to increment is longer now that TOP has updated. This process repeats. The bottom graph shows the value on the OCnB pin. The value is HIGH when the value in TCNTn is less than OCRnB and LOW when the value in TCNTn is between OCRnB and OCRnA.
Figure 9.6.8. Example of a fast PWM waveform generated on pin OCnB using OCRnA as TOP. The value of OCRnA is changed over time, but only updates when the value in the timer/counter becomes TOP and clears to zero.
The same feature is present in phase-correct PWM. Changes to OCRnA are only updated the next time the counter reaches a value of TOP. This is depicted in Figure 9.6.9.
Top graph shows the value stored in the TCNTn register over time. It starts at BOTTOM and increases through OCRnB to OCRnA (which is less than MAX) then decreases back to BOTTOM. This process repeats a second time. The value of OCRnA becomes lower during the second period of incrementing but doesn’t update until the value in TCNTn reaches the old/previous value of OCRnA. The next period to increment between BOTTOM and OCRnA is less than the preceding periods now that TOP has updated. This process repeats. The value of OCRnA becomes higher during the fourth period of incrementing but doesn’t update until the value in TCNTn reaches the old/previous value of OCRnA. The next period to increment is longer now that TOP has updated. This process repeats. The bottom graph shows the value on the OCnB pin. The value is HIGH when the value in TCNTn is less than OCRnB and LOW when the value in TCNTn is between OCRnB and OCRnA.
Figure 9.6.9. Example of a phase-correct PWM waveform generated on pin OCnB using OCRnA as TOP. The value of OCRnA is changed over time, but only updates when the value in the timer/counter becomes TOP.
When using timer/counter 1, it is possible to use ICR1 as the value of TOP. However, this register is not double buffered. This means that the value in the register will update immediately. In either PWM mode, if the updated value of ICR1 is lower than the previous value, the timer/counter will not make a compare match and will count to MAX (65,535) before beginning the next cycle. Once the next cycle begins, a compare match will occur as expected. However, one cycle of the waveform (or interrupt timing) will be significantly affected. This is depicted with phase-correct PWM in Figure 9.6.10. Because of this issue, it is recommended to use ICR1 only if the value of TOP will remain fixed.
Top graph shows the value stored in the TCNT1 register over time. It starts at BOTTOM and increases through OCR1B to ICR1 (which is less than MAX) then decreases back to BOTTOM. This process repeats a second time. The value of ICR1 becomes lower during the second period of incrementing after the value in TCNT1 is already larger than ICR1. This causes the counter to count to MAX before decrementing back to BOTTOM. The next cycle uses the new value of ICR1 as TOP. The bottom graph shows the value on the OCnB pin. The value is HIGH when the value in TCNTn is less than OCRnB and LOW when the value in TCNTn is between OCRnB and OCRnA.
Figure 9.6.10. Example of a phase-correct PWM waveform generated on pin OC1B using ICR1 as TOP. The value of ICR1 is changed immediately, which may cause timing issues if the value of ICR1 is lower than the value stored in TCNT1.
When the value of TOP is changed in phase-correct PWM mode using OCRnA as TOP, even though the register is double buffered, there is still one issue that can occur when the value of OCRnA is changed. This issue is that waveforms are not completely symmetric about BOTTOM, which may be an issue when working with motors. This issue will be considered in the next section on phase- and frequency-correct PWM.

Subsection 9.6.4 Phase- and Frequency-Correct PWM

Phase- and frequency-correct PWM is much the same as phase-correct PWM, except that the output periods are all symmetrical. This is produced by updating the value of OCRnA on BOTTOM, rather than on TOP. This PWM mode of operation is only available on timer/counter 1.
Because the only difference in operation regards how the value of TOP updates, this mode of operation has the same frequency and duty cycle considerations as phase-correct PWM. The values available for TOP are given in Table 9.6.11.
Table 9.6.11. Sources of TOP for timer/counter1 in phase- and frequency-correct PWM modes.
Timer/counter 0 Timer/counter 1 Timer/counter 2
unavailable OCR1A unavailable
ICR1
Because of the problematic nature of ICR1 not being double buffered (which was explained in Subsection 9.6.3), it is not recommended to use that register as the value for TOP when the value needs to be changed over time. Because this PWM mode of operation is designed to be used in the specific instance when TOP needs to change, it is strongly recommended that any designs using this PWM mode of operation use OCR1A instead of ICR1.
The issue of waveform asymmetry and symmetry is demonstrated in Figure 9.6.12, which depicts a phase-correct PWM signal (top) that is not symmetric around BOTTOM. However, the phase- and frequency-correct PWM signal (bottom) is completely symmetric around BOTTOM.
Top graph shows the value stored in the TCNT1 register over time during phase-correct PWM. It starts at BOTTOM and increases through OCR1B to OCR1A (which is less than MAX) then decreases back to BOTTOM. This process repeats a second time. During this second increment, the value of OCR1A changes to a lower value. OCR1A doesn’t update until the next time it hits the old TOP value, causing the second period to be the same as the first period. The third period reflects the new value of TOP. During the fourth increment, the value of OCR1A increases. The fourth period still reflects the old TOP value. The fifth period increases to reflect the new TOP value. The next graph down shows the value on the OC1B pin. The value is HIGH when the value in TCNT1 is less than OCR1B and LOW when the value in TCNT1 is between OCR1B and OCR1A. The third and fifth square wave signals are not symmetric. The next graph down shows the value stored in the TCNT1 register over time during phase- and frequency-correct PWM. It starts at BOTTOM and increases through OCR1B to OCR1A (which is less than MAX) then decreases back to BOTTOM. This process repeats a second time. During this second increment, the value of OCR1A changes to a lower value. OCR1A updates the next time it hits BOTTOM, causing the second period to be the same as the first period. The third period reflects the new value of TOP. During the fourth increment, the value of OCR1A increases. OCR1A updates when the value hits BOTTOM, which means the fourth period will reflect the new TOP value. The fifth and sixths periods are also depicted with the same new value of TOP. The bottom graph shows the value on the OC1B pin. The value is HIGH when the value in TCNT1 is less than OCR1B and LOW when the value in TCNT1 is between OCR1B and OCR1A. All of the square wave signals are symmetric.
Figure 9.6.12. Example of a phase-correct PWM waveform (top) and phase- and frequency-correct PWM waveform (bottom) generated by timer/counter 1. The phase-correct PWM waveform is not completely symmetric about BOTTOM, but the phase- and frequency-correct PWM waveform is.
If a symmetric waveform is required, and the value of TOP can change over time, then it is recommended to use phase- and frequency-correct PWM counting to a TOP value of OCR1.