Assembler or other languages, that is the question. Why should I learn another language, if I already learned other programming languages? The best argument: while you live in France you are able to get through by speaking english, but you will never feel at home then, and life remains complicated. You can get through with this, but it is rather inappropriate. If things need a hurry, you should use the country's language.

Short and easy

Assembler commands translate one by one to executed machine commands. The processor needs only to execute what you want it to do and what is necessary to perform the task. No extra loops and unnecessary features blow up the generated code. If your program storage is short and limited and you have to optimize your program to fit into memory, assembler is choice 1. Shorter programs are easier to debug, every step makes sense.
Fast and quick

Because only necessary code steps are executed assembly programs are as fast as possible. The duration of every step is known. Time critical applications, like time measurements without a hardware timer, that should perform excellent, must be written in assembler. If you have more time and don't mind if your chip remains 99% in a wait state type of operation you can choose any language you want.

Assembler is easy to learn

It is not true that assmbly language is more complicated or not as easy to understand than other languages. Learning assembly language for whatever hardware type brings you to understand the basic concepts of any assembly language. Adding other dialects later is easy. The first assembly code does not look very attractive, with every 100 additional lines programmed it looks better. Perfect programs require some thousand lines of code of exercise and optimization requires lots of work. As some features are hardware-dependant optimal code requires some familiarity with the hardware concept and the dialect. The first steps are hard in any language. After some weeks of programming you will laugh if you go through your first code. Some assembler commands need some monthes of experience.

Test1: Learn to handle the board, output to the board LEDs via a port, basic structure of the assembly language, assembler directives and command. The LEDs will go on and off with 800 Hertz (what a useful example).

Test2 Reading input from a port, call a subroutine, setup and use of the stack by subroutines, binary math operations (AND, OR, ROL, etc.), branching and conditions (SBIx, BRxx). Pressing key 0 and 1 on the board should light up the LEDs 0 and 1, one of the other keys the LEDs 2 to 6, pressing key 7 shuts all the LEDs down (also a rather useful program).

Test3 Read the timer in polling mode, use the MOV command. A loop in the main program reads the hardware counter until it reaches zero, increments a software counter and displays its content in hex on the LEDs of the board (at least something like a clock).

Test4 Timer in interrupt mode, use interrupts, interrupt vectors, BCD-arithmetic. The main program loop waits until the upper byte of a software counter reaches hex 3D. Then it waits until the timer low byte reaches 09 (one second = 15625 decimal = 3D09 hex counter pulses). The counters are reset to zero and the second counter is incremented. The seconds are displayed on the LEDs as packed BCD digits (one digit=4 bits, one byte represents two digits). The seconds are reset to zero, if 60 is reached. The seconds are output for the LEDs.

Test 1: Learn to know parts of the board hardware output to the LEDs

; What to learn here:

; - to access a output-port (Port B and the LEDs)
; - the different parts of a typical assembler program

; General conventions used here:

; - Words in uppercase letters are command words of the assembler language
; or predefined ports of the processor.
; - Words in lowercase letters are defined by me.

; Assembler directive: define the target chip type

;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
; The directives NOLIST and LIST switch off the listing of the INCLUDE-file
; (the listing will be found in the file TEST1.LST).

; Define register

;
; This register is defined for the purpose of interim storage of values.
; The .DEF statement renames one of the 32 8-bit registers to a easier
; to remember name (here: mp). It is easier to use than its real name
; R16. Renaming these register also has the advantage that whenever you
; want to change such a location you'll just have to change the .DEF
; statement. Otherwise you would have to go through all commands re-
; ferencing the register R16 and change all these lines.
.DEFmp = R16

; Restart

;
; Up till now not one byte of code was created. Here we start with the
; first code, we define the program start adress. Later we will see, that
; this jump command at adress 0 is useful. Here the first byte of code is
; created.
; Whenever the AVR is restarted it starts its program execution at adress
; 0000. Such a restart may be activated by a power-on, by a hardware
; reset on the respective pin or by a watchdog-timer reaching its zero
; count. (The watchdog timer is not used here.)
; In all these cases a jump to a program called "main" will be executed.
; RJMP means "Relative Jump". In a relative jump a relative distance
; is added to the current execution adress and the program is executed
; at this new adress. We don't have to care about this distance by now
; because the assembler calculates this relative distance from the information
; in our source code and adds it automatically - as long as the maximum
; permissible distance of 2 kB for- or backwards is not exceeded, otherwise
; the assembler stops with an error message.
RJMPmain
; Here we start with our main program code. First we have to define a
; label, because the assembler has to know that this is the target of a
; jump. A label is a freely defined name, followed by ":". For a better
; overview labels start in column 1 of a line, all commands start with a
; blank or a tab character. Behind the label there could be a command,
; but this is not used here.
main:
; First we need to define port B as output, because the LEDs are connected
; to these port pins. This is done by writing eight ones to the data direction
; register of port B. The data direction register of port B is named DDRB,
; we don't have to care about its real adress, as the .def-file holds this
; information already. We do that in two steps. First we load binary 1111.1111
; to a register:
LDImp,0b11111111
; The command LDI (LoaD Immediate) loads an 8-bit value into the register
; mp. This command is only valid for the registers R16 to R31. That is why we
; defined mp that way at the beginning of this source code file. Commands
; with two parameters are generally defined such that the first parameter
; is the target (here: register mp), where the result of the operation goes to.
; The second parameter is the value or location where the result comes from.
; After execution of this command the register mp has the value 1111.1111
; binary, FF hex or 255 decimal.
; The 0b... of the beginning of the number is always a binary, 0x... is a hex
; notation. The leading zero is the signal for the assembler to expect a number,
; not a register or something else. Numbers without 0b... or 0x.. are decimal
; by default. (LDI mp,255 would have the same result.)
; This value has to be brought to the data direction register of port B now
; to make all port pins to outputs. A 1 in the data direction register brings
; the pin to switch on its output drivers, a zero makes it an input.
OUTDDRB,mp
; The command OUT writes register values (here: mp or R16) to a port
; (here DDRB). DDRB is defined in the file "8515def.inc", which is already
; read by the assembler when the .DEVICE-command or the .INCLUDE-
; command above has been processed. So we don't need to care here
; for the real adress of this port.
; The following part of the program now writes zeros and ones to the port.
; The LEDs are switched on and off with a high frequency. Because this
; part of the program is repeated over and over again, I called it loop.
; The label loop is jumped to whenver the processing of writing ones and
; zeros is ended.
loop:
LDImp,0x00
OUTPORTB,mp
; LDI load eight zero bits to the universial register mp. OUT copies these
; zeros to the port B. This time they are written to the port's output register
; named PORTB.
; The zeros set the LEDs on, because they are connected to the supply
; voltage over resistors of 1 k (0=on, 1=off).
LDImp,0xFF
OUTPORTB,mp
; After that eight ones are loaded into the register mp and copied to
; the same data port. That switches the LEDs off.
RJMPloop
; With this relative jump we jump back to the start of the loop and the
; loop is repeated as long as power is supplied.
; At 4 MHz xtal frequency every LDI- and OUT-command execution requires
; 250 ns, the RJMP need 2 cycles and 500 ns. Every 1,500 ns the loop is
; executed once, so with these values the LEDs are switched at 667 kHz.
; After assembling this sourcefile the program will have eight words.
; The file TEST1.LST holds the result of the assembling process in form
; of a listing.

Test 2: Learn to more about the board: Input from a port

; What to learn here:

; - to read input from a port
; - call subroutines and setup the stack
; - Binary math operations like AND, OR, ROL, etc.
; - Conditional branches (commands SBIx, BRxx)
.NOLIST
.INCLUDE "8515def.inc"
.LIST

; Define a universal register:


.DEFmp = R16

; The jump-command on adress 0 again:


RJMPmain

; The main program starts here:


main:LDImp,LOW(RAMEND) ;Initiate Stackpointer
OUTSPL,mp
LDImp,HIGH(RAMEND)
OUTSPH,mp
These commands initiate the stack in the build in SRAM. Stack operations
; are always necessary when subroutines or interrupts are called.
; By calling the subroutine or interrupt handling routine the actual adress
; is written to the stack in order to later jump back to the code where the
; interrupt or call occurred. The stack is located at the upper end of the
; build in SRAM. The upper end of the SRAM is called RAMEND and is defined
; in the file "xxxxdef.inc" for the respective processor type, so we do not
; have to care about its real value.
; If a byte is disposed on the stack it is written to the SRAM location and the
; stack pointer at adress SPH:SPL (a 16 bit value) is decremented to the next
; lower stack location. Further disposing bytes brings this pointer nearer
; to the beginning of the SRAM. If a byte is taken from the stack then the
; stackpointer is incremented first and then the value is read.
; The last value put on the stack is read first when the stack is read, called
; a Last-In-First-Out structure.
; As the program counter and the adress structure requires 16 bits and
; all registers and the SRAM are 8 bits wide, every adress on stack requires
; two write/read operations to process the 16 bits. The SRAM adress is 16
; bits wide, so the port SPL holds the lower 8 bits and the port SPH holds
; the upper eight bits of the stack adress. Togeter we get the pointer SPH:SPL
; as a 16 bit pointer to the stack adress.
; The operations LOW and HIGH provide the opportunity to commincate to
; the assembler that the lower or upper byte of RAMEND is meant when
; we set up the stack pointer ports with the RAMEND value.
; Port D is connected to the eight switches on the board. In order to
; read these switches these pins have to have a zero in their data direction
; register
LDImp,0x00 ; 8 zeros in universal register
OUTDDRD,mp ; to data direction register
; The switches connect the inputs of port D with GND. In order to provide
; a clear logical 1 when the key is open pull-up resistors have to be added.
; On board the STK200 are external pull-ups, so we don't need the internal
; resistors. Those resistors are build in the chip, so we can switch them
; on by software action. This is done by writing ones to the port register:
LDImp,0xFF ; 8 Ones into the universal register
OUTPORTD,mp ; and to port D (these are the pull-ups now!)
; Port B connected to the LEDs is again output, so we need to set its direction
; register.lOn startup we want the LEDs to be all off, so we need to write ones
; to the port output registers, too.
LDImp,0xFF ; 8 Ones to the universal register
OUTDDRB,mp ; and to the data direction register
OUTPORTB,mp ; and to the output registers.
; Clicking the keys 0 and 1 should switch on the corresponding LEDs,
; the keys 2 to 6 all the other LEDs. Clicking key 7 swiches all LEDs off.
; Within the main loop the switches are read and, if the different conditions
; are met, branched to the different subroutines.
loop:
; Reading switch 0 (very easy first)
; The first command (SBIS) reads port D (PIND) and tests if the bit 0 is
; one. If so, the next command is skipped. This is the case, if the switch
; is open and the input pin is pulled to one by the pull-up. If the switch
; is on, the pin reports zero and the condition for branching is not fulfilled.
; So the next command after SBIS must be a single byte command that
; branches to the routine that sets LED 0 on. This must be a subroutine,
; as it has to come back after execution, because we have to process the
; other switches as well.
; This subroutine is further down in the source code, the assembler cares
; about the displacement for the RCALL command. The RCALL pushes the
; current adress on stack, so the subroutine can come back to the next