Introducing the Atmel AVR Microcontroller

Topics

AVR Links


Introduction

What is a microcontroller unit (MCU)? An MCU is a complete computer in a single chip. Physical sizes range from a miniscule 8-pin package, 5×5 mm square, to as large as a 30×30 mm square package with 50 to 100 or more pins. MCUs are used in embedded applications meaning that they are used in any application that requires computational power. Applications are widespread, including wristwatches, calculators, telephones, cellular phones, TVs, VCRs, camcorders, dishwashers, microwave ovens, computers, computer equipment, printers, scanners, modems, electronic toys and games, scientific equipment, test equipment, data recorders, industrial controllers, etc. An embedded system is distinct from a personal computer (PC) in that while a PC uses an operating system (OS) such as Windows or Unix to allow the user to run any one of many application-programs, an embedded system is designed to run a single application. It may or may not require an operating system to achieve this. While an MCU may provide a compact and low cost solution to many embedded applications, there are some situations where even a PC (or a single-board PC) may serve as an embedded system. A few examples are POS (point-of-sale) cash register, ATM (automated teller machine), airline reservation terminal, laser printer engine, network server etc.


MCUs come with a variety of features including read-write memory, erasable and non-erasable memory, timers, counters, real-time clocks, serial interfaces, parallel interfaces, analog to digital converters (ADC), digital to analog converters (DAC), analog comparators, pulse-width modulation (PWM) outputs, etc. The requirements of the embedded system obviously depend on the application. For example, a high-speed modem and a compact disk (CD) player both require high-speed analog recording and data processing. An MCU with digital signal processing (DSP) capabilities that can perform high-speed numeric computation is essential. On the other hand, a laser printer engine and a network server both have to handle huge amounts of data and therefore large memories and hard disk drives are required.

Atmel AVR

The Atmel AVR MCUs compete directly with other popular chips from various manufacturers such as

Where are these chips used? Single chip MCUs are embedded in everyday appliances, instruments, equipment, controllers, data loggers etc., where low size, cost and power consumption are important.

The Atmel AVR family of microcontrollers uses a common core with some variations implemented in over 30 different devices. We will focus our attention on the low cost, small package varieties, in particular, the ATtiny11, ATtiny12, ATtiny15, AT90S1200, AT90S2343, AT90S2313 and AT90S4433.

What are we looking for? In order to focus on specific chips we will be looking at chips with the following properties:


Architectural Summary

This section summarises the important features of the AVR family. Note that individual MCUs may differ in some areas.

Summary of Features

 

ATtiny11

ATtiny12

ATtiny15

AT90S1200

AT90S2343

AT90S2313

AT90S4433

Clock Speed MHz

0-6

0-8

1.6

0-12

0-10

0-10

0-8

Number of pins

8

8

8

20

8

20

28

Number of I/O pins

6

6

6

15

5

15

20

RAM        

128

128

128

EEPROM  

64

64

64

128

128

256

FLASH

1K

1K

1K

1K

2K

2K

4K

On-chip Oscillator

YES

YES

YES

YES

YES

   
UART          

YES

YES

1st Timer

8-bit

8-bit

8-bit

8-bit

8-bit

8-bit

8-bit

2nd Timer    

8-bit

   

16-bit

16-bit

Interrupts

4

5

8

3

2

10

14

External Interrupts

1

1

1

1

1

4

4

PWM Output    

YES

   

YES

YES

Analog Comparator

YES

YES

YES

YES

YES

YES

YES

10-bit A/D Channels    

4

     

6

Input Capture          

YES

YES

Output Compare          

YES

YES


Programming the AVR MCU

The Atmel AVR MCUs are usually programmed from a host computer such as a desktop PC. Compilers and assemblers are available which will allow you to program in assembly language, BASIC or C. A special programming board, hardware and/or cable is required in order to program your target chip via the PC. This can be in the form of a commercial programmer such as (a) the STK500 from Amtel, (b) a low cost serial programmer from DMI, or (c) a DIY (do-it-yourself) cable that plugs into the parallel port of your PC. No special high voltage is required for programming.

Atmel implements its In-System Programming (ISP) using either a parallel programming mode or a low-voltage serial programming mode. Both EEPROM Data memory and Flash Program memory can be programmed while the MCU is in-circuit. This means that the MCU chips can be directly soldered (DIP or SMD packages) to the printed circuit board and do not require removal for programming or reprogramming.

The serial programming mode uses the Serial Peripheral Interface (SPI). In all, four signals, MISO, MOSI, SCK and RESET are required for serial programming. The DMI serial programmer connects to the RS-232 serial communications port of the host PC and relays the programming commands to the SPI bus of the target MCU.

Programming in BASIC or C has its advantage such as fast software development. However it does come with a price. First of all you have to find a compiler that works. Secondly, code written in BASIC or C always run more slowly and take up more program memory space than the same code written in assembler. All embedded MCU applications involve a lot of bit-manipulation. It is much more efficient from the MCU's perspective if the code is written in assembler. Think twice before using floating-point arithmetic. Libraries required to support floating-point arithmetic take up a lot of memory space.

A PC hosted AVR assembler and Windows IDE (integrated developement environment) is available from DMI for software development in assembly language. Object code is transferred to the target MCU via a single mouse click.


Getting Started

Photographs

  1. DMI AVR Serial Programmer and AT90S2313 Target Board
  2. Programmer connected to PC and Target Board
  3. Programmer used to program a Programmer Board as Target
  4. AT90S2313 Board with LCD

You will need the following:

  1. DMI AVR Serial Programmer board
  2. DMI AVR Target MCU board
  3. Serial 9-pin extension cable (male connector on one end, female on the other)
  4. 9V to 12V DC power supply
  5. XAVR Assembler software on CD-ROM

Set up the hardware as follows:

  1. Connect the serial cable between the Programmer Board and any COM port of your PC.
  2. Connect the Target MCU Board to the Programmer Board using the 10-pin ribbon cable. See photo.
  3. Apply +9V DC (RED) and Ground (BLACK) to the Target Board.

Before starting the WinIDE program, copy the XAVR folder from the CD-ROM to your hard disk. Go to the XAVR folder on your hard disk and right-click on the file called WinIDE.ini. Select Properties and change the Attributes in the WinIDE.ini Properties dialog so that the Read-Only box is disabled. Click OK to dismiss the dialog.

Create a copy of the WinIDE.exe icon and place it on your desktop for easy access.

  1. Start the WinIDE program.
  2. Setup which COM port is to be used by selecting Environment, Setup Environment..., EXE2 (Programmer) and changing the Options to show %FILE% /L2 /E where the "2" means COM2, for example. (/E means erase the MCU before programming).
  3. Go to File, Open File... and select and Open the file called example1.asm
  4. Program your target MCU by clicking on the Programmer (EXE2) button.

If everything is working you should be able to observe on an oscilloscope a 2MHz signal consisting of a 125ns HI pulse and 375ns LO interval on all pins 12 to 19 of the target AT90S2313 MCU. If you do not have an oscilloscope then repeat the above using the file called example2.asm. This program uses the 16-bit Timer/Counter1 to pulse PORTB at a rate of once every second. Use the simple LED test probe shown below to verify that this is working.

Sample Programs

Example #1 shows the simplest program to toggle all the pins on PORTB. This is a simple way to test the WinIDE, Assembler, Programmer and all programming connections. Connect an oscilloscope to any one of pins 12 to 19 of the target AT90S2313 MCU and observe a 2MHz waveform.

Example #2 allows you to test the WinIDE, Assembler, Programmmer and connections using a simple LED logic probe. Connect the LED test probe to any one of pins 12 to 19 of the target AT90S2313 and observe that the LED flashes once every second.

Example #3 demonstrates how to use the serial port to communicate with a host PC. The communications protocol is set for 9600 baud, 8 bits, no parity. Interrupts are not used in this example. Use a terminal emulator program such as HyperTerm (Hypertrm.exe) to test this program. On power up, the AVR MCU should output a message and then echo any characters send from the PC's keyboard.

Example #4 contains subroutines which will allow a program to output text information to a liquid crystal display (LCD). The interface is a common 14-pin connection used by many different LCDs. Here are some examples of compatible LCD modules.

Manufacturer Model Display Format
Sharp LM16255 16 characters × 2 lines
Optrex DMC16117 16 characters × 1 line
Optrex DMC16207 16 characters × 2 lines
Optrex DMC20434 20 characters × 4 lines


Programming Model

Single chip MCUs generally have about 4 working registers or accumulators, namely, an A and B register and perhaps two index registers X and Y. All arithmetic and logic operations are performed using these registers. Motorola's 6805 and 68HC11 family of MCUs are memory based and allow arithmetic and logic operations on memory and input/output addresses just as if they were registers.

The Atmel AVR MCU uses a Harvard RISC architecture with 32 working registers. This architecture is designed for speed. Arithmetic and logic operations are restricted to the registers and are not allowed on memory locations. This has a serious impact on they way we program the AVR MCU. In general, programs written for MCUs in embedded controller applications tend to be small or medium sized. The need for large variable space is not great. This need could very well be accommodated by the 32 registers on the AVR. Therefore the tendency is to dedicate a specific register for a specific variable, for example, a loop counter. Unfortunately, there are some restrictions with the AVR instruction set.

Here is some tips. Registers 0 to 15 are somewhat restricted. Therefore use registers 16 to 25 as your general purpose registers. Reserve registers 26 to 31 for indexed operations. Use registers 1 to 15 for arithmetic functions and data storage. Register 0 is reserved for the LPM instruction. Here is a summary.

Register Usage
0 LPM instruction
1-15 Math functions and program variables
16-25 General purpose registers, loop counters
26-31 Indirect and indexed operations for accessing memory, arrays and strings

This discussion really only applies to global variables and passing parameters to and from subroutines. Bare in mind that a subroutine can still use any register locally. It is good programming practice to push the register on to the stack before using and restore it before returning from the subroutine using the PUSH and POP instructions.

Instruction Set Summary

AVR Instruction Set Summary

All instructions are one (16-bit) word in length except the LDS and STS instructions which are two words in length. Instructions are grouped into the following categories:

Inherent Instructions

With inherent instructions, no operand is required since the register that will be affected is implied.


Operations on the Status Register (SREG)  
  CLC Clear Carry  
  SEC Set Carry  
  CLN Clear Negative flag  
  SEN Set Negative Flag  
  CLZ Clear Zero flag  
  SEZ Set Zero flag  
  CLS Clear Signed test flag  
  SES Set Signed test flag  
  CLV Clear 2's complement overflow  
  SEV Set 2's complement overflow  
  CLH Clear Half carry flag  
  SEH Set Half carry flag  
  CLT Clear T flag (not available)  
  SET Set T flag (not available)  
  CLI Disable global interrupts  
  SEI Enable global interrupts  
       
Branch Instructions Alternatives
  IJMP Indirect Jump PC Z  
  ICALL Indirect Call PC Z  
  RET Return from subroutine RTS
  RETI Return from interrupt RTI
       
Miscellaneous  
  LPM Load from program memory R0(Z)  
  NOP No Operation  
  SLEEP Sleep  
  WDR Watchdog Reset  

Immeditate Instructions

Immediate instructions operate on a single register using a constant value which is part of the instruction. Note that there are restrictions to which registers can be used.

  LDI reg, K Load Immediate registers 16-31
  ANDI reg, K AND with constant registers 16-31
  ORI reg, K OR with constant registers 16-31
  SUBI reg, K Subtract constant from register registers 16-31
  SUBCI reg, K Subtract Carry and constant from register registers 16-31
  CPI reg, K Compare register with constant registers 16-31
  SBR reg, mask Set bits in register specified by mask registers 16-31
  CBR reg, mask Clear bits in register specified by mask registers 16-31
  ADIW reg, K Add 6-bit constant to word register pairs 24, 26, 28, 30
  SBIW reg, K Subtract 6-bit constant from word register pairs 24, 26, 28, 30

Arithmetic and Logic Operations on a single register

  PUSH reg Push register on to the Stack  
  POP reg Pop register from the Stack PULL
  LSL reg Logical Shift Left  
  LSR reg Logical Shift Right  
  ROL reg Rotate Left through Carry  
  ROR reg Rotate Right through Carry  
  ASR reg Arithmetic Shift Right  
  SWAP reg Swap Nibbles  
  COM reg One's Complement  
  NEG reg Two's Complement  
  INC reg Increment  
  DEC reg Decrement  
  TST reg Test for Zero or Minus  
  CLR reg Clear to $00  
  SER reg Set to $FF Registers 16-31

Arithmetic and Logic Operations using two registers

  MOV Rd, Rr Move RdRr
  ADD Rd, Rr Add RdRd + Rr
  ADC Rd, Rr Add with Carry RdRd + Rr + C
  SUB Rd, Rr Subtract RdRd - Rr
  SBC Rd, Rr Subtract with Carry RdRd - Rr - C
  AND Rd, Rr Logical AND RdRd · Rr
  OR Rd, Rr Logical OR RdRd v Rr
  EOR Rd, Rr Exclusive OR RdRdRr
  CP Rd, Rr Compare Rd - Rr
  CPC Rd, Rr Compare with Carry Rd - Rr - C
  CPSE Rd, Rr Compare and skip if equal skip if Rd = Rr

Data Transfer Instructions

These are a powerful group of instructions used to read (load) or write (store) to data memory. Important features to note are:

The SRAM memory or data segment is the assumed memory. The exception to this is the LPM instruction which is used to read a byte stored in the code segment or program memory (flash memory). Since the program memory space is read-only there is no store instruction to write to program space.

The LD and ST instructions use the index registers X, Y and Z. Therefore the listing here only shows the instructions for the Y-index register. The LDD and STD instructions use a memory address which is computed as the contents of the index register (Y or Z) plus a 6-bit (a range from 0 to 63). The LDD and STD instructions are not available with the X-index register. Note that the flags in the status register (SREG) are not affected.

The small versions of the AVR MCU discussed here contain up to 128 bytes of SRAM. Therefore the upper byte of the index register is usually zero.

The LPM instruction is a special case for reading a byte from program space. The Z register is loaded with the 16-bit byte-address. The byte from program space is read into register R0. In this case the upper byte cannot be assumed to be zero. To increment the Z register the following instruction should be used since this operates on the 16-bit register-pair:

ADIW Z, 1

This instruction adds 1 to the R30-R31 register-pair (assuming that Z is declared as R30). The LPM instruction is instrumental in implementing look-up tables, constant strings, arrays and jump tables.

  LPM   Load data from code segment (Z) R0(Z)
  LDS reg, label Load register from SRAM (data segment) reg(label)
  STS label, reg Store (data) SRAM with register (label)reg
  LD reg, Y Load register from (Y)  
  LD reg, Y+ Load register from (Y) and increment Y  
  LD reg, -Y Decrement Y and Load register from (Y)  
  LDD reg, Y + disp Load register from (Y + disp)  
  ST Y, reg Store register to (Y)  
  ST Y+, reg Store register to (Y) and increment Y  
  ST -Y, reg Decrement Y and Store register to (Y)  
  STD Y +disp, reg Store register to (Y + disp)  

Input/Output Instructions

Input/Output instructions are used to exchange data between a register and an input/output port or to set or clear individual bits of a port.

  IN reg, port Input from port regport
  OUT port, reg Output to port portreg
  SBI port, bit Set bit of port to 1  
  CBI port, bit Clear bit of port to 0  

Note that the SBI and CBI instructions operate on I/O registers $00 to $1F only.

Skip Instructions

Skip instructions allow the program to redirect the program flow based on the condition of a single bit in a register or input/output port. If the condition is satisfied then the next instruction is skipped. Most often (but not necessarily) the next instruction will be an unconditional branch (JMP) instruction. Note that the flags in the status register (SREG) are not affected.

  CPSE Rd, Rr Compare and skip if Rd = Rr  
  SBRS reg, bit Skip if Bit in Register is Set  
  SBRC reg, bit Skip if Bit in Register is Cleared  
  SBIS port, bit Skip if Bit in I/O port is Set  
  SBIC port, bit Skip if Bit in I/O port is Cleared  

Note that the SBIS and SBIC instructions operate on I/O registers $00 to $1F only.

Branch Instructions

Branch instructions allow the program to branch to another location (label) if the branch condition is true. This is a relative branch and the range of the destination label is limited to -64 to +63 instructions away from the branch instruction. (The BRBS and BRBC instructions have not been listed below since these two are the general cases for the branch instructions listed below and are never needed.)

        Equivalent mnemonics
  BREQ label Branch if Equal BEQ
  BRNE label Branch if Not Equal BNE
  BRCS label Branch if Carry is Set BCS, BLO
  BRCC label Branch if Carry is Cleared BCC, BRSH, BHS
  BRSH label Branch if Same or Higher BHS, BRCC, BCC
  BRLO label Branch if Lower BLO, BCS
  BRPL label Branch if Plus BPL
  BRMI label Branch if Minus BMI
  BRGE label Branch if Greater or Equal, signed BGE
  BRLT label Branch if Less than, signed BLT
  BRHS label Branch if Half Carry is Set BHCS
  BRHC label Branch if Half Carry is Cleared BHCC
  BRTS label Branch if T flag is Set  
  BRTC label Branch if T flag is Cleared  
  BRVS label Branch if Overflow flag is Set BVS
  BRVC label Branch if Overflow flag is Cleared BVC
  BRIE label Branch if Interrupt is Enabled  
  BRID label Branch if Interrupt is Disabled  

Unconditional Branch Instructions

These instructions are used to redirect the program flow using jumps or subroutine calls.

        Equivalent mnemonics
  RJMP label Jump to label BRA, JMP
  IJMP   Jump to (Z)  
  RCALL label Call subroutine BSR, JSR, CALL
  ICALL   Call subroutine at (Z)  
  RET   Return from subroutine RTS
  RETI   Reurn from Interrupt RTI

NOTES

Data transfer instructions MOV, LD, LDI, LDD, LDS, LPM, IN, POP etc. do not affect the SREG flags. Therefore to test the value of a register after a load instruction requires a TST, CP, CPC, CPI etc. instruction to be executed first before performing a conditional branch.


Programming Tips

Tip #1

Never use the actual register number in the instruction, for example,

  MOV 3 4
  LDI 16 7

This could easily lead to confusion and programming errors. One choice is to define all the registers by names such as the following:

R0 EQU 0
R1 EQU 1
R2 EQU 2

A better idea is to use appropriate variable names such as the following:

A EQU 16
B EQU 17
char EQU 18
COUNT EQU 20
X EQU 26
Y EQU 28
Z EQU 30

This makes the program easier to read and also allows you to easily change your register usage without having to check each line of your program. Examples:

  LDI A 7
  ADD B A
  LDI Y message
  LD char Y+

Tip #2

Remember that the order of the parameters is always

operator destination source

Tip#3

Data movement instructions such as MOV, LD, POP and IN do not affect the flags of the status register (SREG). To test for zero or minus you must use the TST instruction before the conditional branch instruction.

Tip #4

Note that the following instruction is a valid one:

  ADD A 6

But it may not result in what you might expect. This instruction adds the contents of Register 6 to the contents of the register declared as A. There is no ADD Immediate (ADDI) instruction (and this is unfortunate). You could use the following instead but the intent is not so obvious.

  SUBI A 250 ;since -6 = 256-6

Tip #5

Input from a hardware port such as PORTB or PORTD must use the address of the input port such as PINB and PIND.

Tip #6

The instructions SBI, CBI, SBIS and SBIC operate on input/output registers at addresses 0 to 31 only.

Tip #7 - MCUs without SRAM

MCUs that contain no SRAM space (ATtiny11, ATtiny12, ATtiny15, AT1200) have a severe limitation. Firstly, there is no storage for program variables. Registers have to be dedicated for global variables. A much more severe limitation is that there is no space for a stack. These MCUs utilize a 3-level hardware stack which will severly limit the use of modular programming, that is, nested subroutine calls and storing working registers on to the stack. When using these MCUs, here are points to remember.

  1. Global variables must be kept in registers dedicated for those purposes.
  2. Do not PUSH or POP registers using the stack. Use registers for temporary storage instead.
  3. Allow registers to be altered between subroutine calls but keep track of register usage.
  4. Do not nest subroutine calls more than two levels. (Two calls plus one level for interrupts.)

Tip #8 - Hardware Differences

When switching from one AVR model to another always double check the I/O register addresses and interrupt vector assignments. These are different from one model to another.



XAVR Assembler

Byte-addresses and word-addresses

Even though the AVR MCU fetches 16-bit instructions, load and store instructions will only access 8-bit data in and out of memory. The assembler will assign byte-addresses to labels declared in DATA and EEPROM segments. That is, the byte-address is the location of the byte in SRAM or EEPROM.

In CODE segments (program memory space) word-addresses will be generated and assigned to programming labels, except if the label is on a line with one of the following pseudo-op:

FCB, DB, FCC, FCS

FCW, FDB, DW

In these exceptional cases a byte-address is generated and assigned to the label.

A byte-address is the word-address shifted one bit to the left. When a double byte is stored in any segment (FCW, FDB, DW) the assembler will pack the LSB first followed by the MSB. In the CODE segment, the byte-address generated is always even, i.e. bit-0 is set to zero. A byte-address with bit-0 equal to 0 points to the LO-order byte (LSB). A byte-address with a one in bit-0 points to the HI-order byte (MSB). This allows the LPM (Load Program Memory) instructions to be used directly.

For example:

LDI X byte-address

LPM

Differences between HC11 and XAVR Assembler

1. As indicated in the examples above, the AVR syntax specifies the destination operand before the source operand. That is, the format of the instruction is:

operator destination source

2. The XAVR assembler does now allow assembly-time arithmetic such as

LDS A label + 1

For example, on the HC11 it is possible to do the following:

num DS 2 ;declare num as 2 bytes
       
  LDA num ;get hi-byte of num
  LDB num + 1 ;these two can be combined as LDD num

The XAVR assembler does not allow assembly-time arithmetic. Therefore each byte address of a multi-byte variable must be declared. Since the "dot" is an allowed character, one scheme is shown in the following example:

D.L EQU 18 ;declare D register lo-byte
D.H EQU 19 ;declare D register hi-byte
num.L DS 1 ;declare lo-byte of num
num.H DS 1 ;declare hi-byte of num
       
  LDS D.L num.L ;get lo-byte of num
  LDS D.H num.H ;get hi-byte of num


3. The XAVR assembler has three new segment declarations DATA, EEPROM and CODE for placing data into the three memory areas.

4. The XAVR assembler has two new directives LO and HI for generating the LSB and MSB of a byte address.


Migrating from the Motorola HC11 to the Atmel AVR

Ignore this section if you have not used the Motorolal HC11.

Comparing the MC68HC811E2 with the AT90S4433

 

MC68HC811E2/HC711E9

AT90S4433

ATmega8

Max Clock Speed MHz

8

10

16

MIPS (Million Instructions/Second)

0.5

10

16

RAM

256/512

128

1K

EEPROM

2K/512

256

512

Program Memory

0/12K

4K

8K

Package

52-pin PLCC

28-pin DIP, 32-pin TQFP

28-pin DIP, 32-pin TQFP

Number of I/O Pins

42

20

32

1st Timer

16-bit

8-bit

2 × 8-bit

2nd Timer  

16-bit

16-bit

Real Time Counter

1

 

1

UART

1

1

1

SPI

1

1

1

Channels of A/D

8

6

6/2

Number of A/D bits

8

10

10/8

Analog Comparator  

1

1

Input Capture functions

4

1

1

Output Compare Functions

4

1

2

PWM Outputs

4

1

3

Hardware Multiply

YES

 

YES

At the time of writing (Nov. 2001) the Motorola MC68HC811E2CFN2 has been discontinued and has been replaced by the MC68HC711E9CFN2 which comes with 12K OTP (one-time programmable) PROM, 512 bytes RAM and 512 bytes EEPROM. A more fair comparison would be a comparison with the Atmel AT90S81515, AT90S8535, ATmega8 and ATmega16.

Two noticeable advantages the HC11 has over the AVR are:

  1. The ability to perform operations on RAM locations as if they were registers.
  2. Double byte (16-bit) operations.

The advantages of using the AVR over the HC11 are cost, package size and speed.

Converting HC11 code to XAVR code

To a very large extent it is very easy to convert HC11 code to AVR. Most instructions have a direct equivalent. To make life easier, many of the HC11 mnemonics have been retained in the XAVR assembler. For example, BSR, JSR, RCALL and CALL generate the same code on the XAVR.

Here are some examples of direct translations from HC11 to AVR.

HC11 Syntax AVR Syntax
Immediate Addressing  
LDA #$3F LDI A $3F
CMPA #98 CPI A 98
   
Direct RAM addressing  
LDA num LDS A num
STB num STS num B
   
Indexed Addressing  
LDA 0,Y LD A Y
LDA 1,Y LD A Y 1
STA 0,Y ST Y A
STB 1,Y ST Y 1 B
   
Register-register operations  
TAB MOV B A
TBA MOV A B
   
Register Operations  
CLRA CLR A
PSHA PUSH A
PULA PULL A
   
Input/Output  
LDA #$FF LDI A $FF
STA PORTD OUT PORTD A
   
LDA PORTB IN A PINB
   

Note that in general the AVR syntax is: operator destination source


Idiosyncrasies of the AVR instruction set

1. Set/Clear Interrupts - This is actually an idiosyncrasy of the HC11 MCU. The HC11 uses an interrupt MASK. Therefore CLI clears the interrupt mask (enables interrupts) and SEI sets the interrupt mask (disables interrupts). With the AVR, SEI enables interrupts and CLI disables interrupts.

2. Unlike the HC11, the LD and ST instructions do not affect the flags in the status register. In order to branch on a zero/non-zero or positive/negative value of a variable loaded from RAM you must use the TST instruction first, for example:

HC11 Syntax AVR Syntax
   
LDA num LDS A num
BEQ iszero TST A
  BEQ iszero

3. An input port uses a different address (e.g. PINB) from the output port (e.g. PORTB). Reading the input port reads the actual logic input at the input pins.

4. Arithmetic and Logic instructions are not available on all 32 registers. Registers 16 to 31 are privileged as most instructions apply to these. Reserve these as your general purpose registers. Registers 26-27, 28-29, 30-31 are used for indexed and indirect address and should be reserved for these purposes.

The following instructions are not available on registers 0-15:

LDI CPI ANDI ORI SUBI SBCI SBR CBR SER


5. The instructions CLR (Clear Register) and SER (Set Register) are of questionable value.( Both of these are not extra instructions in any case since CLR is actually EOR reg,reg and SER is LDI reg,$FF).

6. Skip on register bit set or clear (SBRS, SBRC) can be useful instructions. Unfortunately, the instructions to set and clear register bits (SBR, CBR) do not use the bit-number but use a bit-mask instead. This means that programs have to create constants for both the bit-number as well as the bit-mask. (Note that SBR is the same as ORI in any case). It would have been nicer to have SBR and CBR use a bit-number just as the SBI and CBI instructions.

7. Set and Clear bit in I/O register (SBI and CBI) and Skip if Bit in I/O register is Set or Clear (SBIS and SBIC) operate on I/O addresses 0 to 31 ($00 to $1F) only. You cannot use these instructions on registers involving the timers, input capture, output compare, interrupt flag and mask, MCU control register, watchdog timer and the status register.

8. An ADDI (Add Immediate) instruction is noticeably missing and would be desirable.

9. A LDI (Load Immediate) and CPI (Compare with Immediate) on all registers would have been nice. This would have allowed all of the registers to be usable as general purpose registers.

10. ADIW (Add Immediate to Word) and SBIW (Subtract Immediate from Word) have four idiosyncracies:

  1. They operate on a pair of registers (16 bits).
  2. Only registers 24-25, 26-27, 28-29, 30-31 are allowed.
  3. The immediate value is restricted to 6 bits (0-63).
  4. Register pair 24-25 is of questionable value.

11. Register-0 is the implied destination of the LPM (Load Program Memory) instruction.

12. The SBC (Subtract with Carry) instruction does not change the Z-flag if the result of the subtraction is zero. If the result is non-zero the Z-flag is cleared.


Appendix

Drawings

AVR Serial Programmer Version 1

Schematics

Board Layout

AT90S2313 Target Board Version 1

Schematics

Board Layout

     

2002.02.15

Last Updated 2007.09.07