Professional Documents
Culture Documents
http://www.instructables.com/id/Command-Line-Assembly-Language-Pro...
[2]
6/27/2015 11:33 PM
2 of 10
http://www.instructables.com/id/Command-Line-Assembly-Language-Pro...
If you haven't gone through Tutorial 1 you should stop now and do that one rst.
In this tutorial we will continue our study of assembly language programming of the
atmega328p used in Arduino's.
You will need:
1. a breadboard Arduino or just a normal Arduino as in Tutorial 1
2. an LED
3. a 220 ohm resistor
4. a push button
5. connecting wires for making the circuit on your breadboard
6. Instuction Set Manual: www.atmel.com/images/atmel-0856-avr-instruction-s...[3]
7. Datasheet: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco...[4]
6/27/2015 11:33 PM
3 of 10
http://www.instructables.com/id/Command-Line-Assembly-Language-Pro...
[5]
First you need to construct the circuit that we will be studying in this tutorial.
Here is the way it is connected:
PB0 (digital pin 8) ---> LED ---> R (220 ohm) ---> 5V
PD0 (digital pin 0) ---> pushbutton ---> GND
You can check that your LED is oriented properly by connecting it to GND instead of PB0. If
nothing happens then reverse the orientation and the light should come on. Then reconnect
it to PB0 and continue. The picture shows how my breadboard arduino is connected.
6/27/2015 11:33 PM
4 of 10
http://www.instructables.com/id/Command-Line-Assembly-Language-Pro...
[6]
Write the following code in a text le called pushbutton.asm and compile it with avra as you
did in Tutorial 1.
Notice that in this code we have plenty of comments. Every time the assembler sees a
semicolon it will skip the rest of the line and go on to the next line. It is good programming
practice (especially in assembly language!) to heavily comment your code so that when you
return to it in the future you will know what you were doing. I am going to comment things
quite a lot in the rst few tutorials so that we know exactly what is going on and why. Later
on, once we become a bit better at assembly coding I will comment things in a bit less detail.
;************************************
; written by: 1o_o7
; date: <2014|10|23>
; version: 1.0
; file saved as: pushbutton.asm
; for AVR: atmega328p
; clock frequency: 16MHz
;************************************
; Program function:-----------------------------; Turns on an led connected to PB0 (digital 0)
; when you push a button connected to PD0
;----------------------------------------------;
;
;
;
;
.nolist
.include "./m328Pdef.inc"
6/27/2015 11:33 PM
5 of 10
http://www.instructables.com/id/Command-Line-Assembly-Language-Pro...
.list
;==============
; Declarations
.def
temp
=r16
;=================
; Start of Program
rjmp
Init
;============
Init:
ser
temp
out
DDRB,temp
out
DDRD,temp
clr
temp
out
PortB,temp
PortD,temp
;======================
; Main body of program:
Main:
in
out
temp,PinD
PortB,temp
6/27/2015 11:33 PM
6 of 10
http://www.instructables.com/id/Command-Line-Assembly-Language-Pro...
;
rjmp
Main
Notice that this time we not only have many more comments in our code, but we also have a
header section which gives some information about who wrote it, when it was written, what
type of controller it was written for, and I have even included a simple circuit diagram to
show how you construct the circuit. The rest of the code is also separated into sections.
After you have compiled the above code you should load it onto the microcontroller and see
that it works. The LED should turn on while you are pushing the button and then turn off
again when you let go. I have shown what it looks like in the picture.
These three lines include the le containing the Register and Bit de nitions for the
ATmega328P that we are programming. The .nolist command tells the assembler not to
include this le in the pushbutton.lst le that it produces when you assemble it. It turns off
the listing option. After including the le we turn the listing option back on with the .list
command. The reason we do this is because the m328Pdef.inc le is quite long and we don't
really need to see it in the list le. Our assembler, avra, doesn't automatically generate a list
le and if we would like one we would assemble using the following command:
avra -l pushbutton.lst pushbutton.asm
If you do this it will generate a le called pushbutton.lst and if you examine this le you will
nd that it shows your program code along with extra information. If you look at the extra
information you will see that the lines begin with a C: followed by the relative address in hex
of where the code is placed in memory. Essentially it begins at 000000 with the rst
command and increases from there with each subsequent command. The second column
after the relative place in memory is the hex code for the command followed by the hex code
for the argument of the command. We will discuss list les further in future tutorials.
.def
temp
In this line we use the assembler directive ".def" to de ne the variable "temp" as equal to the
r16 "working register." We will use register r16 as the one which stores the numbers that we
want to copy to various ports and registers (which can't be written to directly).
6/27/2015 11:33 PM
7 of 10
http://www.instructables.com/id/Command-Line-Assembly-Language-Pro...
Exercise 1: Try to copy a binary number directly into a port or special register
like DDRB and see what happens when you try to assemble the code.
A register contains a byte (8 bits) of information. Essentially it is usually a collection of
SR-Latches each one is a "bit" and contains a 1 or a 0. We may discuss this (and even build
one!) later on in this series. You may be wondering what is a "working register" and why we
chose r16. We will discuss that in a future tutorial when we dive down into the quagmire of
the internals of the chip. For now I want you to understand how to do things like write code
and program physical hardware. Then you will have a frame of reference from that
experience which will make the memory and register properties of the microcontroller easier
to understand. I realize that most introductory textbooks and discussions do this the other
way around but I have found that playing a video game for a while rst and dicking around to
get a global perspective and then reading the instruction manual to get better at it is much
easier than reading the manual rst.
rjmp
Init
This line is a "relative jump" to the label "Init" and is not really necessary here since the next
command is already in Init but we include it for future use.
Init:
ser
temp
After the Init label we execute a "set register" command. This sets all of the 8 bits in the
register "temp" (which you recall is r16) to 1's. So temp now contains 0b11111111.
out
The register DDRB (Data Direction Register for PortB) tells which pins on PortB (i.e. PB0
through PB7) are designated as input and which are designated as output. Since we have the
pin PB0 connected to our LED and the rest not connected to anything we will set all the bits
to 1 meaning they are all outputs.
ldi temp,0b11111110
This line loads the binary number 0b11111110 into the temp register.
out
DDRD,temp
6/27/2015 11:33 PM
8 of 10
http://www.instructables.com/id/Command-Line-Assembly-Language-Pro...
Now we set the Data Direction Register for PortD from temp, since temp still contains
0b11111110 we see that PD0 will be designated as an input pin (since there is a 0 in the far
right spot) and the rest are designated as outputs since there are 1's in those spots.
clr
temp
out
PortB,temp
First we "clear" the register temp which means setting all of the bits to zero. Then we copy
that to the PortB register which sets 0V on all of those pins. A zero on a PortB bit means that
the processor will keep that pin at 0V, a one on a bit will cause that pin to be set to 5V.
Exercise 2: Use a multimeter to check if all of the pins on PortB are actually zero.
Is something weird going on with PB1? Any idea why that might be? (similar to
Exercise 4 below then follow the code...)
Exercise 3: Remove the above two lines from your code. Does the program still run
correctly? Why?
ldi temp,0b00000001
out
PortD,temp
Exercise 4: Remove the above two lines from your code. Does the program still run
correctly? Why? (This is different from Exercise 3 above. See the pin out diagram.
What is the default DDRD setting for PD0? (See page 90 of the data sheet)
First we "load immediate" the number 0b00000001 to temp. The "immediate" part is there
since we are loading a straight up number to temp rather than a pointer to a memory
location containing the number to load. In that case we would simply use "ld" rather than
"ldi". Then we send this number to PortD which sets PD0 to 5V and the rest to 0V.
Now we have set the pins as input or output and we have set up their initial states as either
0V or 5V (LOW or HIGH) and so we now enter our program "loop".
Main:
in
temp,PinD
The register PinD contains the current state of the PortD pins. For example, if you attached a
5V wire to PD3, then at the next clock cycle (which happens 16 million times per second
since we have the microcontroller hooked up to a 16MHz clock signal) the PinD3 bit (from
the current state of PD3) would become a 1 instead of a 0. So in this line we copy the current
state of the pins to temp.
6/27/2015 11:33 PM
9 of 10
http://www.instructables.com/id/Command-Line-Assembly-Language-Pro...
out PortB,temp
Now we send the state of the pins in PinD to the PortB output. Effectively, this means that
PD0 will send a 1 to PortD0 unless the button is pressed. In that case since the button is
connected to ground that pin will be at 0V and it will send a 0 to PortB0. Now, if you look at
the circuit diagram, 0V on PB0 means the LED will glow since the other side of it is at 5V. If
we are not pressing the button, so that a 1 is sent to PB0, that would mean we have 5V on
PB0 and also 5V on the other side of the LED and so there is no potential difference and no
current will ow and so the LED will not glow (in this case it is an LED which is a diode and
so current only ows one direction regardless but whatever).
rjmp
Main
This relative jump loops us back to our Main: label and we check PinD again and so on.
Checking every 16 millionth's of a second whether the button is being pushed and setting
PB0 accordingly.
Exercise 5: Modify your code so that your LED is connected to PB3 instead of PB0
and see that it works.
Exercise 6: Plug your LED into GND instead of 5V and modify your code
accordingly.
Step 4: Conclusion
In this tutorial we have further investigated the assembly language for the ATmega328p and
learned how to control an LED with a pushbutton. In particular we learned the following
commands:
ser register sets all of the bits of a register to 1's
clr register sets all of the bits of a register to 0's
in register, i/o register copies the number from an i/o register to a working register
In the next tutorial we will examine the structure of the ATmega328p and the various
registers, operations, and resources contained therein.
6/27/2015 11:33 PM
10 of 10
http://www.instructables.com/id/Command-Line-Assembly-Language-Pro...
Before I continue with these tutorials I am going to wait and see the level of interest. If there
are a number of people that are actually enjoying learning how to code programs for this
microprocessor in assembly language then I will continue and construct more complicated
circuits and use more robust code.
1. http://www.instructables.com/member/1o_o7/
2. http://cdn.instructables.com/F4I/UT4Q/I1P33YSI/F4IUT4QI1P33YSI.LARGE.jpg
3. http://www.atmel.com/images/atmel-0856-avr-instruction-se...
4. http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A88PA-168A-168PA-328-328P_datasheet_Complete.pdf
5. http://cdn.instructables.com/FM0/0MXY/I1P33YQ7/FM00MXYI1P33YQ7.LARGE.jpg
6. http://cdn.instructables.com/F5T/QZGJ/I1P33YPQ/F5TQZGJI1P33YPQ.LARGE.jpg
6/27/2015 11:33 PM