This is the personal website of Garthee, who believes it is the perspiration not the perception that brings the success

Search:     All roads lead to ROME !  

Be Miracle!

Lets start to code in assembly

The best way to learn to code is to write, but do we have time to find everything ourselves by perusing the datasheets and tampering with the devices or simulators. Of course there is another route, easiest more traveled path, find already written code and edit them; be warned never ever edit the code, but the comments. In a well written code, the however a simple the code is, the comments will take at least half of the lines making the duty of preprocessor ineluctable. well that's enough chit chat to chase the superficial people, and lets get back to the business.

;**********************************************************************
;                                                                     *
;    Filename:      test1.asm                                         *
;    Date:          17 july 2008                                      *
;    File Version:  0.2                                               *
;                                                                     *
;    Author:        Garthee                                    *
;    Company:       University of Moratuwa, ETNC                      *
;                                                                     *
;    Description:   The following code displays a running  light      *
;                   on PORTB with a controlling display on PORTC      *
;                                                                     *
                                                      *
;**********************************************************************
;                                                                     *
;    Files required: m16def.inc                                       *
;                                                                     *
; m16def defines All the registers by the name used in datasheets     *
; with few definitions for bit locations as well. Further, it         *
; it provides macros for widely used instructions to guarantee         *
; the proper use and familiar nomenclature.                           *
;                                                                     *
;**********************************************************************

.NOLIST
.INCLUDE "m16def.inc"
.LIST

; Above three lines make sure the m16def is included and only once
; This is similar to C's #define _header_ and indef and ifndef or
; PHP's requireonce.
; It is worth noting that #include <> can also be used directly as in C
; Also the file can be in the same directory with asm file, and
; otherwise full path must be given

.NOLIST
.INCLUDE "m16def.inc"
.LIST

; Above three lines make sure the m16def is included and only once
; This is similar to C's #define _header_ and indef and ifndef or
; PHP's requireonce.
; It is worth noting that #include <> can also be used directly as in C
; Also the file can be in the same directory with asm file, and
; otherwise full path must be given

.DEF    mp = R16                ; General purpose
.DEF    tp = R17                ; Direction of the flow
; The above two registers of 32 available namely R16 and R17
; are addressed as mp and tp to be used later in the code.
; General purpose registers are needed in general instructions to
; manipulate the values read from I/O ports or written to I/O ports

.ORG    0x0000                    ; processor reset vector
RJMP    MAIN                      ; go to beginning of program

.ORG    0x0010                    ; Timer1 overflow vector
RJMP    ISR                       ; go to ISR - interrupt service routine

; Main program begins here, whatever the instruction line it is in
; the program memory it will be identified as MAIN elsewhere.
; Interrupt service routine
; Do the processing and before exiting using RETI enable
; when entering CLI and exiting SEI are executed automatically

ISR:

    LDI      mp,    0xF7          ; To make the period exactly 250ms
    out      TCNT1L, mp               
    LDI      mp,    0xC2
    out      TCNT1H, mp   

    in       mp, PINB             ; read PINB
    SBRC     mp, 0                ; is PINB<0> = 0
    RJMP     FORWARD              ; jump to set forward
    SBRC     mp, 7                ; is PINB<7> = 0
    RJMP     REVERSE              ; jump to set reverse
EE: SBRS     tp, 0                ; is in reverse direction
    RJMP     RR                   ; jump to ROR
    RJMP     RL                   ; jump to ROL
ES: out      PORTB, mp            ; output
    RETI                          ; return from ISR
FORWARD:
    LDI      tp,0x01              ; set forward
    RJMP     EE
REVERSE:
    LDI      tp,0x00              ; set reverse
    RJMP     EE
RR:
    CLC       
    ROR      mp
    RJMP     ES
RL:
    CLC       
    ROL      mp
    RJMP     ES

MAIN:

    LDI        mp,LOW(RAMEND)      ; Initiate Stackpointer
    out        SPL,mp              ; for the use by interrupts and subroutines
    LDI        mp,HIGH(RAMEND)
    out        SPH,mp

    ldi        mp,0b11111111       ; Write All 1s to mp
    out        DDRB,mp             ; Make PortB output
    out        DDRC,mp             ; Make PortC output

; DDRx is the direction vector that decides whether each I/O pin
; in a port is output or an input. Writing 1 to the corresponding
; port / pin bit makes it output and clearing it makes it input.

    ldi        mp,0x02             ;Write 2 (in hex) to mp
    out        PORTC, mp           ;Initialize PortB with 2
    out        PORTB, mp           ;Initialize PortC with 2

; Intial value 2 is set to PORTB and PORTC

    ldi        tp,0x00             ; counter 2 to have 260ms

; Post scalar is initialized with 2.

    SEI                            ; Enable global interrupts
    LDI     mp, (1<<TOIE1)         ; Timer1 interrupt mask
    out     TIMSK, mp              ; Enable Timer1 Overflow int

    LDI     mp,    0xF7            ; To make the period exactly 250ms
    out     TCNT1L, mp           
    LDI     mp,    0xC2
    out     TCNT1H, mp

    LDI     mp, (1<<0) + (1<<1)  
    out     TCCR1B, mp

; Enable normal mode operation with the prescalar for TIMER1
; TCCR1A and TCCR1B controls the operation of TIMER1 and
; prescalar.

; The following loop explains the necessity of using
; counter to make the running lights noticeable.
; Here as it happens at aroud 0.5MHz frequency
; PORTC LEDs will appear to be ON always

LOOP:
    in         mp, PINC           
    ROL        mp
    out        PORTC, mp
    RJMP    LOOP                ; Jump to LOOP

; Refer to the Datasheet for AtMega16 for more details

More assistance on AVR programming can be found at

1) http://www.avr-asm-tutorial.net/avr_en/AVR_TUT.html

2) http://www.educypedia.be/electronics/avr.htm

3) http://www.avr-asm-download.de/beginner_en.pdf