Saturday, July 17, 2010

AVR2

Here is the hello world program for the Tiny85.
All this does is turn on a single LED connected
to pin 5 (Port B bit 0)


Here is the code followed by a complete description
of every line.




Ok, firstly, anything following a ; is considered by
the assembler to be just a comment. So the entire
section

; ********************************************
; * Tiny85LEDON                                                          *
; * 07/17/2010                                                                 *
; ********************************************

is nothing but a comment and means nothing to
the assembler...this is stuff just for you the programmer
to read and use.

these lines cause a large file of definitions
and such to be loaded and processed by the
assembler.

.NOLIST
.INCLUDE "tn85def.inc"
.LIST

 The include file named tn85def.inc is the important
thing here. The .NOLIST and .LIST are there just to
keep the AVR Studio IDE from displaying the huge
tn85def.inc file when it produces a list file. You don't
need to see all the stuff inside that file, it's mostly
boring and you need not think about it. Each AVR
model has its own def file that details stuff like the names
of the registers, amounts of memory..etc..etc  If you
don't include this file you cannot use the simple names
for things like I/O registers and would have to enter
the addresses instead, that would suck because it would
make assembly programming much more tedious.

The line
.def    temp    =r16

 defines the word temp to mean the same thing as r16.
Now you can just type temp and the assembler will
translate that to r16 (working register 16) there are 32
working registers that each hold one byte(8 bits). Registers
16-31 are more useful than the others especially 30 and 31
because this pair can hold a word (16 bit number)

This long list of interrupt vectors is not strictly
needed but we will include it for now since it will
help you to understand that the first several bytes
of memory are meant to hold these vectors.

        rjmp Start ; Reset vector
        reti ; Int vector 1
        reti ; Int vector 2
        reti ; Int vector 3
        reti ; Int vector 4
        reti ; Int vector 5
        reti ; Int vector 6
        reti ; Int vector 7
        reti ; Int vector 8
        reti ; Int vector 9
        reti ; Int vector 10
        reti ; Int vector 11
        reti ; Int vector 12
        reti ; Int vector 13
        reti ; Int vector 14

The first one is memory location zero, this is the first
byte of code that runs when you power up an AVR.
Putting this line

rjmp Start ; Reset vector

In this spot is not required but is much recommended!
rjmp means relative jump and it sends the AVR down to
where your actual program starts at the label   Start:
It thus jumps over all the other interrupt vector bytes
which are filled with the reti command. This is the
return from interrupt code and usually is found at the
very end of an interrupt service routine. It serves well
here as a sort of placeholder that will if ever called
just bounce your program out of any interrupt that jumps
to it.

Notice the ; in each of these short lines of code, it means
that the text on the line following the ; is just a comment.

Ok, this next line is called a label. This is just a name you
make up to tell the assembler where a particular place in
memory is.

Start:

Don't forget to put labels starting in the first column and
never ever forget the : at the end!  Also don't use a name
reserved by the assembler for something else such as
PORTB:  all hell would break loose if you tried it! :-)
Labels don't take up memory space in the AVR, they
are simply a way for the assembler to locate a place in
memory when it assembles your source code.

ser    temp          ;set temp (r16) to 0b11111111

ser        means SEt Register

What it does is it moves 0b11111111 into a register
quickly. It is the fastest way to do this and you will
use this instruction often. Note that it only works on
working registers 16-31 !!!

0b11111111 is the proper way to write a binary value
for the assembler to understand. Hexadecimal is written
like this 0xFF or $FF    these three numbers

0b11111111
0xFF
$FF

All equal decimal 255, you can use decimal in the assembler,
it is the default base and so you could simply write 255.
(you do know computer arithmetic? I hope so because I
am not planning on reviewing it here...there are many fine
tutorials already on the web)


out    DDRB,temp     ;copy temp to I/O register DDRB
                                  ;making port B pins all outputs

the out instruction copies the value in a working register
into an I/O register. You cannot move a number directly
into an I/O register, you must copy it over from a working
register!

Copying the value 0b11111111 into DDRB will make
all the pins of PortB outputs. If a bit is set to a 1 then
the corresponding pin is an output, if the bit is a 0 then
that pin is an input.

clr    temp          ;set temp to 0b00000000

The clr instruction sets a working register to 0b00000000
clr stands for CLear Register.


out    PortB,temp    ;set all port B pins low

This turns off all the I/O pins on PortB. They will thus
be at ground potential. If a bit in PortB holds a zero then
it's corresponding pin is low.

Ok, now we get to the line that actually will turn
our LED on!

sbi PortB,0       ;set PortB pin 0 high

sbi sets a bit in an I/O register to a one. This makes it
high (at vcc usually 5v) so this line sets pin 0 at 5v and
if an LED is connected from this pin to ground (through
a current limiting resistor) it will light up!

loop:    rjmp loop         ; loop 4ever

This is the last line in our small program. It just creates
an endless loop, you can never let the AVR just wonder
off when its program ends!  You must put it into some
sort of loop, or put it to sleep :-)

If you run this in the AVR Studio IDE and look at the
simulator over on the right and click on PortB you will
see this



Notice that DDRB has been set to all ones by the code line
 
out    DDRB,temp

Remember that temp held 0b11111111 when it's value was
copied to DDRB.

And notice that pin zero of PortB is indeed turned on,
it is at vcc (usually 5v)

I will try to actually build up a small circuit for the next
post so you can actually see this program running on a
Tiny85 and lighting up an LED.

After that perhaps we will alter this program and
let an interrupt service routine turn the LED on.
It is easy to blink the LED using a Timer interrupt
or you can use a button connected to an input pin
to turn it on when a pin change interrupt is triggered.

1 comment:

  1. The dark purple text on black is nearly impossible to read.

    ReplyDelete