03 - AVR specifics

 

As we have seen in the previous chapter there are several things to bear in mind for PWM:-

 

1. The clock speed of your microcontroller. Obviously a given microcontroller only has one speed that at it runs at - although this can be can be altered by changing fuse bits or by adding external crystals. Changing the clock speed will effect ALL of your PWM channels

2. A microcontroller can have one or more Timer that can be used to produce PWM. Each Timer may provide zero-or-more PWM channels and will have a pre-scaler value that effects all of the channels that it provides and controls the speed at which the clock is used to count between BOTTOM and TOP. Each Timer can have a mode of operation (Fast PWM, phase correct or phase and frequency correct) which may have a fixed value for TOP or allow you to specify a precise value.

3. Each channel can have a comparator mode (inverted, or non-inverted) as well as its own comparator value that allows you to define the duty-cycle of the PWM signal for the channel.

 

If you are struggling with these concepts then please go back and re-read the previous chapters (or let me know if something is missing or non-sensible!).

 

Since PWM 'in-practice' uses a number of fiddly little bits in various registers - and these change from one controller to another - then its hard to give you a 'one-solution-fits-all'. So we will now start to look at where these settings exist for each controller. The principles are always the same - but the registers and the bits may change. So the purpose of this chapter is to come up with some tabular data for different controllers and channels so that you can substitute the appropriate values into your code. It may sound complicated - but once you settle on a given controller then (I hope) it will all make sense.In the next chapter I provide some downloads to give the specific names for each register/bit for various microcontrollers.

 

In order for you to make sense of some of the datasheets then I will try to describe some of the 'generic' nomenclature they use.

 

Each Timer has various registers that are used to store its configuration. These are normally called TCCRxA, TCCRxB, TCCRxC etc where 'x' is the Timer number (1,2,3, etc). Since each timer provides different capabilities then it requires more or less configuration bits so each timer may have a varying number of configuration registers. If they one require one register then the last character is dropped and it is just called TCCRx. Since the Timers are capable of a lot more than just PWM then some of the configuration values in these registers is way beyond the scope of this tutorial.

 

The pre-scaler mode for a timer is generally set by the combination of 3 bits called (from most to significant to least significant) CSx2, CSx1 and CSx0 and normally exist in register TCCRxB  where 'x' is the timer number. These bits, for PWM purposes, may have the following example values:-

0,0,0 = The timer is stopped and so no PWM will be generated. This kills the whole timer and therefore also kills all PWM channels it provides. The main advantage of 'stopping' a timer is that the chip may consume less power. Its always good to kill off facilities you don't need.

0,0,1 - PWM is active with a pre-scaler value of 1

0,1,0 - PWM is active with a pre-scaler value of 8

0,1,1 - PWM is active with a pre-scaler value of 64

1,0,0 - PWM is active with a pre-scaler value of 256

1,0,1 - PWM is active with a pre-scaler value of 1024

 

The comparator mode requires 2 bits that are normally stored in register TCCRxA where 'x' is the timer number. But don't forget that each timer can support mulitple channels so there will be a complete set of these 2 bits for each channel for each timer. The bits are called COMxy1 and COMxy0 where 'x' is the timer number and 'y' is the channel number: 'A', 'B' etc. The general value for these two pins is as follows:-

0,0 - This PWM channel is switched off.

1,0 - This PWM channel is switched on in non-inverting mode

1,1 - This PWM channel is switch on in inverting mode

NB The last two values will switch the PWM channel 'on' - but unless the timer, as a whole, is switched 'on' by setting a pre-scale value as mentioned above then nothing will happen.

 

The mode of operation is set using the four (or less) bits WGMx3, WGMx2, WGMx1, WGMx0 where 'WGM' stands for 'Waveform Generation Mode', and 'x' is the Timer number. Just to make life a bit more complicated the controllers often split these bits so that some are stored in register TCCRxA and others in register TCCRxB. These four bits actually give a total of 16 different modes (called Mode 0 to Mode 15). Each Timer (especially 8 bits ones) will only support a subset of these modes. Some of these modes are for non-PWM usage and so we wont discuss them further.

The most flexible modes, only available on 16 bit Timers, are those where TOP is set to a specific value by ICRx and use OCRxy is used to modify the duty cycle on the fly. These modes are:-

Mode WGMx3 WGMx2 WGMx1 WGMx0 Description
8 1 0 0 0 Phase and Frequency Correct mode
10 1 0 1 0 Phase Correct Mode
14 1 1 1 0 Fast PWM Mode

 

The value of TOP is specified by the register ICRx where 'x' is the timer number and is a 16 bit value (ie 0 to 65,535). Note that there is only one value per timer - so all the PWM channels on the same channel will share this value. This is not normally an issue since, as an example, if we were using two channels on the same timer to drive two servos then this one value for TOP is used to set the overall pulse frequency - which is every 20ms for a servo. So there is no problem with the same value applying to both servos.

Other mode numbers are available for these 3 basic PWM modes - the only difference is that the value of TOP is fixed at a set value ie 255, 511, 1023 and so you have less flexibility to set an exact repeating frequency.

 

The comparator value, which you use to specify the duty cycle of a given channel, is set by writing the required number to register OCRxy. Where 'x' is the timer number, and 'y' is the PWM channel A, B etc. So for PWM channel A on Timer 1 then we would write to OCR1A. If the Timer only has one possible channel then the final letter would be removed ie OCRx

 

 

So let's practice this with an imaginary example - before giving some real examples in later chapters. Assume that we wanted to set up a 16 bit PWM on Channel B of Timer 1 with a prescaler of 1, non-inverting mode, Phase and Frequency Correct, with a TOP of 10,000. Then we would replace 'x' in the above details with the Timer number - ie '1' for this example, and the 'y' with the Channel number - ie 'B' for this example. So in pseudo code this is what we would do:

// Set up the pre-scaler to 1

Register: TCCR1B - set bits CS12,CS11,CS10 to 0,0,1 respectively

// Set up the comparator mode to 'non-inverting'

Register: TCCR1A - set bits COM1B1 and COM1B0 to 1,0 respectively

// Set for phase and frequency correct mode

In Registers TCCR1A and/or TCCR1B - set bits WGM13, WGM12, WGM11, WGM10 to 1,0,0,0 respectively

// Set the TOP value

Set Register ICR1 to 10,000

// We can now change the duty cycle by varying the value of the comparator in register OCR1B with a value between 0 and TOP (ie 0 to 10,000)

 

Easy?