[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] light up and led

From: Joerg Wunsch
Subject: Re: [avr-gcc-list] light up and led
Date: Fri, 7 Oct 2005 22:20:20 +0200 (MET DST)

On Fri, 2005-10-07 at 17:52 +1000, Timothy Smith wrote:

> the timer stuff is still a little confusing, all the abreviations
> are unintuitive.

You mean the bit names?

They come straight from Atmel's datasheet.  Usually, with a bit of
phantasy, you could guess what they mean.

    /* tmr1 is 10-bit PWM */
    TCCR1A = _BV (PWM10) | _BV (PWM11) | _BV (XCOM11);

Timer/counter 1's control register A gets bits PWM10 and PWM11 set
plus bit XCOM11.  The comment on top basically explains the effect of
these. ;-)

What makes it confusing here (sorry, I don't see a better way) is that
each and every AVR has some variations of how the bits are named.  The
#ifdef spaghetti on top then maps the names for one AVR to the names
of another one if needed.  So you need to make sure to get the right
datasheet to interpret the above. :-(  As that particular code is
already a bit aged, it has once been written for the AT90S2313, so for
all newer AVRs, bit names are mapped to the old ones.  For similar
reasons, that XCOM11 is rather an alias for COM1A1, see a few lines
above in that file.

So with PWM10, PWM11, and COM1A1, you'll find the explanation on pages
32 (table 9) and 34 (table 12) of the AT90S2313 datasheet.
PWM10+PWM11 enable a 10-bit PWM mode (iow, the counter counts from 0
to 1023 and then back to 0).  COM1A1 without COM1A0 in PWM mode says
the respective output compare pin will be cleared on compare match
(i.e. when the counter reaches the value of the OCR1A register) when
counting up, and set again when getting below that value while
counting down.  Thus, a large value in OCR1A (remember the largest
possible value is 1023, due to it being a 10-bit counter here) means
the OC1A pin will get a wide high portion of its output pulse, so the
LED will be bright.

    /* tmr1 running on full MCU clock */
    TCCR1B = _BV (CS10);

Timer/counter 1's control register B is explained on page 32.  The
comment says it all, the above starts the timer at full CPU clock.
Thus, the frequency of the PWM itself is F_CPU / 2046 (see table 11).

    /* set PWM value to 0 */
    OCR = 0;

Should be clear.  OCR (output compare register) is actually OCR1A here
(see the #ifdefs).  This will start the PWM with a LED that's turned
off, as there's never a condition where OC1 would get high.

    /* enable OC1 and PB2 as output */
    DDROC = _BV (OC1);

This enables the data direction register for the output compare match
pin, to set that pin as an output.  As different AVRs have the OC1
register at different pins even on different ports, this again needs
to be #ifdefed.  For the AT90S2313, OC1 is physical pin PB3, so DDROC
will actually be DDRB (data direction register for port B).

> eg. i was told on this list that _BV() is discouraged, ..

No, _BV() is not discouraged, only the previous BV() was (as it has a
rather high probability to be a valid name within the application
itself so it could cause collisions).  _BV() is nothing more but
shifting a 1-bit left by the count given as parameter, so if you
prefer you can always write (1 << OC1) etc. yourself.  This bit
shifting is frequently needed on the AVR, as the datasheet lists all
bits not as bit masks but as bit numbers.  This is probably due to
these bit numbers also being needed for the SBI, SBIS, CBI, and CBIS
assembly instructions, and as the header files defining the IO bits
(i.e. <avr/io.h> in our case) are also meant to be used in assembly
source files, but C's bit manipulation always requires bit masks, we
need to shift around...

cheers, J"org               .-.-.   --... ...--   -.. .  DL8DTL

http://www.sax.de/~joerg/                        NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)

reply via email to

[Prev in Thread] Current Thread [Next in Thread]