This is the personal website of Garthee, who believes it is the perspiration not the perception that brings the success
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





