6 channel PWM on avr microcontroller. Multichannel software PWM in AVR. Instructions for using PWM in Arduino

In order to understand how you can implement several PWM channels on one controller, let's first remember what PWM is and what it is used for.

PWM stands for Pulse Width Modulation. This is an operating mode when the duty cycle of the pulses can be regulated by a control chip (our controller) according to some rules (in other words, they say that the duty cycle is modulated by something or depending on something). That is, switching from a high signal level to a low one and vice versa is performed at moments of time strictly defined by some rules.

Thus, for one PWM channel we need to know the rules that determine the duty cycle (there are no problems with this, we set them ourselves), and, in addition, count two points in time from the beginning of the pulse: firstly, how long the signal is in the state high level and secondly, the total pulse time. Great, then all we need to implement one PWM is two counters. The algorithm will turn out like this: we start both counters, switch the output to “1”. Upon interruption from the first counter (high level time), we switch the output to “0”, turn off the counter and wait for the interruption from the second counter. Upon interruption from the second counter (total pulse time), we repeat everything from the beginning.

Accordingly, for three PWM channels we need 3*2=6 counters. But, let’s say the PIC12F629 has only 2 counters, what should we do? First, let’s make the total pulse time the same for all PWM channels (let all three channels operate at the same frequency), this is already minus two counters. All that remains is to count the high level time for each of the PWM channels. In total, there are 4 counters left. Not much, but easier.

Now let's remember that the controller is not an analog microcircuit, but a digital one, and it counts the moments of time discretely. All three high-level times (for each of the PWM channels) will be a multiple of some common time quantum. The duration of this quantum is determined by the PWM width and the pulse frequency. In the case when all channels operate at the same frequency and have the same bit depth, this time slice will be equal to: T 1 =1/(f*(2 n -1)), where n is the PWM capacity, f is the pulse frequency.

If the PWM is 8-bit and operates at a frequency of 100 Hz, then the quantum duration is (1/100)/(2 8 -1) = 39 μs - the total pulse time (1/f) divided by the number of possible switching moments (2 n) minus 1 (if you put N points on a straight line, then they form N-1 intervals).

That is, We only need one hardware counter that will count the T 1 intervals. Next, we create a program counter that will count the number of such intervals, and set four settings. One setting determines how many program counter readings are needed to count the high level time for the first PWM channel, the second is the same for the second channel, the third is for the third, the fourth corresponds to the total pulse time, and the operations of comparing, switching, increasing or resetting the program counter we will
do it based on an interrupt from a hardware counter.

The main disadvantage of this method is that instead of (n+1) interrupts per period, we will process (2 n -1) interrupts.

Let's estimate what the maximum PWM frequency could be with such an implementation? Obviously, at the maximum frequency, the controller only has enough time to process the interrupt. That is, the entire time slice T 1 of the controller is busy processing the interrupt; as soon as it exits the interrupt, another thing happens immediately.

If we denote the maximum number of machine cycles for which the subroutine is executed, N max - then, taking into account the expression for T 1, we obtain the equation: N max *4/fosc=1/(f max *(2 n -1)). Hence, the maximum PWM frequency: f max =fosc/(4*N max *(2 n -1)). Naturally, the resulting formula is simply an estimate, because we assumed that the subroutine takes up all the time T 1 , but if after executing the subroutine there is time left to execute 2 or 3 commands, then this, in general, will not suit us much either. What can be done in 3 teams? Normally, if we want to do something else, for example, exchange information with a computer, then the calculated frequency value must be divided by at least another half.

What determines the maximum execution time of an interrupt routine? Well, firstly, of course, it depends on the degree of crookedness of the programmer, and secondly, on the number of PWM channels that we want to implement.

To make it clear what values ​​we are talking about, let’s calculate a specific example: let the controller operate at a frequency of fosc = 4 MHz, we have written a subroutine that runs in a maximum of 40 machine cycles and we want to get a PWM width of 8 bits. Then the maximum PWM frequency will be equal to 4000000/(4*40*255)=98 Hz. As you can see, with this method of implementation, everything is quite limited, but it’s enough for RGB. By the way, with 8 bits per color we get a total number of colors equal to 2 8 * 2 8 * 2 8 = 16 million and in general it’s worth thinking about - do we need that many?

With 2 bits per channel and the same clock frequency, you can get a maximum PWM frequency equal to 4000000/(4*40*3)=8.3 kHz, and there will be 2 2 *2 2 *2 2 =64 different combinations of duty cycles (in the case of RGB this is 64 colors). This frequency can already be used not only for RGB.

Well, that's all for the theory.

Digital devices, for example, a microcontroller can only work with two signal levels, i.e. zero and one or off and on. Thus, you can easily use it to monitor the load status, such as turning an LED on or off. You can also use it to control any electrical device using the appropriate drivers (transistor, triac, relay, etc.). But sometimes you need more than just “turning on” and “turning off” the device. So if you want to control the brightness of an LED (or lamp) or the speed of a DC motor, then digital signals simply can't do it. This situation is very common in digital technology and is called Pulse Width Modulation (PWM).

Almost all modern microcontrollers have specialized hardware for generating a PWM signal. In this tutorial we will learn the basics of PWM technique and later we will see how to implement PWM using AVR microcontrollers.

Digital devices like a microcontroller can only generate two levels on the output lines, high = 5V and low = 0V. But what if we want to get 2.5 or 3.1 or any voltage between 0-5V? To do this, instead of generating a constant DC voltage at the output, we will generate a square wave that has high = 5V and low = 0V levels (see Figure 1).

Fig.1

The figure shows that the signal remains alternately at low and high levels for some time. T0 - low level, T1 - high level. The signal period will be equal to T = T0+T1. Pulse period- this is the time interval between two characteristic points of two adjacent pulses. Typically, the period is measured between two rises or fall of adjacent pulses and is denoted by the capital letter T.

The pulse repetition period is directly related to the frequency of the pulse sequence, and it can be calculated using the formula: T = 1/F

If the pulse length T1 is exactly equal to half the period T, then such a signal is often called a “square wave”.

The duty cycle of pulses is the ratio of the pulse repetition period to their duration and is denoted by the letter S: S = T/T1

Duty factor is a dimensionless quantity and has no units of measurement, but can be expressed as a percentage. The term is often found in English texts Duty cycle, this is the so-called duty cycle or PWM duty cycle value. The duty cycle D is the reciprocal of the duty cycle.

Fill factor usually expressed as a percentage and calculated using the formula: D=1/S or so D = T1/T*100%

In the figure above (Fig. 1) you can see that T1 = T0, this is equal to half the time period. So the PWM duty cycle is 50%. If the frequency of such pulses is high enough (say, 5000 Hz), then we get half of 5V i.e. 2.5V. Thus, if the controller's output is coupled to the motor (using appropriate drivers) it will operate at 50% of its full speed. The PWM technique uses this fact to create any voltage between two levels (for example, between 0-12V). The trick is that when the duty cycle value changes between 0-100%, we get the same percentage of input voltage at the output. Below are some examples of PWM signals with different duty cycles.

If you install an R/C filter at the output, you can get a pure DC signal level rather than square waves. But this is not required for brushed motors or for controlling LED brightness. To do this, you can apply a PWM signal directly to the driver (for example, a bipolar transistor, MOSFET, etc.).


Under 16-bit operating mode. The timer is understood as its counting algorithm and the behavior of the pulse shaper output associated with it, which is determined by a combination of bits that specify the timer operating mode (WGMn3-0) and the output signal generation mode (COMnx1:0). In this case, the bits for setting the output signal generation mode do not affect the counting algorithm, because The counting algorithm depends only on the state of the bits for setting the timer operating mode. In PWM modes, the COMnx1:0 bits allow you to enable/disable inversion on the generated PWM output (i.e. select PWM with inversion or PWM without inversion). For non-PWM modes, the COMnx1:0 bits determine what action to take when a match occurs: reset, set, or invert the output (see also “Output Signal Conditioning Block” and “16-Bit Timer-Counter Timing Diagrams”).

Normal operation

The simplest operating mode is normal mode (WGMn3-0 = 0b0000). In this mode, the counter operates as a summing (incrementing) counter, and the counter is not reset. The counter overflows when passing through the maximum 16-bit. value (0xFFFF) to the lower count limit (0x0000). During normal operation, the timer-counter overflow flag TOVn will be set on the same clock cycle when TCNTn reaches zero.

In fact, the TOVn overflow flag is the 17th bit of the timer-counter, except that it is only set and not cleared. However, this property can be used programmatically to increase the resolution of the timer by using a timer overflow interrupt, upon which the TOVn flag is automatically reset. There are no special situations for normal operation, so a new meter state can be recorded at any time.

In normal mode, you can use the capture block. However, it must be ensured that the maximum time interval between the occurrence of external events does not exceed the counter overflow period. If this condition is not met, it is necessary to use a timer-counter overflow interrupt or a prescaler.

The comparison block can be used to generate interrupts. It is not recommended to use the OCnx output to generate signals in normal operation, because in this case, a significant part of the processor time will be spent.

Match timer reset mode (CTC)

In CTC mode (WGM01, WGM00 =0b10), the OCR0 register is used to set the counter resolution. If CTC mode is set and the counter value (TCNT0) matches the value of the OCR0 register, the counter is reset to zero (TCNT0=0). Thus, OCR0 specifies the top count of the counter, and, consequently, its resolution. This mode provides a wider range of adjustment of the frequency of generated rectangular pulses. It also simplifies the operation of the external event counter.

In timer reset on match mode (WGMn3-0 = 0b0100 or 0b1100), the timer resolution is set by the OCRnA or ICRn registers. In CTC mode, the counter (TCNTn) is reset if its value matches the value of the OCRnA register (WGMn3-0 = 0b0100) or ICRn (WGMn3-0 = 0b1100). The value of the OCRnA or ICRn register determines the upper count limit, and therefore the resolution of the timer. This mode provides a wider range of adjustment of the frequency of generated rectangular pulses. It also simplifies the operation of the external event counter. The timing diagram of the timer operation in CTC mode is shown in Figure 1. The counter (TCNTn) increments its state until a match occurs with the value of OCRnA or ICRn, and then the counter (TCNTn) is reset.

Figure 1 – Timing diagram for STS mode

When the upper count limit is reached, an interrupt can be generated using the OCFnA or ICFn flags corresponding to the registers used to set the upper count limit. If the interrupt is enabled, then the interrupt routine can be used to update the upper count limit. However, setting the count top value close to the count bottom limit value when the counter operates without prescale or with a small prescale value must be done with extreme caution, because There is no double buffering in CTC mode. If the value written to OCRnA or ICRn is less than the current value of TCNTn, the counter will reset when the match condition occurs when it reaches the maximum value (0xFFFF), then resets to 0x0000 and reaches the new value of OCRnA or ICRn. In many cases, this situation is not desirable. An alternative is the fast PWM mode, where the OCRnA register determines the upper count limit (WGMn3-0 = 0b1111), because in this case OCRnA is double buffered.

To generate a signal in CTC mode, the OCnA output can be used to change the logic level on each match by setting the switching mode (COMnA1, COMnA0 = 0b01). The OCnA value will be present on a port pin only if the output direction is specified for that pin. The maximum frequency of the generated signal is fOC0 = fclk_I/O/2 if OCRnA = 0x0000. For other OCRn values, the frequency of the generated signal can be determined by the formula:

where the variable N specifies the prescaler division factor (1, 8, 32, 64, 128, 256 or 1024).

As with normal operation, the TOV0 flag is set at the same timer tick when its value changes from 0xFFFF to 0x0000.

Fast PWM mode

The fast pulse width modulation (PWM) mode (WGMn3-0 = 0b0101, 0b0110, 0b0111, 0b1110, 0b1111) is designed to generate PWM pulses of increased frequency. Unlike other operating modes, this one uses unidirectional counter operation. Counting is performed in the direction from the lower to the upper counting limit.

If a non-inverting output mode is set, then when TCNTn and OCRnx coincide, the OCnx signal is set and reset at the upper counting limit. If inverting mode is specified, the OCnx output is reset on a match and set to the high count limit. Due to the unidirectional counting, the operating frequency for this mode is twice as high as compared to the PWM mode with phase correction, where bidirectional counting is used. The ability to generate high-frequency PWM signals makes the use of this mode useful in tasks of power stabilization, rectification and digital-to-analog conversion. High frequency, at the same time, allows the use of external elements of physically small sizes (inductors, capacitors), thereby reducing the overall cost of the system.

The PWM resolution can be fixed 8, 9 or 10 bits or set by the ICRn or OCRnA register, but not less than 2 bits (ICRn or OCRnA = 0x0003) and no more than 16 bits (ICRn or OCRnA = 0xFFFF). The PWM resolution at a given upper limit value (UL) is calculated as follows:

In fast PWM mode, the counter is incremented until its value matches one of the fixed values ​​0x00FF, 0x01FF or 0x03FF (if WGMn3:0 = 0b0101, 0b0110 or 0b0111, respectively), the value in ICRn (if WGMn3:0 = 0b1110) or the value in OCRnA (if WGMn3:0 = 0b1111) and then reset by the next timer clock tick. The timing diagram for fast PWM mode is shown in Figure 2. The figure shows fast PWM mode when the OCRnA or ICRn register is used to set the upper limit. The TCNTn value in the timing diagram is shown as a function graph to illustrate the unidirectional counting. The diagram shows both inverted and non-inverted PWM outputs. A short horizontal line shows points on the TCNTn graph where the OCRnx and TCNTnx values ​​coincide. The OCnx interrupt flag is set when a match occurs.

Figure 2 – Timing diagram for fast PWM mode

The Timer-Counter Overflow (TOVn) flag is set whenever the counter reaches its high limit. Additionally, the same clock pulse, along with the TOVn flag, can set the OCnA or ICFn flags if the OCRnA or ICRn register is used to set the upper limit, respectively. If one of these interrupts is enabled, then the interrupt routine can update the upper count limit and comparison thresholds.

If the value of the upper count limit changes, then the condition must be met that the new upper limit value written is greater than or equal to the values ​​in all comparison threshold registers. Otherwise, a match between TCNTn and OCRnx will never occur. Note that when using fixed upper limit values, unused bits are masked to 0 when writing to the OCRnx registers.

The ICRn register modification mechanism differs from OCRnA when it is used to set the upper limit. The ICRn register is not double buffered. This means that if a small value is written to ICRn while the counter is running with little or no prescaling, there is a risk of writing a value to the ICRn register that is less than the current value of TCNTn. As a result, in this situation the match at the top of the count will be missed. In this case, the counter will reach its maximum value (0xFFFF), restart at 0x0000, and only then generate a match. The OCRnA register contains a double buffering scheme, so it can be modified at any time.

class="eliadunit">

If a write is made to address OCRnA, the value is actually placed in the OCRnA buffer register. If a match occurs between TCNTn and the top of the count, then the next clock cycle of the timer is the copying of the buffer register to the comparison threshold register OCRnA. The register is updated in the same clock cycle as TCNTn is reset and the TOVn flag is set.

It is recommended to use the ICRn register to set the upper limit if the upper count limit is a constant. In this case, the OCRnA register is also freed to generate a PWM signal at the OCnA output. However, if the PWM frequency changes dynamically (due to changing the upper limit), then in this case it is more advantageous to use the OCRnA register to set the upper limit, because it supports double buffering.

In fast PWM mode, the comparison units allow you to generate PWM signals on the OCnx pins. If COMnx1:0 = 0b10, then PWM is set without output inversion, and if COMnx1:0 = 0b11, then PWM mode with output inversion is set (see Table 59). The actual OCnx value can be observed on the port pin if it is set to output direction (DDR_OCnx). The PWM signal is generated by setting (resetting) the OCnx register when a match occurs between OCRnx and TCNTn, and by resetting (setting) the OCnx register along with resetting the counter (change from high limit to low limit).

The PWM frequency of the output signal for a given upper limit value (UL) is determined by the expression:

where N is a variable that specifies the value of the predivision coefficient (1, 8, 32, 64, 128, 256 or 1024).

Writing limit values ​​to the OCRnx register is associated with special cases in the generation of PWM pulses. If OCRnx is set equal to the lower limit (0x0000), then a short pulse will appear at the output every (VP+1)th clock cycle of the timer. Writing a value equal to the upper limit to OCRnx will result in setting a constant log level. 1 or 0 at the output (depending on the polarity of the output signal selected using the COMnx1:0 bit).

If high-frequency square wave generation (rectangular pulses with a duty cycle of 2 or 50% fill) is required, then it is necessary to use the fast PWM mode with the bits COMnA1:0 = 0b01 set, which causes the logic level at the OCnA output to switch (invert) on each match. This is only applicable if OCRnA is used to set the upper limit (WGMn3-0 =0b1111). The maximum generated square wave frequency in this case is fOCnA = fclk_I/O/2, if OCRnA = 0x0000. This feature is similar to OCnA switching in CTC mode, with the exception of double buffering, which is present in fast PWM mode.

Pulse width modulation mode with phase correction (Phase Correct)

Phase-corrected pulse width modulation (PWM FC) mode (WGMn3-0 = 0b0001, 0b010, 0b0011, 0b1010 or 0b1011) is designed to generate a phase-corrected PWM signal with high resolution. The PWM FC mode is based on the bidirectional operation of a timer-counter. The counter cycles from the low limit (0x0000) to the high limit and then back from the high limit to the low limit. If the pulse shaper output mode is set to non-inverting, the OCnx output is reset/set when the TCNTn and OCRnx values ​​match during up/down counting. If the inverting output mode is set, then, on the contrary, during direct counting, the setting occurs, and during reverse counting, the OCnx output is reset. With bidirectional operation, the maximum frequency of the PWM signal is less than with unidirectional operation, however, due to such features as symmetry in PWM modes with bidirectional operation, these modes are preferred to be used when solving drive control problems.

The PWM resolution in this mode can be either fixed (8, 9 or 10 bits) or set using the ICRn or OCRnA register. The minimum resolution is 2 bits (ICRn or OCRnA = 0x0003), and the maximum is 16 bits (ICRn or OCRnA = 0xFFFF). If an upper limit is specified, then the PWM resolution in this mode is determined as follows:

In PWM FC mode, the counter is incremented until it reaches one of the fixed values ​​0x00FF, 0x01FF or 0x03FF (respectively for WGMn3-0 = 0b0001, 0b0010 or 0b0011), as well as a value equal to ICRn (if WGMn3-0 = 0b1010) or OCRnA (if WGMn3 :0 = 0b1011). Further, when the upper limit is reached, the counter changes the counting direction. The TCNTn value remains at the upper limit for one timer clock cycle. The timing diagram for PWM PC mode is shown in Figure 3. The figure shows PWM PC mode using the OCRnA or ICRn register to set the upper limit. The TCNTn state is represented as a function graph to illustrate bidirectional counting. The figure shows both non-inverted and inverted PWM output. Short horizontal lines indicate points on the TCNTn graph where a match with the OCRnx value occurs. The OCnx interrupt flag is set when a match occurs.

Figure 3 – Timing diagram for PWM FC mode

The Timer-Counter Overflow (TOVn) flag is set whenever the counter reaches its lower limit. If the OCRnA or ICRn register is used to set the upper limit, then the OCnA or ICFn flag is set accordingly with the same clock pulse at which the OCRnx register was updated from the buffer register (at the top of the count). Interrupt flags can be used to generate an interrupt when a counter reaches a low or high limit.

When changing the value of the upper count limit, you must ensure that it is greater than or equal to the values ​​in all comparison registers. Otherwise, a match between TCNTn and OCRnx will never occur. Note that when using fixed upper count values, unused bits are cleared to zero when writing to the OCRnx registers. The third period in Figure 53 illustrates the case when a dynamic change in the upper count limit leads to the generation of an asymmetrical pulse. This feature is based on the update time of the OCRnx register. Since the OCRnx update occurs at the top of the count, the PWM period begins and ends at the top of the count. This implies that the countdown duration is determined by the previous upper limit value, and the forward counting duration is determined by the new upper limit value. If these two values ​​are different, then the duration of the forward and backward counting will also be different. The difference in duration leads to asymmetry of the output pulses.

If the task is to change the upper limit while the counter is running, then instead of this mode it is recommended to use the PWM PFC mode (phase and frequency correction). If a static upper limit value is used, then there are practically no differences between these modes.

In PWM FC mode, comparison units allow you to generate PWM signals at the OCnx pins. If you set COMnx1:0 = 0b10, then the PWM output will be without inversion, and if COMnx1:0=0b11, then with inversion. The actual value of OCnx can be observed on the port pin if the data direction register for that port pin is set to output direction (DDR_OCnx). The PWM signal is generated by setting (resetting) the OCnx register when the values ​​of OCRnx and TCNTn match during upcount, and by resetting (setting) the OCnx register when there is a match between OCRnx and TCNTn during downcount. The resulting frequency of the PWM signal in PWM FC mode at a given upper limit (UL) can be calculated using the following expression:

Writing limit values ​​to the OCRnx register is associated with special cases in the generation of PWM signals in the PWM FC mode. If you set the PWM mode without inversion and set OCRnx equal to the lower limit, then the output will be continuously set to log. 0, and if equal to the upper limit, then a log is always present at the output. 1. For PWM with inversion, the indicated levels must be replaced with the opposite ones.

If you specify to use OCnA as the upper limit (WGMn3:0 = 0b1011) and set COMnA1:0 =0b01, a square wave will be generated at the OCnA output.

Pulse width modulation mode with phase and frequency correction (Phase and Frequency Correct)

The pulse-width modulation mode with phase and frequency correction (PWM PFC) (WGMn3-0 = 0b1000 or 0b1001) is designed to generate high-resolution PWM pulses with phase and frequency correction. Just like the PWM FC mode, the PWM FC mode is based on the bidirectional operation of the counter. The counter cycles from the low limit (0x0000) to the high limit and then back from the high limit to the low limit. If the non-inverting PWM mode is specified, the OCnx output is cleared if a match occurs between TCNTn and OCRnx during upcount, and set if a match occurs during downcount. In inverting mode the operation is inverse. Bidirectional operation, compared to unidirectional operation, is associated with the generation of lower frequencies. However, due to the symmetry in PWM modes with bidirectional counting, their use is preferable in drive control tasks.

The main difference between the PWM FC and PWM FC modes is the moment the OCRnx register is updated from the OCRnx buffer register (see Figure 3 and Figure 4).

The PWM resolution in this mode can be set using the ICRn or OCRnA register. The minimum resolution is 2 bits (ICRn or OCRnA = 0x0003), and the maximum resolution is 16 bits (ICRn or OCRnA = 0xFFFF). The PWM resolution in bits can be calculated using the following expression:

In PWM FCC mode, the counter is incremented until it matches the value in ICRn (WGMn3:0 = 0b1000) or in OCRnA (WGMn3:0 = 0b1001). This means reaching the top of the count, after which the direction of the count changes. The value of TCNTn remains at the top of the count for one timer clock cycle. The timing diagram for the PWM FCC mode is shown in Figure 54. The figure shows the PWM FCC mode when the counting top is set by the OCRnA or ICRn register. The TCNTn value is shown as a function graph to illustrate the bidirectional counting. The diagram shows both non-inverting and inverting PWM outputs. Short horizontal lines indicate points on the TCNTn plot where a match between OCRnx and TCNTn occurs. The OCnx interrupt flag is set after a match occurs.

Figure 4 – Timing diagram of PWM mode with phase and frequency correction

The timer-counter overflow flag (TOVn) is set at the same clock cycle when the registers are updated with the value from the buffer register (at the lower counting limit). If the OCRnA or ICRn register is used to set the upper limit, then when the counter reaches the upper limit, the OCnA or ICFn flag is set, respectively. Interrupt flags can be used to generate an interrupt when a counter reaches a high or low limit.

When changing the upper limit, you must ensure that the new value is greater than or equal to the values ​​in all comparison threshold registers. Otherwise, if the upper limit is set to a value less than any of the values ​​in the comparison threshold registers, a match between TCNTn and OCRnx will never occur.

Figure 4 shows that, unlike the PWM FC mode, the generated output signal is symmetrical at all periods. Since the OCRnx registers are updated at the lower counting limit, the durations of the forward and backward counts are always equal. As a result, the output pulses have a symmetrical shape and, therefore, a corrected frequency.

Using the ICRn register to set the upper limit is recommended if the upper limit value is a constant. In this case, the OCRnA register is also freed for pulse width modulation of the pulses at the OCnA pin. However, if you need to dynamically change the PWM frequency by changing the upper limit, then it is recommended to use the OCRnA register to set the upper limit due to its double buffering.

In PWM mode, the comparison units allow you to generate PWM pulses at the OCnx pin. If COMnx1:0 = 0b10, then a non-inverting PWM output is set, and if COMnx1:0=0b11, then an inverting one (see table 60). The OCnx value will only be present on the corresponding port pin if it is set to output direction. The PWM signal is generated by setting (resetting) the OCnx register on a match between OCRnx and TCNTn during upcount and resetting (setting) the OCnx register on a match between OCRnx and TCNTn during downcount. The PWM frequency in this mode with a given upper limit (UP) of counting is determined as follows:

where N is the prescaler division factor (1, 8, 32, 64, 128, 256 or 1024).

Writing limit values ​​to the OCRnx register is associated with special cases in the generation of PWM signals in this mode. If you set OCRnx equal to the lower limit (0x0000), then in non-inverting mode the output will constantly have a low logic level, and when writing a value equal to the upper limit, the output will have a high logic level for a long time. In inverting mode, the given levels will be opposite.

If OCRnA is used to set the upper limit (WGMn3:0 = 0b1001) and COMnA1:0 = 0b01, then a square wave will be generated at the OCnA output.


Hardware implementation of PWM provides undoubted advantages over software, since it relieves the processor of both unnecessary and cumbersome code and time for its maintenance, and also provides more opportunities for using work with PWM. It is enough to initialize the timer/counter (enter the necessary values ​​into the registers used by the timer/counter) and the timer/counter can work independently of the processor; accordingly, the processor can deal with other tasks, only occasionally contacting at the necessary moment to adjust or change the mode or obtain results from the timer /counter.

Description of interrupt flags

T1 can generate an interrupt when:

  1. counter register TCNT1 overflow;
  2. if the counting register TCNT1 and the comparison register OCR1A and OCR1B are equal (separately for each register);
  3. while storing the counting register in the capture register ICR1.

T2 can generate an interrupt when:

  1. overflow of the TCNT2 counter register;
  2. when the counting register TCNT2 and the comparison register OCR2 are equal.

The flags of all interrupts are in the TIFR register, and interrupt enable/disable is in the TIMSK register.

TIMSK register bits
Register7 6 5 4 3 2 1 0
TIMSK OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 OCIE0* TOIE0
  • OCIE2- Interrupt enable flag for the “match” event of the timer/counter T2
  • TOIE2- T2 timer/counter overflow interrupt enable flag
  • TICIE1- Interrupt enable flag for the “capture” event of the timer/counter T1
  • OCIE1A- Interrupt enable flag for the “match A” event of the timer/counter T1
  • OCIE1B- Interrupt enable flag for the “coincidence B” event of the timer/counter T1
  • TOIE1- T1 timer/counter overflow interrupt enable flag
  • OCIE0*- Interrupt enable flag for the “coincidence” event of the timer/counter T0 (* - not available in ATmega8)
  • TOIE0- Timer/counter overflow interrupt enable flag T0
  • OCF2- Interrupt flag for the “coincidence” event of the timer/counter T2
  • TOV2- Timer/counter overflow interrupt flag T2
  • ICF1- Interrupt flag for the “capture” event of the timer/counter T1
  • OCF1A- Interrupt flag for the event "coincidence A" of the timer/counter T1
  • OCF1B- Interrupt flag for the event "coincidence B" of the timer/counter T1
  • TOV1- Timer/counter overflow interrupt flag T1
  • OCF0- Interrupt flag for the “coincidence” event of the timer/counter T0
  • TOV0- Timer/counter overflow interrupt flag T0

Description of the operation of the timer/counter T1 in the ATmega8/16 controller

The sixteen-bit timer/counter T1 can be used to generate time intervals, count the number of external signals, and generate PWM signals of varying duty cycles and durations on pins OC1A and OC1B. In addition, by an external signal from the ICP1 pin or from an analog comparator, T1 can save its current state in a separate capture register ICR1.

Register bits TCCR1A:TCC1B:TCNT1:OCR1A:OCR1B:ICR1
Register7 6 5 4 3 2 1 0
TCCR1A COM1A1 COM1A0 COM1B1 COM1BO FOC1A FOC1B WGM11 WGM10
TCCR1B ICNC1 ICES1 * WGM13 WGM12 CS12 CS11 CS10
TCNT1:H R/W R/W R/W R/W R/W R/W R/W R/W
TCNT1:L R/W R/W R/W R/W R/W R/W R/W R/W
OCR1A:H R/W R/W R/W R/W R/W R/W R/W R/W
OCR1A:L R/W R/W R/W R/W R/W R/W R/W R/W
OCR1B:H R/W R/W R/W R/W R/W R/W R/W R/W
OCR1B:L R/W R/W R/W R/W R/W R/W R/W R/W
ICR1:H R/W R/W R/W R/W R/W R/W R/W R/W
ICR1:L R/W R/W R/W R/W R/W R/W R/W R/W

Each 16-bit register is physically located in two 8-bit registers, so when reading an entry in them, two operations must be performed. When writing, the high byte is loaded first, then the low byte; when reading, on the contrary, the low byte is read first, then the high byte.

TCCR1A:TCCR1B- 8-bit timer/counter control registers T1

TCNT1- 16-bit timer/counter register T1. Depending on the operating mode, the contents of this register are cleared, incremented (the value is increased by 1), or decremented (the value is decreased by 1) for each pulse of the timer/counter clock signal.

OCR1A:OCR1B- 16-bit comparison registers

ICR1- 16-bit capture register, stores the value of TCNT1 when an active signal edge is applied to the ICP1 pin or by a signal from the comparator.

Bit assignment

COM1A1:COM1A0:COM1B1:COM1B0- These bits determine the behavior of the OC1A:OC1B pin when the value of the TCNT1 counting register and the OCR1A:OCR1B comparison register match

FOC1A:FOC1B- These bits are used to force a change in the state of pin OC1A:OC1B

ICNC1- Interference circuit control bit, if the bit is “0” the capture will be on the first active edge, if “1” the capture will be after the fourth identical sample of the capture signal.

ICES1- Bit for selecting the active edge of the signal, if its value is “0”, saving the counting register TCNT1 in the capture register OCR1 will be on the falling edge of the signal, if “1” on the rising edge.

WGM13:WGM12:WGM11:WGM10- These bits determine the operating mode of the timer/counter T1

CS22:CS21:C20- Bits that determine the source of the T1 timer/counter clock signal.

Selecting the operating mode of the timer/counter T1
WGM13WGM12WGM11WGM10Operating modeAccount module (TOP)
0 0 0 0 Normal $FFFF
0 0 0 1 Phase correct PWM

8-bit

$00FF
0 0 1 0 Phase correct PWM

9-bit

$01FF
0 0 1 1 Phase correct PWM

10-bit

$03FF
0 1 0 0 CTC (reset on match) OCR1A
0 1 0 1 Fast PWM

8-bit

$00FF
0 1 1 0 Fast PWM

9-bit

$01FF
0 1 1 1 Fast PWM

10-bit

$03FF
1 0 0 0 ICR1
1 0 0 1 Phase and Frequency Correct PWM OCR1A
1 0 1 0 Phase correct PWM ICR1
1 0 1 1 Phase correct PWM OCR1A
1 1 0 0 CTC (reset on match) ICR1
1 1 0 1 Reserved *
1 1 1 0 Fast PWM ICR1
1 1 1 1 Fast PWM OCR1A

Selecting a Clock Source

Normal mode

The simplest operating mode is T1. For each pulse of the clock signal, the counting register TCNT1 is incremented (the value increases by 1). When passing through the value $FFFF of the counting module (TOP), an overflow occurs and the next clock cycle begins counting from the value $0000, at the same moment the TOV1=1 flag is set in the TIFR register, and an interrupt can be generated if the TOIE1=1 flag is set in the TIMSK register. In order to generate a signal of a given frequency in this mode, it is necessary to write in the bits COM1A1=0:COM1A0=1 for the OC1A output or COM1B1=0:COM1B0=1 for the OC1B output of the controller.

In addition, for each clock cycle, a comparison is made between the counting register TCNT1 and the comparison register OCR1A:OCR1B, if there is a match, the interrupt flag OCF1A=1:OCF1B=1 is set and if the bit OCIE1A=1:OCIE1B=1 of the TIMSK register, an interrupt is generated. At the same time, the state of the OC1A:OC1B pin can be changed depending on the settings of the COM1A1:COM1A0:COM1B1:COM1B0 bits.

CTC mode (reset on match)

In this mode, T1 works on the same principle as in Normal mode. The difference is that the maximum possible value of the counting register TCNT1 is limited by the value of the comparison register OCR1A or ICR1 (see the timer/counter mode selection table). When TCNT1 reaches the value of OCR1A or ICR1, the value of TCNT1 is reset to TCNT1=$0000. At the same time, the TOV1=1 flag is set COM1A1:COM1A0:COM1B1:COM1B0 Determines the behavior of the OC1A:OC1B pin when there is a match.

Fast PWM mode (fast PWM)

Using this mode, you can generate a high-frequency PWM signal. The principle and procedure of operation does not differ from the Normal mode, except for the presence of double buffering of the OCR1A:OCR1B register, which eliminates the appearance of asymmetrical signal pulses, and also differs in the behavior of the OC1A:OC1B pins (see table).


Phase Correct PWM mode

The difference between this mode and the previous ones is that the counting register operates as a reverse counter. Since this mode is recommended by Atmel as the most suitable for tuning engines, we will consider it in more detail. When the counting register TCNT1 reaches the value of the counting modulus (TOP) (or the value of the ICR1 register or the value of the OCR1A register, see the timer/counter mode selection table), the counting direction changes. When the counting register TCNT1 reaches the minimum value ($0000), the counting direction also changes and at the same time the interrupt flag TOV1 of the TIFR register is set. Also, if the contents of the counting register TCNT1 and the comparison register OCR1A:OCR1B are equal, the OCF1A:OCF1B flag of the TIFR register is set and the state of the OC1A:OC1B output changes, according to the table.

To avoid asymmetrical emissions when writing a value to the OCR1A:OCR1B register, double write buffering is implemented in this mode. Thanks to this, the actual change in the register value changes at the moment the counter register TCNT1 reaches the value of the counting modulus (TOP) (or the value of the ICR1 register or the OCR1A register value, see the timer/counter mode selection table). Therefore, at the very beginning, when the timer/counter is initialized, the OC1A:OC1B pin will not change its state upon matching until the register reaches the value (TOP).


Task: Let's develop a program to control the brightness of a 12 Volt incandescent lamp using PWM. When you press the “More” button, the brightness of the lamp increases, and when you click on the “Less” button, the brightness decreases. The diagram of our future device is shown in the figure. As usual, we use the Atmega8 microcontroller, which will be clocked from an internal oscillator with a frequency of 4 MHz. Actually, we will get a dimmer; these devices are designed to adjust the brightness of lighting fixtures. Nowadays, LED dimmers are the most widespread.

For simplicity, you can also connect an LED to our circuit, but it will be more clear with a light bulb. Buttons are connected to pins PD0, PD1. We connect the load to the output PB1(OC1A) through a resistor and a MOSFET field-effect transistor, which will work as a key for us (in switching mode). A field-effect transistor is preferable because its gate is isolated from the power circuit and is controlled by an electric field, and the control current reaches microamps. This allows, using one or two transistors, to control a load of enormous power (up to tens of amperes and tens or hundreds of volts) without loading the microcontroller. Taking into account also the fact that field-effect transistors can be connected in parallel (unlike bipolar ones), it is possible to obtain an even more powerful cascade of hundreds of amperes.

Now let's figure out how the microcontroller implements PWM and write a program. As mentioned earlier, our MK has 3 timers, and all of them can operate in PWM mode. We will be working with a sixteen-bit timer/counter. Bits WGM13-10 let's configure our timer to work FastPWM with an upper count limit ICR1. The principle of the program is this: our timer counts from 0 to 65535(0xFFFF), into the register ICR1 Let's enter the number 255, this will be the upper limit of the timer count (TOP), the frequency of the PWM signal will be constant. Also, our timer is configured so that if the counting register and the comparison register match (TCNT1 = OCR1A), the controller output will switch OC1A. The PWM duty cycle can be changed by writing to the comparison register OCR1A a certain number from 0 to 255, the larger this number, the greater the fill factor, the brighter the lamp will burn. Depending on which button is pressed the variable changes i, and then it is written to the register OCR1A.

The full text of the program is presented below. The comments describe the operation of the program in more detail.

/***Lesson No. 8. Generating PWM signals***/ #include #include int main(void) ( unsigned int i=0; //define variable i /***Configuring I/O ports***/ PORTB = 0x00; DDRB |= (1<< PB1); PORTD |= (1 << PD1)|(1 << PD0); // подключаем внутренние нагрузочные резисторы DDRD = 0x00; /***Настройка таймера***/ TCCR1A |= (1 << COM1A1)|(0 << COM1A0) // Установим биты COM1A1-COM1A0:0b10, означает сброс вывода канала A при сравнении |(1 << WGM11)|(0 << WGM10); // Установим биты WGM13-10:0b1110, согласно таблице это TCCR1B |= (1 << WGM13)|(1 << WGM12) // будет режим - FAST PWM, где верхний предел счета задается битом ICR1 |(0 << CS12)|(0 << CS11)|(1 << CS10); // Битами CS12-10:0b001 задаем источник тактового сигнала для таймера МК, включен без делителя TCNT1 = 0x00; // начальная установка счетчика ICR1 = 0xFF; // задаем период ШИМ, здесь у нас число 255, // по формуле fPWM=fclk_I/O/N*(1+ICR1)// вычисляем частоту ШИМ, она будет равна 15625 Hz OCR1A = 0x00; // начальный коэффициент заполнения ШИМ /***Основной цикл программы***/ while(1) { if((PIND&(1 << PD0)) == 0) //если кнопка "больше" нажата { if (i < 254) { // коэффициент заполнения ШИМ изменяется от 0 до 255 i=i+1; // увеличиваем i на единицу OCR1A = i; // записываем переменную в регистр сравнения _delay_ms(30); // задержка 30ms } } if((PIND&(1 << PD1)) == 0) //если кнопка "меньше" нажата { if (i >0) // PWM duty cycle changes from 255 to 0 ( i--; // decrease i by one (you can also write this) OCR1A = i; // write a variable to the comparison register _delay_ms(30); // delay 30ms ) ) ) )

Attention! First, we supply power to the microcontroller, then you need to make sure that the transistor is connected to the MK pin, and only then supply power to the circuit with the lamp and the field-effect transistor. Otherwise you may burn the transistor. The fact is that when turned off, the “legs” of the MK “dangle in the air” - they are not connected to anything, and interference occurs on them. These weak interferences are enough to partially open a very sensitive field-effect transistor. Then its resistance between drain and source will drop from several MOhms to several Ohms or fractions of Ohms and a large current will flow through it to the lamp. But the transistor will not open completely, because for this you need to apply not 1-3 V interference to the gate, but a stable 5 V, and its resistance will be much greater than the minimum. This will lead to the release of a large amount of heat on it, and it will smoke and possibly burn.

Pulse width modulation (PWM) is a signal conversion method in which the pulse duration (duty factor) changes, but the frequency remains constant. In English terminology it is referred to as PWM (pulse-width modulation). In this article we will look in detail at what PWM is, where it is used and how it works.

Application area

With the development of microcontroller technology, new opportunities have opened up for PWM. This principle has become the basis for electronic devices that require both adjusting output parameters and maintaining them at a given level. The pulse-width modulation method is used to change the brightness of light, the rotation speed of motors, as well as in controlling the power transistor of pulse-type power supplies (PSUs).

Pulse width (PW) modulation is actively used in the construction of LED brightness control systems. Due to low inertia, the LED has time to switch (flash and go out) at a frequency of several tens of kHz. Its operation in pulse mode is perceived by the human eye as a constant glow. In turn, the brightness depends on the duration of the pulse (open state of the LED) during one period. If the pulse time is equal to the pause time, that is, the duty cycle is 50%, then the brightness of the LED will be half of the nominal value. With the popularization of 220V LED lamps, the question arose of increasing the reliability of their operation with an unstable input voltage. The solution was found in the form of a universal microcircuit - a power driver operating on the principle of pulse width or pulse frequency modulation. A circuit based on one of these drivers is described in detail.

The mains voltage supplied to the input of the driver chip is constantly compared with the in-circuit reference voltage, generating a PWM (PWM) signal at the output, the parameters of which are set by external resistors. Some microcircuits have a pin for supplying an analog or digital control signal. Thus, the operation of the pulse driver can be controlled using another PHI converter. It is interesting that the LED does not receive high-frequency pulses, but a current smoothed by the inductor, which is a mandatory element of such circuits.

The large-scale use of PWM is reflected in all LCD panels with LED backlighting. Unfortunately, in LED monitors, most PWB converters operate at a frequency of hundreds of Hertz, which negatively affects the vision of PC users.

The Arduino microcontroller can also operate in PWM controller mode. To do this, call the AnalogWrite() function, indicating in parentheses the value from 0 to 255. Zero corresponds to 0V, and 255 to 5V. Intermediate values ​​are calculated proportionally.

The widespread proliferation of devices operating on the PWM principle has allowed humanity to move away from linear-type transformer power supplies. The result is an increase in efficiency and a several-fold reduction in the weight and size of power supplies.

A PWM controller is an integral part of a modern switching power supply. It controls the operation of a power transistor located in the primary circuit of the pulse transformer. Due to the presence of a feedback circuit, the voltage at the output of the power supply always remains stable. The slightest deviation of the output voltage is detected through feedback by a microcircuit, which instantly corrects the duty cycle of the control pulses. In addition, a modern PWM controller solves a number of additional tasks that help increase the reliability of the power supply:

  • provides a soft start mode for the converter;
  • limits the amplitude and duty cycle of control pulses;
  • controls the input voltage level;
  • protects against short circuits and overtemperature of the power switch;
  • if necessary, switches the device to standby mode.

Operating principle of a PWM controller

The task of the PWM controller is to control the power switch by changing control pulses. When operating in switching mode, the transistor is in one of two states (fully open, completely closed). In the closed state, the current through the p-n junction does not exceed several μA, which means that the power dissipation tends to zero. In the open state, despite the high current, the resistance of the pn junction is extremely low, which also leads to insignificant thermal losses. The greatest amount of heat is released at the moment of transition from one state to another. But due to the short transition time compared to the modulation frequency, the power losses during switching are insignificant.

Pulse width modulation is divided into two types: analog and digital. Each type has its own advantages and can be implemented in different circuitry ways.

Analog PWM

The operating principle of an analog PWM modulator is based on comparing two signals whose frequencies differ by several orders of magnitude. The comparison element is an operational amplifier (comparator). A sawtooth voltage of a high constant frequency is supplied to one of its inputs, and a low-frequency modulating voltage with variable amplitude is supplied to the other. The comparator compares both values ​​and generates rectangular pulses at the output, the duration of which is determined by the current value of the modulating signal. In this case, the PWM frequency is equal to the frequency of the sawtooth signal.

Digital PWM

Pulse width modulation in digital interpretation is one of the many functions of a microcontroller (MCU). Operating exclusively with digital data, the MK can generate either a high (100%) or low (0%) voltage level at its outputs. However, in most cases, to effectively control the load, the voltage at the MC output must be changed. For example, adjusting the engine speed, changing the brightness of the LED. What should I do to get any voltage value in the range from 0 to 100% at the microcontroller output?

The issue is solved by using the pulse-width modulation method and using the phenomenon of oversampling, when the specified switching frequency is several times higher than the response of the controlled device. By changing the duty cycle of the pulses, the average value of the output voltage changes. As a rule, the entire process occurs at a frequency of tens to hundreds of kHz, which allows for smooth adjustment. Technically, this is implemented using a PWM controller - a specialized microcircuit that is the “heart” of any digital control system. The active use of PWM-based controllers is due to their undeniable advantages:

  • high signal conversion efficiency;
  • stability of work;
  • saving energy consumed by the load;
  • low cost;
  • high reliability of the entire device.

You can receive a PWM signal at the microcontroller pins in two ways: hardware and software. Each MK has a built-in timer that is capable of generating PWM pulses at certain pins. This is how hardware implementation is achieved. Receiving a PWM signal using software commands has more possibilities in terms of resolution and allows you to use a larger number of pins. However, the software method leads to a high load on the MK and takes up a lot of memory.

It is noteworthy that in digital PWM the number of pulses per period can be different, and the pulses themselves can be located in any part of the period. The output signal level is determined by the total duration of all pulses per period. It should be understood that each additional pulse is a transition of the power transistor from an open state to a closed state, which leads to an increase in losses during switching.

Example of using a PWM regulator

One of the options for implementing a PWM simple regulator has already been described earlier in. It is built on a microcircuit and has a small harness. But, despite the simple design of the circuit, the regulator has a fairly wide range of applications: circuits for controlling the brightness of LEDs, LED strips, adjusting the rotation speed of DC motors.

Read also

PWM- Pulse width modulation
PWM- Pulse Width Modulation (i.e. the same as PWM)

What is PWM and why is it needed?

Why do you need software PWM?

Then, on the AVR (Atmega) itself there are 1-2 shim channels, which is often not enough for what is needed.

Let us have 3 (three) LEDs and we want to control the brightness of each of them individually. The built-in PWM timer channels are not enough. And, in general, maybe we still want to exercise some special control over each of them. Therefore, we put them on normal legs (in the PORTC example, legs 3,4,5) and control them programmatically.

Additional information about the connection: http://www.radiokot.ru/start/mcu_fpga/avr/05/ and in the datasheet for the controller.

Calculation of a resistor for an LED:

Power: 5V. The voltage drop across the LED can be considered 1.5V. The current on the LED should be no more than 20mA (some will argue that 15mA is needed, but I like it brighter).
According to Ohm's law: I=U/R, R=U/I=(5-1.5)/0.02=175 Ohm. I installed resistors R1, R2 and R2 - 220 Ohms.

Algorithm

The simplest option is an eternal cycle. The option with interruption will be later (below), now let's look at a simple example to understand the essence.

Firstly, you need to determine two things: at what frequency the LEDs will blink so that this blinking is not visible and, secondly, how many brightness levels the LED can have.

In terms of brightness levels, let it be 256. 0 - completely off, 255 - completely on (i.e. the PWM channel is in logical one all the time, i.e. duty cycle = 100%.

However, now I will confuse you a little.

The point is that we have the PLUS of the diode in the circuit connected directly to the power supply, and the minus goes through the resistor to the leg (where the resistor is does not matter, what matters is what is to the MK leg). Therefore, the LED lights up when the level on the MK leg is low, i.e. zero, i.e. the leg inside the MK is thrown to GND, i.e. to the ground. This means that the 0s and 1s in the PWM must actually be inverted. Those. The longer the signal contains 0s relative to 1s, the brighter the diode will be.

And so, there are 256 brightness levels.

What kind of blinking are we talking about? The bottom line is that if we must apply a PWM signal to many many diodes and do this sequentially to each, then after outputting the signal to the first diode we must return to outputting the signal to it in such a time that:

  1. have time to generate a full-fledged PWM signal,
  2. no more than 1/25 of a second has passed, otherwise the LED will blink noticeably,
  3. There were no noticeable pauses in PWM generation between segments of the PWM signal, i.e. so that the PWM signal IS NOT DISTORTED.

Here is an example of PWM signal distortion:

We will keep all this in mind, but in fact it is not important to us here, since we will have a very simple smooth flasher and it will only change the brightness, i.e. there will be plenty of time, and the task is so simple that it will not eat up time from generating the PWM signal.

And so, here is the source code (for AVR studio, i.e. gcc):

#define F_CPU 1000000UL #include #include #define LEDS_N 3 #define LEDS_PORT PORTC #define LEDS_DDR DDRC int main() ( register unsigned char scancounter=0; register unsigned char i; register unsigned char glow=0; unsigned char level=(0,16,32); // which part of all cycles the led is ON unsigned char ledbits=(0b00001000,0b00010000, 0b00100000); // set C5 direction - output LEDS_DDR=0b11111111; // turn off all leds LEDS_PORT=0b11111111; main pwm part for (i=0;i =level[i])( // off - turn on the pin LEDS_PORT|=ledbits[i]; ) else ( // on - turn off he pin LEDS_PORT&=~ledbits[i]; ) ) scancounter++; // led brightness change if (!scancounter)( for (i=0;i

128)level[i]=0;

) ) ) )

Below in the program we control the brightness level of the diode so that there is some kind of demonstration. With each counter overflow, 1 is added to the brightness of all diodes, but if the brightness becomes more than 128, then it is reset to 0. In general, if this check had not existed, then after reaching the brightness level of 255 it would have reset to zero, but experience has shown that after a brightness of 128 it increases so imperceptibly that we can assume that at a value of 128 it is already almost the maximum. And so that the resulting effect is more dynamic, this check was introduced.

You should also know that the dependence of brightness on current for LEDs is NOT LINEAR. Those. 128 is not twice as dim as 255 and not twice as bright as 64.

How long it takes to turn the entire cycle with all the diodes is of little interest to us here, since it is clear that at a purity of 1 MHz (that’s where my MK works), it will be fast enough for the eye not to see any flickering.

Assembly photo:


click on photo to enlarge

And here is a video of the work: (avi, divx, 3MB)
The video does not show the brightness transition process well, since the camera matrix does not have the same visual inertia as the human eye, but, in general, the process is visible.

Fig.1

T = T0+T1. Pulse period

T = 1/F

S = T/T1

Duty cycle

Fill factor D=1/S or so D = T1/T*100%

Digital devices, for example, a microcontroller can only work with two signal levels, i.e. zero and one or off and on. Thus, you can easily use it to monitor the load status, such as turning an LED on or off. You can also use it to control any electrical device using the appropriate drivers (transistor, triac, relay, etc.). But sometimes you need more than just “turning on” and “turning off” the device. So if you want to control the brightness of an LED (or lamp) or the speed of a DC motor, then digital signals simply can't do it. This situation is very common in digital technology and is called Pulse Width Modulation (PWM).

Almost all modern microcontrollers have specialized hardware for generating a PWM signal. In this tutorial we will learn the basics of PWM technique and later we will see how to implement PWM using AVR microcontrollers.

Digital devices like a microcontroller can only generate two levels on the output lines, high = 5V and low = 0V. But what if we want to get 2.5 or 3.1 or any voltage between 0-5V? To do this, instead of generating a constant DC voltage at the output, we will generate a square wave that has high = 5V and low = 0V levels (see Figure 1).

Fig.1

The figure shows that the signal remains alternately at low and high levels for some time. T0 - low level, T1 - high level. The signal period will be equal to T = T0+T1. Pulse period- this is the time interval between two characteristic points of two adjacent pulses. Typically, the period is measured between two rises or fall of adjacent pulses and is denoted by the capital letter T.

The pulse repetition period is directly related to the frequency of the pulse sequence, and it can be calculated using the formula: T = 1/F

If the pulse length T1 is exactly equal to half the period T, then such a signal is often called a “square wave”.

The duty cycle of pulses is the ratio of the pulse repetition period to their duration and is denoted by the letter S: S = T/T1

Duty factor is a dimensionless quantity and has no units of measurement, but can be expressed as a percentage. The term is often found in English texts Duty cycle, this is the so-called duty cycle or PWM duty cycle value. The duty cycle D is the reciprocal of the duty cycle.

Fill factor usually expressed as a percentage and calculated using the formula: D=1/S or so D = T1/T*100%

In the figure above (Fig. 1) you can see that T1 = T0, this is equal to half the time period. So the PWM duty cycle is 50%. If the frequency of such pulses is high enough (say, 5000 Hz), then we get half of 5V i.e. 2.5V. Thus, if the controller's output is coupled to the motor (using appropriate drivers) it will operate at 50% of its full speed. The PWM technique uses this fact to create any voltage between two levels (for example, between 0-12V). The trick is that when the duty cycle value changes between 0-100%, we get the same percentage of input voltage at the output. Below are some examples of PWM signals with different duty cycles.

If you install an R/C filter at the output, you can get a pure DC signal level rather than square waves. But this is not required for brushed motors or for controlling LED brightness. To do this, you can apply a PWM signal directly to the driver (for example, a bipolar transistor, MOSFET, etc.).

Under 16-bit operating mode. The timer is understood as its counting algorithm and the behavior of the pulse shaper output associated with it, which is determined by a combination of bits that specify the timer operating mode (WGMn3-0) and the output signal generation mode (COMnx1:0). In this case, the bits for setting the output signal generation mode do not affect the counting algorithm, because The counting algorithm depends only on the state of the bits for setting the timer operating mode. In PWM modes, the COMnx1:0 bits allow you to enable/disable inversion on the generated PWM output (i.e. select PWM with inversion or PWM without inversion). For non-PWM modes, the COMnx1:0 bits determine what action to take when a match occurs: reset, set, or invert the output (see also “Output Signal Conditioning Block” and “16-Bit Timer-Counter Timing Diagrams”).

Normal operation

The simplest operating mode is normal mode (WGMn3-0 = 0b0000). In this mode, the counter operates as a summing (incrementing) counter, and the counter is not reset. The counter overflows when passing through the maximum 16-bit. value (0xFFFF) to the lower count limit (0x0000). During normal operation, the timer-counter overflow flag TOVn will be set on the same clock cycle when TCNTn reaches zero.

In fact, the TOVn overflow flag is the 17th bit of the timer-counter, except that it is only set and not cleared. However, this property can be used programmatically to increase the resolution of the timer by using a timer overflow interrupt, upon which the TOVn flag is automatically reset. There are no special situations for normal operation, so a new meter state can be recorded at any time.

In normal mode, you can use the capture block. However, it must be ensured that the maximum time interval between the occurrence of external events does not exceed the counter overflow period. If this condition is not met, it is necessary to use a timer-counter overflow interrupt or a prescaler.

The comparison block can be used to generate interrupts. It is not recommended to use the OCnx output to generate signals in normal operation, because in this case, a significant part of the processor time will be spent.

Match timer reset mode (CTC)

In CTC mode (WGM01, WGM00 =0b10), the OCR0 register is used to set the counter resolution. If CTC mode is set and the counter value (TCNT0) matches the value of the OCR0 register, the counter is reset to zero (TCNT0=0). Thus, OCR0 specifies the top count of the counter, and, consequently, its resolution. This mode provides a wider range of adjustment of the frequency of generated rectangular pulses. It also simplifies the operation of the external event counter.

In timer reset on match mode (WGMn3-0 = 0b0100 or 0b1100), the timer resolution is set by the OCRnA or ICRn registers. In CTC mode, the counter (TCNTn) is reset if its value matches the value of the OCRnA register (WGMn3-0 = 0b0100) or ICRn (WGMn3-0 = 0b1100). The value of the OCRnA or ICRn register determines the upper count limit, and therefore the resolution of the timer. This mode provides a wider range of adjustment of the frequency of generated rectangular pulses. It also simplifies the operation of the external event counter. The timing diagram of the timer operation in CTC mode is shown in Figure 1. The counter (TCNTn) increments its state until a match occurs with the value of OCRnA or ICRn, and then the counter (TCNTn) is reset.

Figure 1 – Timing diagram for STS mode

When the upper count limit is reached, an interrupt can be generated using the OCFnA or ICFn flags corresponding to the registers used to set the upper count limit. If the interrupt is enabled, then the interrupt routine can be used to update the upper count limit. However, setting the count top value close to the count bottom limit value when the counter operates without prescale or with a small prescale value must be done with extreme caution, because There is no double buffering in CTC mode. If the value written to OCRnA or ICRn is less than the current value of TCNTn, the counter will reset when the match condition occurs when it reaches the maximum value (0xFFFF), then resets to 0x0000 and reaches the new value of OCRnA or ICRn. In many cases, this situation is not desirable. An alternative is the fast PWM mode, where the OCRnA register determines the upper count limit (WGMn3-0 = 0b1111), because in this case OCRnA is double buffered.

To generate a signal in CTC mode, the OCnA output can be used to change the logic level on each match by setting the switching mode (COMnA1, COMnA0 = 0b01). The OCnA value will be present on a port pin only if the output direction is specified for that pin. The maximum frequency of the generated signal is fOC0 = fclk_I/O/2 if OCRnA = 0x0000. For other OCRn values, the frequency of the generated signal can be determined by the formula:

where the variable N specifies the prescaler division factor (1, 8, 32, 64, 128, 256 or 1024).

As with normal operation, the TOV0 flag is set at the same timer tick when its value changes from 0xFFFF to 0x0000.

Fast PWM mode

The fast pulse width modulation (PWM) mode (WGMn3-0 = 0b0101, 0b0110, 0b0111, 0b1110, 0b1111) is designed to generate PWM pulses of increased frequency. Unlike other operating modes, this one uses unidirectional counter operation. Counting is performed in the direction from the lower to the upper counting limit.

If a non-inverting output mode is set, then when TCNTn and OCRnx coincide, the OCnx signal is set and reset at the upper counting limit. If inverting mode is specified, the OCnx output is reset on a match and set to the high count limit. Due to the unidirectional counting, the operating frequency for this mode is twice as high as compared to the PWM mode with phase correction, where bidirectional counting is used. The ability to generate high-frequency PWM signals makes the use of this mode useful in tasks of power stabilization, rectification and digital-to-analog conversion. High frequency, at the same time, allows the use of external elements of physically small sizes (inductors, capacitors), thereby reducing the overall cost of the system.

The PWM resolution can be fixed 8, 9 or 10 bits or set by the ICRn or OCRnA register, but not less than 2 bits (ICRn or OCRnA = 0x0003) and no more than 16 bits (ICRn or OCRnA = 0xFFFF). The PWM resolution at a given upper limit value (UL) is calculated as follows:

In fast PWM mode, the counter is incremented until its value matches one of the fixed values ​​0x00FF, 0x01FF or 0x03FF (if WGMn3:0 = 0b0101, 0b0110 or 0b0111, respectively), the value in ICRn (if WGMn3:0 = 0b1110) or the value in OCRnA (if WGMn3:0 = 0b1111) and then reset by the next timer clock tick. The timing diagram for fast PWM mode is shown in Figure 2. The figure shows fast PWM mode when the OCRnA or ICRn register is used to set the upper limit. The TCNTn value in the timing diagram is shown as a function graph to illustrate the unidirectional counting. The diagram shows both inverted and non-inverted PWM outputs. A short horizontal line shows points on the TCNTn graph where the OCRnx and TCNTnx values ​​coincide. The OCnx interrupt flag is set when a match occurs.

Figure 2 – Timing diagram for fast PWM mode

The Timer-Counter Overflow (TOVn) flag is set whenever the counter reaches its high limit. Additionally, the same clock pulse, along with the TOVn flag, can set the OCnA or ICFn flags if the OCRnA or ICRn register is used to set the upper limit, respectively. If one of these interrupts is enabled, then the interrupt routine can update the upper count limit and comparison thresholds.

If the value of the upper count limit changes, then the condition must be met that the new upper limit value written is greater than or equal to the values ​​in all comparison threshold registers. Otherwise, a match between TCNTn and OCRnx will never occur. Note that when using fixed upper limit values, unused bits are masked to 0 when writing to the OCRnx registers.

The ICRn register modification mechanism differs from OCRnA when it is used to set the upper limit. The ICRn register is not double buffered. This means that if a small value is written to ICRn while the counter is running with little or no prescaling, there is a risk of writing a value to the ICRn register that is less than the current value of TCNTn. As a result, in this situation the match at the top of the count will be missed. In this case, the counter will reach its maximum value (0xFFFF), restart at 0x0000, and only then generate a match. The OCRnA register contains a double buffering scheme, so it can be modified at any time.

class="eliadunit">

If a write is made to address OCRnA, the value is actually placed in the OCRnA buffer register. If a match occurs between TCNTn and the top of the count, then the next clock cycle of the timer is the copying of the buffer register to the comparison threshold register OCRnA. The register is updated in the same clock cycle as TCNTn is reset and the TOVn flag is set.

It is recommended to use the ICRn register to set the upper limit if the upper count limit is a constant. In this case, the OCRnA register is also freed to generate a PWM signal at the OCnA output. However, if the PWM frequency changes dynamically (due to changing the upper limit), then in this case it is more advantageous to use the OCRnA register to set the upper limit, because it supports double buffering.

In fast PWM mode, the comparison units allow you to generate PWM signals on the OCnx pins. If COMnx1:0 = 0b10, then PWM is set without output inversion, and if COMnx1:0 = 0b11, then PWM mode with output inversion is set (see Table 59). The actual OCnx value can be observed on the port pin if it is set to output direction (DDR_OCnx). The PWM signal is generated by setting (resetting) the OCnx register when a match occurs between OCRnx and TCNTn, and by resetting (setting) the OCnx register along with resetting the counter (change from high limit to low limit).

The PWM frequency of the output signal for a given upper limit value (UL) is determined by the expression:

where N is a variable that specifies the value of the predivision coefficient (1, 8, 32, 64, 128, 256 or 1024).

Writing limit values ​​to the OCRnx register is associated with special cases in the generation of PWM pulses. If OCRnx is set equal to the lower limit (0x0000), then a short pulse will appear at the output every (VP+1)th clock cycle of the timer. Writing a value equal to the upper limit to OCRnx will result in setting a constant log level. 1 or 0 at the output (depending on the polarity of the output signal selected using the COMnx1:0 bit).

If high-frequency square wave generation (rectangular pulses with a duty cycle of 2 or 50% fill) is required, then it is necessary to use the fast PWM mode with the bits COMnA1:0 = 0b01 set, which causes the logic level at the OCnA output to switch (invert) on each match. This is only applicable if OCRnA is used to set the upper limit (WGMn3-0 =0b1111). The maximum generated square wave frequency in this case is fOCnA = fclk_I/O/2, if OCRnA = 0x0000. This feature is similar to OCnA switching in CTC mode, with the exception of double buffering, which is present in fast PWM mode.

Pulse width modulation mode with phase correction (Phase Correct)

Phase-corrected pulse width modulation (PWM FC) mode (WGMn3-0 = 0b0001, 0b010, 0b0011, 0b1010 or 0b1011) is designed to generate a phase-corrected PWM signal with high resolution. The PWM FC mode is based on the bidirectional operation of a timer-counter. The counter cycles from the low limit (0x0000) to the high limit and then back from the high limit to the low limit. If the pulse shaper output mode is set to non-inverting, the OCnx output is reset/set when the TCNTn and OCRnx values ​​match during up/down counting. If the inverting output mode is set, then, on the contrary, during direct counting, the setting occurs, and during reverse counting, the OCnx output is reset. With bidirectional operation, the maximum frequency of the PWM signal is less than with unidirectional operation, however, due to such features as symmetry in PWM modes with bidirectional operation, these modes are preferred to be used when solving drive control problems.

The PWM resolution in this mode can be either fixed (8, 9 or 10 bits) or set using the ICRn or OCRnA register. The minimum resolution is 2 bits (ICRn or OCRnA = 0x0003), and the maximum is 16 bits (ICRn or OCRnA = 0xFFFF). If an upper limit is specified, then the PWM resolution in this mode is determined as follows:

In PWM FC mode, the counter is incremented until it reaches one of the fixed values ​​0x00FF, 0x01FF or 0x03FF (respectively for WGMn3-0 = 0b0001, 0b0010 or 0b0011), as well as a value equal to ICRn (if WGMn3-0 = 0b1010) or OCRnA (if WGMn3 :0 = 0b1011). Further, when the upper limit is reached, the counter changes the counting direction. The TCNTn value remains at the upper limit for one timer clock cycle. The timing diagram for PWM PC mode is shown in Figure 3. The figure shows PWM PC mode using the OCRnA or ICRn register to set the upper limit. The TCNTn state is represented as a function graph to illustrate bidirectional counting. The figure shows both non-inverted and inverted PWM output. Short horizontal lines indicate points on the TCNTn graph where a match with the OCRnx value occurs. The OCnx interrupt flag is set when a match occurs.

Figure 3 – Timing diagram for PWM FC mode

The Timer-Counter Overflow (TOVn) flag is set whenever the counter reaches its lower limit. If the OCRnA or ICRn register is used to set the upper limit, then the OCnA or ICFn flag is set accordingly with the same clock pulse at which the OCRnx register was updated from the buffer register (at the top of the count). Interrupt flags can be used to generate an interrupt when a counter reaches a low or high limit.

When changing the value of the upper count limit, you must ensure that it is greater than or equal to the values ​​in all comparison registers. Otherwise, a match between TCNTn and OCRnx will never occur. Note that when using fixed upper count values, unused bits are cleared to zero when writing to the OCRnx registers. The third period in Figure 53 illustrates the case when a dynamic change in the upper count limit leads to the generation of an asymmetrical pulse. This feature is based on the update time of the OCRnx register. Since the OCRnx update occurs at the top of the count, the PWM period begins and ends at the top of the count. This implies that the countdown duration is determined by the previous upper limit value, and the forward counting duration is determined by the new upper limit value. If these two values ​​are different, then the duration of the forward and backward counting will also be different. The difference in duration leads to asymmetry of the output pulses.

If the task is to change the upper limit while the counter is running, then instead of this mode it is recommended to use the PWM PFC mode (phase and frequency correction). If a static upper limit value is used, then there are practically no differences between these modes.

In PWM FC mode, comparison units allow you to generate PWM signals at the OCnx pins. If you set COMnx1:0 = 0b10, then the PWM output will be without inversion, and if COMnx1:0=0b11, then with inversion. The actual value of OCnx can be observed on the port pin if the data direction register for that port pin is set to output direction (DDR_OCnx). The PWM signal is generated by setting (resetting) the OCnx register when the values ​​of OCRnx and TCNTn match during upcount, and by resetting (setting) the OCnx register when there is a match between OCRnx and TCNTn during downcount. The resulting frequency of the PWM signal in PWM FC mode at a given upper limit (UL) can be calculated using the following expression:

Writing limit values ​​to the OCRnx register is associated with special cases in the generation of PWM signals in the PWM FC mode. If you set the PWM mode without inversion and set OCRnx equal to the lower limit, then the output will be continuously set to log. 0, and if equal to the upper limit, then a log is always present at the output. 1. For PWM with inversion, the indicated levels must be replaced with the opposite ones.

If you specify to use OCnA as the upper limit (WGMn3:0 = 0b1011) and set COMnA1:0 =0b01, a square wave will be generated at the OCnA output.

Pulse width modulation mode with phase and frequency correction (Phase and Frequency Correct)

The pulse-width modulation mode with phase and frequency correction (PWM PFC) (WGMn3-0 = 0b1000 or 0b1001) is designed to generate high-resolution PWM pulses with phase and frequency correction. Just like the PWM FC mode, the PWM FC mode is based on the bidirectional operation of the counter. The counter cycles from the low limit (0x0000) to the high limit and then back from the high limit to the low limit. If the non-inverting PWM mode is specified, the OCnx output is cleared if a match occurs between TCNTn and OCRnx during upcount, and set if a match occurs during downcount. In inverting mode the operation is inverse. Bidirectional operation, compared to unidirectional operation, is associated with the generation of lower frequencies. However, due to the symmetry in PWM modes with bidirectional counting, their use is preferable in drive control tasks.

The main difference between the PWM FC and PWM FC modes is the moment the OCRnx register is updated from the OCRnx buffer register (see Figure 3 and Figure 4).

The PWM resolution in this mode can be set using the ICRn or OCRnA register. The minimum resolution is 2 bits (ICRn or OCRnA = 0x0003), and the maximum resolution is 16 bits (ICRn or OCRnA = 0xFFFF). The PWM resolution in bits can be calculated using the following expression:

In PWM FCC mode, the counter is incremented until it matches the value in ICRn (WGMn3:0 = 0b1000) or in OCRnA (WGMn3:0 = 0b1001). This means reaching the top of the count, after which the direction of the count changes. The value of TCNTn remains at the top of the count for one timer clock cycle. The timing diagram for the PWM FCC mode is shown in Figure 54. The figure shows the PWM FCC mode when the counting top is set by the OCRnA or ICRn register. The TCNTn value is shown as a function graph to illustrate the bidirectional counting. The diagram shows both non-inverting and inverting PWM outputs. Short horizontal lines indicate points on the TCNTn plot where a match between OCRnx and TCNTn occurs. The OCnx interrupt flag is set after a match occurs.

Figure 4 – Timing diagram of PWM mode with phase and frequency correction

The timer-counter overflow flag (TOVn) is set at the same clock cycle when the registers are updated with the value from the buffer register (at the lower counting limit). If the OCRnA or ICRn register is used to set the upper limit, then when the counter reaches the upper limit, the OCnA or ICFn flag is set, respectively. Interrupt flags can be used to generate an interrupt when a counter reaches a high or low limit.

When changing the upper limit, you must ensure that the new value is greater than or equal to the values ​​in all comparison threshold registers. Otherwise, if the upper limit is set to a value less than any of the values ​​in the comparison threshold registers, a match between TCNTn and OCRnx will never occur.

Figure 4 shows that, unlike the PWM FC mode, the generated output signal is symmetrical at all periods. Since the OCRnx registers are updated at the lower counting limit, the durations of the forward and backward counts are always equal. As a result, the output pulses have a symmetrical shape and, therefore, a corrected frequency.

Using the ICRn register to set the upper limit is recommended if the upper limit value is a constant. In this case, the OCRnA register is also freed for pulse width modulation of the pulses at the OCnA pin. However, if you need to dynamically change the PWM frequency by changing the upper limit, then it is recommended to use the OCRnA register to set the upper limit due to its double buffering.

In PWM mode, the comparison units allow you to generate PWM pulses at the OCnx pin. If COMnx1:0 = 0b10, then a non-inverting PWM output is set, and if COMnx1:0=0b11, then an inverting one (see table 60). The OCnx value will only be present on the corresponding port pin if it is set to output direction. The PWM signal is generated by setting (resetting) the OCnx register on a match between OCRnx and TCNTn during upcount and resetting (setting) the OCnx register on a match between OCRnx and TCNTn during downcount. The PWM frequency in this mode with a given upper limit (UP) of counting is determined as follows:

where N is the prescaler division factor (1, 8, 32, 64, 128, 256 or 1024).

Writing limit values ​​to the OCRnx register is associated with special cases in the generation of PWM signals in this mode. If you set OCRnx equal to the lower limit (0x0000), then in non-inverting mode the output will constantly have a low logic level, and when writing a value equal to the upper limit, the output will have a high logic level for a long time. In inverting mode, the given levels will be opposite.

If OCRnA is used to set the upper limit (WGMn3:0 = 0b1001) and COMnA1:0 = 0b01, then a square wave will be generated at the OCnA output.

Hardware implementation of PWM provides undoubted advantages over software, since it relieves the processor of both unnecessary and cumbersome code and time for its maintenance, and also provides more opportunities for using work with PWM. It is enough to initialize the timer/counter (enter the necessary values ​​into the registers used by the timer/counter) and the timer/counter can work independently of the processor; accordingly, the processor can deal with other tasks, only occasionally contacting at the necessary moment to adjust or change the mode or obtain results from the timer /counter.

Description of interrupt flags

T1 can generate an interrupt when:

  1. counter register TCNT1 overflow;
  2. if the counting register TCNT1 and the comparison register OCR1A and OCR1B are equal (separately for each register);
  3. while storing the counting register in the capture register ICR1.

T2 can generate an interrupt when:

  1. overflow of the TCNT2 counter register;
  2. when the counting register TCNT2 and the comparison register OCR2 are equal.

The flags of all interrupts are in the TIFR register, and interrupt enable/disable is in the TIMSK register.

TIMSK register bits
Register7 6 5 4 3 2 1 0
TIMSK OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 OCIE0* TOIE0
  • OCIE2- Interrupt enable flag for the “match” event of the timer/counter T2
  • TOIE2- T2 timer/counter overflow interrupt enable flag
  • TICIE1- Interrupt enable flag for the “capture” event of the timer/counter T1
  • OCIE1A- Interrupt enable flag for the “match A” event of the timer/counter T1
  • OCIE1B- Interrupt enable flag for the “coincidence B” event of the timer/counter T1
  • TOIE1- T1 timer/counter overflow interrupt enable flag
  • OCIE0*- Interrupt enable flag for the “coincidence” event of the timer/counter T0 (* - not available in ATmega8)
  • TOIE0- Timer/counter overflow interrupt enable flag T0
  • OCF2- Interrupt flag for the “coincidence” event of the timer/counter T2
  • TOV2- Timer/counter overflow interrupt flag T2
  • ICF1- Interrupt flag for the “capture” event of the timer/counter T1
  • OCF1A- Interrupt flag for the event "coincidence A" of the timer/counter T1
  • OCF1B- Interrupt flag for the event "coincidence B" of the timer/counter T1
  • TOV1- Timer/counter overflow interrupt flag T1
  • OCF0- Interrupt flag for the “coincidence” event of the timer/counter T0
  • TOV0- Timer/counter overflow interrupt flag T0

Description of the operation of the timer/counter T1 in the ATmega8/16 controller

The sixteen-bit timer/counter T1 can be used to generate time intervals, count the number of external signals, and generate PWM signals of varying duty cycles and durations on pins OC1A and OC1B. In addition, by an external signal from the ICP1 pin or from an analog comparator, T1 can save its current state in a separate capture register ICR1.

Register bits TCCR1A:TCC1B:TCNT1:OCR1A:OCR1B:ICR1
Register7 6 5 4 3 2 1 0
TCCR1A COM1A1 COM1A0 COM1B1 COM1BO FOC1A FOC1B WGM11 WGM10
TCCR1B ICNC1 ICES1 * WGM13 WGM12 CS12 CS11 CS10
TCNT1:H R/W R/W R/W R/W R/W R/W R/W R/W
TCNT1:L R/W R/W R/W R/W R/W R/W R/W R/W
OCR1A:H R/W R/W R/W R/W R/W R/W R/W R/W
OCR1A:L R/W R/W R/W R/W R/W R/W R/W R/W
OCR1B:H R/W R/W R/W R/W R/W R/W R/W R/W
OCR1B:L R/W R/W R/W R/W R/W R/W R/W R/W
ICR1:H R/W R/W R/W R/W R/W R/W R/W R/W
ICR1:L R/W R/W R/W R/W R/W R/W R/W R/W

Each 16-bit register is physically located in two 8-bit registers, so when reading an entry in them, two operations must be performed. When writing, the high byte is loaded first, then the low byte; when reading, on the contrary, the low byte is read first, then the high byte.

TCCR1A:TCCR1B- 8-bit timer/counter control registers T1

TCNT1- 16-bit timer/counter register T1. Depending on the operating mode, the contents of this register are cleared, incremented (the value is increased by 1), or decremented (the value is decreased by 1) for each pulse of the timer/counter clock signal.

OCR1A:OCR1B- 16-bit comparison registers

ICR1- 16-bit capture register, stores the value of TCNT1 when an active signal edge is applied to the ICP1 pin or by a signal from the comparator.

Bit assignment

COM1A1:COM1A0:COM1B1:COM1B0- These bits determine the behavior of the OC1A:OC1B pin when the value of the TCNT1 counting register and the OCR1A:OCR1B comparison register match

FOC1A:FOC1B- These bits are used to force a change in the state of pin OC1A:OC1B

ICNC1- Interference circuit control bit, if the bit is “0” the capture will be on the first active edge, if “1” the capture will be after the fourth identical sample of the capture signal.

ICES1- Bit for selecting the active edge of the signal, if its value is “0”, saving the counting register TCNT1 in the capture register OCR1 will be on the falling edge of the signal, if “1” on the rising edge.

WGM13:WGM12:WGM11:WGM10- These bits determine the operating mode of the timer/counter T1

CS22:CS21:C20- Bits that determine the source of the T1 timer/counter clock signal.

Selecting the operating mode of the timer/counter T1
WGM13WGM12WGM11WGM10Operating modeAccount module (TOP)
0 0 0 0 Normal $FFFF
0 0 0 1 Phase correct PWM

8-bit

$00FF
0 0 1 0 Phase correct PWM

9-bit

$01FF
0 0 1 1 Phase correct PWM

10-bit

$03FF
0 1 0 0 CTC (reset on match) OCR1A
0 1 0 1 Fast PWM

8-bit

$00FF
0 1 1 0 Fast PWM

9-bit

$01FF
0 1 1 1 Fast PWM

10-bit

$03FF
1 0 0 0 ICR1
1 0 0 1 Phase and Frequency Correct PWM OCR1A
1 0 1 0 Phase correct PWM ICR1
1 0 1 1 Phase correct PWM OCR1A
1 1 0 0 CTC (reset on match) ICR1
1 1 0 1 Reserved *
1 1 1 0 Fast PWM ICR1
1 1 1 1 Fast PWM OCR1A

Selecting a Clock Source

Normal mode

The simplest operating mode is T1. For each pulse of the clock signal, the counting register TCNT1 is incremented (the value increases by 1). When passing through the value $FFFF of the counting module (TOP), an overflow occurs and the next clock cycle begins counting from the value $0000, at the same moment the TOV1=1 flag is set in the TIFR register, and an interrupt can be generated if the TOIE1=1 flag is set in the TIMSK register. In order to generate a signal of a given frequency in this mode, it is necessary to write in the bits COM1A1=0:COM1A0=1 for the OC1A output or COM1B1=0:COM1B0=1 for the OC1B output of the controller.

In addition, for each clock cycle, a comparison is made between the counting register TCNT1 and the comparison register OCR1A:OCR1B, if there is a match, the interrupt flag OCF1A=1:OCF1B=1 is set and if the bit OCIE1A=1:OCIE1B=1 of the TIMSK register, an interrupt is generated. At the same time, the state of the OC1A:OC1B pin can be changed depending on the settings of the COM1A1:COM1A0:COM1B1:COM1B0 bits.

CTC mode (reset on match)

In this mode, T1 works on the same principle as in Normal mode. The difference is that the maximum possible value of the counting register TCNT1 is limited by the value of the comparison register OCR1A or ICR1 (see the timer/counter mode selection table). When TCNT1 reaches the value of OCR1A or ICR1, the value of TCNT1 is reset to TCNT1=$0000. At the same time, the TOV1=1 flag is set COM1A1:COM1A0:COM1B1:COM1B0 Determines the behavior of the OC1A:OC1B pin when there is a match.

Fast PWM mode (fast PWM)

Using this mode, you can generate a high-frequency PWM signal. The principle and procedure of operation does not differ from the Normal mode, except for the presence of double buffering of the OCR1A:OCR1B register, which eliminates the appearance of asymmetrical signal pulses, and also differs in the behavior of the OC1A:OC1B pins (see table).


Phase Correct PWM mode

The difference between this mode and the previous ones is that the counting register operates as a reverse counter. Since this mode is recommended by Atmel as the most suitable for tuning engines, we will consider it in more detail. When the counting register TCNT1 reaches the value of the counting modulus (TOP) (or the value of the ICR1 register or the value of the OCR1A register, see the timer/counter mode selection table), the counting direction changes. When the counting register TCNT1 reaches the minimum value ($0000), the counting direction also changes and at the same time the interrupt flag TOV1 of the TIFR register is set. Also, if the contents of the counting register TCNT1 and the comparison register OCR1A:OCR1B are equal, the OCF1A:OCF1B flag of the TIFR register is set and the state of the OC1A:OC1B output changes, according to the table.

To avoid asymmetrical emissions when writing a value to the OCR1A:OCR1B register, double write buffering is implemented in this mode. Thanks to this, the actual change in the register value changes at the moment the counter register TCNT1 reaches the value of the counting modulus (TOP) (or the value of the ICR1 register or the OCR1A register value, see the timer/counter mode selection table). Therefore, at the very beginning, when the timer/counter is initialized, the OC1A:OC1B pin will not change its state upon matching until the register reaches the value (TOP).

Task: Let's develop a program to control the brightness of a 12 Volt incandescent lamp using PWM. When you press the “More” button, the brightness of the lamp increases, and when you click on the “Less” button, the brightness decreases. The diagram of our future device is shown in the figure. As usual, we use the Atmega8 microcontroller, which will be clocked from an internal oscillator with a frequency of 4 MHz. Actually, we will get a dimmer; these devices are designed to adjust the brightness of lighting fixtures. Nowadays, LED dimmers are the most widespread.

For simplicity, you can also connect an LED to our circuit, but it will be more clear with a light bulb. Buttons are connected to pins PD0, PD1. We connect the load to the output PB1(OC1A) through a resistor and a MOSFET field-effect transistor, which will work as a key for us (in switching mode). A field-effect transistor is preferable because its gate is isolated from the power circuit and is controlled by an electric field, and the control current reaches microamps. This allows, using one or two transistors, to control a load of enormous power (up to tens of amperes and tens or hundreds of volts) without loading the microcontroller. Taking into account also the fact that field-effect transistors can be connected in parallel (unlike bipolar ones), it is possible to obtain an even more powerful cascade of hundreds of amperes.

Now let's figure out how the microcontroller implements PWM and write a program. As mentioned earlier, our MK has 3 timers, and all of them can operate in PWM mode. We will be working with a sixteen-bit timer/counter. Bits WGM13-10 let's configure our timer to work FastPWM with an upper count limit ICR1. The principle of the program is this: our timer counts from 0 to 65535(0xFFFF), into the register ICR1 Let's enter the number 255, this will be the upper limit of the timer count (TOP), the frequency of the PWM signal will be constant. Also, our timer is configured so that if the counting register and the comparison register match (TCNT1 = OCR1A), the controller output will switch OC1A. The PWM duty cycle can be changed by writing to the comparison register OCR1A a certain number from 0 to 255, the larger this number, the greater the fill factor, the brighter the lamp will burn. Depending on which button is pressed the variable changes i, and then it is written to the register OCR1A.

The full text of the program is presented below. The comments describe the operation of the program in more detail.

/***Lesson No. 8. Generating PWM signals***/ #include #include int main(void) ( unsigned int i=0; //define variable i /***Configuring I/O ports***/ PORTB = 0x00; DDRB |= (1<< PB1); PORTD |= (1 << PD1)|(1 << PD0); // подключаем внутренние нагрузочные резисторы DDRD = 0x00; /***Настройка таймера***/ TCCR1A |= (1 << COM1A1)|(0 << COM1A0) // Установим биты COM1A1-COM1A0:0b10, означает сброс вывода канала A при сравнении |(1 << WGM11)|(0 << WGM10); // Установим биты WGM13-10:0b1110, согласно таблице это TCCR1B |= (1 << WGM13)|(1 << WGM12) // будет режим - FAST PWM, где верхний предел счета задается битом ICR1 |(0 << CS12)|(0 << CS11)|(1 << CS10); // Битами CS12-10:0b001 задаем источник тактового сигнала для таймера МК, включен без делителя TCNT1 = 0x00; // начальная установка счетчика ICR1 = 0xFF; // задаем период ШИМ, здесь у нас число 255, // по формуле fPWM=fclk_I/O/N*(1+ICR1)// вычисляем частоту ШИМ, она будет равна 15625 Hz OCR1A = 0x00; // начальный коэффициент заполнения ШИМ /***Основной цикл программы***/ while(1) { if((PIND&(1 << PD0)) == 0) //если кнопка "больше" нажата { if (i < 254) { // коэффициент заполнения ШИМ изменяется от 0 до 255 i=i+1; // увеличиваем i на единицу OCR1A = i; // записываем переменную в регистр сравнения _delay_ms(30); // задержка 30ms } } if((PIND&(1 << PD1)) == 0) //если кнопка "меньше" нажата { if (i >0) // PWM duty cycle changes from 255 to 0 ( i--; // decrease i by one (you can also write this) OCR1A = i; // write a variable to the comparison register _delay_ms(30); // delay 30ms ) ) ) )

Attention! First, we supply power to the microcontroller, then you need to make sure that the transistor is connected to the MK pin, and only then supply power to the circuit with the lamp and the field-effect transistor. Otherwise you may burn the transistor. The fact is that when turned off, the “legs” of the MK “dangle in the air” - they are not connected to anything, and interference occurs on them. These weak interferences are enough to partially open a very sensitive field-effect transistor. Then its resistance between drain and source will drop from several MOhms to several Ohms or fractions of Ohms and a large current will flow through it to the lamp. But the transistor will not open completely, because for this you need to apply not 1-3 V interference to the gate, but a stable 5 V, and its resistance will be much greater than the minimum. This will lead to the release of a large amount of heat on it, and it will smoke and possibly burn.