Showing posts with label AVR. Show all posts
Showing posts with label AVR. Show all posts

Friday, July 30, 2010

AVR4

First we are going to make our Tiny85 blink the
green LED by using a simple delay routine. Then
we will modify the program further to accomplish the blinking
by use of a timer interrupt.

Saturday, July 17, 2010

AVR3

I just put the circuit together so you can see
the last program actually running and lighting
up the LED on a Tiny85 pin 5 (PortB 0)


I used a 7905 5v negative regulator instead of a 7805
positive regulator because that's all I could find in my
part drawer. It works fine for this. Between the regulator
top and the little orange wire are 6 socket holes. These
are where I plug the 6 wires from the STK500 programmer
into the solderless breadboard to program the flash
memory using AVR Studio. If you have a solderless
breadboard you can assemble an identical circuit from
this image. Now look at the image below, it is a blowup
of the 6 pin holes for the programming cable.



Socket hole 5 is for the VCC wire (+5v)
Socket hole 6 is for the MOSI wire
Socket hole 7 is for the GND wire
Socket hole 8 is for the RESET wire
Socket hole 9 is for the SCK wire
Socket hole 10 is for the MISO wire

Note what pins the leads for MOSI, RESET, SCK and
MISO route to on the Tiny85. The GND and VCC just
connect to any handy socket where GND and 5v are
available.




Here is an image of my solderless board with the
makeshift programming cable connected.


                 

Notice in the upper left corner of the breadboard where
I drilled a small hole and ran the power leads through it
for strain relief. This is handy :-)

I want you to be absolutely certain of how to connect
the wires to the end of the 10-pin programming cable.
This image shows the cable end, please note the orientation
of the connector and where the red stripe is on the cable!




Ok, starting at the top left corner and moving right. The first
pin is MOSI  the center top pin is RESET  the 4th pin from
left is SCK and the rightmost top row pin is MISO.

The far left pin on the lower row is VCC (5v)
and the 2nd pin from the left is GND.

The other pins need not connect to anything, only these
six are important. Some people use a smaller six pin cable
for programming, but I find it difficult to find the connectors
and sockets for the six pin cables so I use the older 10 pin
style cables. If you need help with the six pin type send me
a message and I will detail the pinout.

===========================

I will be posting some short videos so I went and got an
account on youtube today. 

There is nothing there yet so be patient. I will post videos
of the next two projects running. They will both be
interrupt driven LED blinkers.

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.

Friday, July 16, 2010

AVR1

It is my firm belief that anyone starting
out to learn to program a new processor should start
with its assembly language. My reasoning is that using assembly
forces you to learn and understand the architecture
of the processor. To be any good at assembly you must
be able to hold an image of the chip's hardware in your mind. You must
know exactly where the data is, what the assembly instructions
do with that data and how your code controls the hardware.
In short, if you want to do really good work then you had
better know how to code in assembler(asm).

Luckily assembler is the simplest of all languages to code
in. Now I did not mean it is the fastest way to write code
for a processor, just that it is the simplest and most
elementary way. Most processors have a relatively small collection
of assembly instructions and these are nearly all as easy
to understand as 1 + 1 = 2. The AVR and the MSP430 are easy to
program in assembly and the Parallax Propeller processor(the Prop)
is no exception, it too is easy to program in asm!

The easiest way to learn asm is by taking short asm programs
that are already written and known to work and making modifications
to them. We will start with the simplest of all asm programs, one
that does absolutely nothing! It is what is called a program template.
You will use such a template over and over, it saves you
from having to re enter all the preliminary stuff. Never start
an asm program from scratch, that is a waste of your time.

Here is a suitable program template for the AVR.
It is very basic and later I will create a more
complete version that sets up the stack address
and has place holders for interrupt routines.etc.


; ********************************************
; * Put program name here along with date                   *
; * written and any other pertinent info                         *
; ********************************************

.NOLIST
.INCLUDE "tn85def.inc"
.LIST

rjmp Start ; This is the reset vector


Start:
rjmp Start ; loop 4ever


Here is what this short program looks like in AVR Studio
when it is compiled.

This image shows how much memory has been used
by this short program. It only takes up 4 bytes of the
8192 bytes available in the Tiny85's flash memory.
Of course it doesn't actually do anything...it just causes
the AVR to continually execute the first instruction
that is located at the label Start: this is an identical rjmp
instruction that causes the program counter to load the
location of  Start:  and jump there....an infinite loop.
 When powered up the Tiny85 will execute the instruction
it finds at memory location zero (the reset interrupt vector
location) it finds an instruction there that loads the program
counter with the location of the Start: label    when the
Tiny85 gets to that location it finds another instruction
that simply points it again at the location of the Start:
label.



Start:    
rjmp Start

This simple program can actually be made smaller.
This works just as well.

; ********************************************
; * Put program name here along with date    *
; * written and any other pertinent info     *
; ********************************************

.NOLIST
.INCLUDE "tn85def.inc"
.LIST

Start:
    rjmp Start ; loop 4ever

This version uses only 2 bytes. But there is a very
good reason to include this line

rjmp Start ; This is the reset vector

The reason is that in the AVR the interrupt vectors
are all in low memory starting at location 0x000000
This first vector is called the reset vector and it is
the first instruction that is run whenever the Tiny85
is powered up or reset. It is best to place an rjmp
instruction here and jump to the start of your asm
program. You may need to come back and add some
rjmp instructions that point to a routine you wish to run
when another of the interrupts is triggered. The locations
that are meant to hold the vectors can be used for regular
program code as long as the interrupts will never be called!

Here is the interrupt chart from  the Tiny85 datasheet
Some people just add them all as sort of placeholders
whether they use them all or not...like this

    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

This takes up space that could be used by program
code, unless you need to use all 14 interrupts..this
is rarely the case. But some people just like to start
out with a list like this. If any interrupts are triggered
they jump to the corresponding reti (return from interrupt)
command and all is well. You can simply replace one
of the lines above with an rjmp command to cause
your code to be jumped to if a particular interrupt is
triggered...like so

reti ; Int vector 5

might be replaced by

rjmp MyTimer1OverflowCode


Here is the program with all the placeholders for
the interrupt vectors added.







This works just fine
but note that the memory usage is now at 32 bytes!





Now, probably it won't matter if you use up a few
extra bytes but I prefer to keep things trim. You
must be careful though to place a vector into the
proper location if you do not use placeholders and
later want to edit your asm and add an rjmp to a
new interrupt routine! You can use the org command to
make certain of where you place an interrupt vector.
This will place a new rjmp at the proper location
for interrupt 3, the pin change interrupt. (remember
that the memory is counted up from zero so the third
location is at $0002)

.ORG $0002
rjmp MyPinChangeCode









This entire program with the new int vector
for the pin change interrupt and the tiny
MyPinChange routine is only 8 bytes. Using
the .ORG moves your code that begins at Start:
farther up in memory so you are leaving some
bytes unused.

I think I will use the template version with the full
list of interrupt vector place holders for the time being.
I think it will be easier for newbies to understand with
them listed. Just be aware that once you get used to AVR
asm you don't have to do it this way. Just always remember
where these important vectors are in memory! The number
of interrupt vectors is different for different AVRs ..just
check the data sheet to see what and where they are.



More later...stay tuned :-)