Chapter 3

Lets Learn AVR - Step 1:

In this part of tutorial you will learn
1. Reading from Program memory
2. Reading from RAM
3. Writing to RAM
4. Practice programs

Here is the summary of Load and store instructions that are used for dealing with SRAM of AVR Microcontroller
i. LD Rn,X/Y/Z
>either X or Y or Z register can be used
>this will load the value which is stored in memory location pointed by register X/Y/Z to the destination register Rn (can be R0, R1.. any etc)
ii. LD Rn,X+/Y+/Z+
>This instruction will load the value which is stored in memory at location pointed by X/Y/Z registers and then increment the memory location by 1
>This is a post increment instruction
iii. LD Rn, -X/-Y/-Z
>Load Rn with value stored at location pointed by pre-decrement of address stored in X/Y/Z
iv. LDD Rn,Y/Z+displacement
>Load Rn with value at address Z or Y + displacement
>e.g. Z is 0x0090, Displacement is 0x10 so Rn will be loaded with value stored at 0x0090+0x10 = 0x0100
v. ST X/Y/Z, Rn
>Store the value of Rn to location pointed by X or Y or Z
vi. ST X+/Y+/Z+, Rn
>Store the value in Rn to location pointed by X or Y or Z and increment the address pointer
vii. STD Y/Z+displacement, Rn
>Store the value in Rn to location pointed by Y or Z + Displacement
viii. LDS Rn, SRAM_Address
>Load value from SRAM Address to the Rn register
>SRAM Address is the immediate value e.g. LDS R0,0x0100
ix. STS SRAM_Address, Rn
>Store Rn to immediate SRAM location


To read from Program memory we have special instructions like
i. LPM
>Load form program memory, This instruction is used in most of the AVRs and its hard coded in the architecture.
>This instruction will load R0 with the address specified by register Z [This is hardcoded]
ii. LPM Rn, Z
>Load Rn from program memory pointed by register Z
>This instruction is not supported by all AVRs e.g ATMega8515, AT90S8515
iii. LPM Rn,Z+
>Load Rn from program memory and increment the memory location pointed by Z
>This instruction is also not supported by all AVRs


Note: load from program memory instructions are not supported by all AVR architectures. Most of the architectures support LPM instruction which is hard coded to load R0 from location in Z. where as in some AVR this is also not implemented.

Now we are done with the instructions overview.. now lets practice them..



Program 1: Copy 10 Bytes memory block stored in Program memory(ROM) to Data memory (SRAM)
CODE:
;This program is to copy memory block from Program
;memory to AVR RAM (10 Bytes)

.include "8515def.inc"

.org $0
.def Temp = R0 ;Temprary variable
.def count = R17 ;Byte Count

ldi ZH,HIGH(2*data) ;Load Z with address where
ldi ZL,LOW(2*data) ;our data is stored
ldi XL,$60 ;Load Destination RAM location
ldi XH,$0
ldi count,$A ;Load count 10 Bytes
again:
lpm ;Load value from program memory
inc ZL ;Increment memory location
st X+,Temp ;Store byte to the RAM location
dec count ;Decrement Count
brne again ;Check if all bytes moved
end:
rjmp end ;End of program

;Our data which we will copy from Program Memory to RAM
Data:
.db $10,$20,$30,$40,$50,$60,$70,$80,$90,$95

In the above code.. you can see while loading the address of program memory location, i multiplied it with 2, i.e. LDI ZH,High(2*Data)
The reason is, the program memory is organized in word manner i.e. two bytes for each command, So the address has to be multiplied by 2. You can try running these programs and see its working in the Simulator of AVR Studio.





Program 2: Find Greatest of 3 numbers Stored in program memory
CODE:
;Program to find greatest of 3 numbers
;
;numbers are stored in ROM and the final
;result will be stored in a register

.include "8515def.inc"

.def num1 = r0 ;Location for First number
.def num2 = r1 ;Location for second number
.def answer = R2 ;location for Final answer

.org $0
ldi ZL, Low(2*Data) ;Load the program memory address
ldi ZH, High(2*data)

lpm ;Load first number
mov num2,num1 ;Move it to num2
inc ZL ;Increment the address
lpm ;Load second number
cp num1,num2 ;Compare them
brlt next ;Jump if num1 mov num2,num1 ;If num1>num2 then move num1
next: ; to num2 location
inc ZL ;Increment the address
lpm ;Load the third number
cp num1,num2 ;Again compare
brlt final ;Check if num1 mov answer,num1 ;If No, then num1 is answer
final:
mov answer,num2 ;If Yes, then num2 is our answer
end:
rjmp end ;End of program


Data: ;Our 3 numbers
.db $23,$23,$14 ;Try changing them and see results






Program3: Program to swap two numbers

.include "8515def.inc"

.def temp = R16 ;Temporary register
.def num1 = R17 ;Number one location
.def num2 = R18 ;Location for second number

.cseg
.org $0

ldi ZH,0x00 ;Assuming the two numbers are stored
ldi ZL,0x90 ;at location 0x0090 in RAM
ld num1,Z+ ;Load first number
ld num2,Z ;Load second number
mov temp,num1 ;copy num1 to temp
mov num1,num2 ;copy num2 to num1
mov num2,temp ;copy temp to num2
ldi ZL,0x90 ;load the RAM location back
st Z+,num1 ;store the first number
st Z, num2 ;store the second number
end:
rjmp end ;end of prog





Program 4: Find Greatest of 5 numbers
CODE:
;Program to find greatest of 5 numbers
;
;numbers are stored in ROM and the final
;result will be stored in a register

.include "8515def.inc"

.def num1 = r0 ;Location for First number
.def num2 = r1 ;Location for second number
.def answer = R2 ;location for Final answer
.def count = r16 ;Count

.org $0
ldi ZL, Low(2*Data) ;Load the program memory address
ldi ZH, High(2*data)
ldi count,4 ;Load count
lpm ;Load first number
mov num2,num1 ;Move it to num2
adiw Z,1
again:
lpm ;Load second number
cp num1,num2 ;Compare them
brlt next ;Jump if num1 mov num2,num1 ;If num1>num2 then move num1
next: ; to num2 location
adiw Z,1 ;Increment the address
dec count ;are we done with all 5 numbers?
brne again ;if no then jump back
final:
mov answer,num2 ;If Yes, then num2 is our answer
end:
rjmp end ;End of program

;Try changing them and see results
Data: ;Our 5 numbers
.db $3,$23,$14,$50,$20,$0
;last zero is to aligh the bytes in word manner
;we have 5 numbers so i am padding with a 0 to make it
;even. if we dont't do this.. compiler will do it
;automatically to prevent misalignment.





Program5 Copy memory block from RAM to RAM
CODE:
;Program to copy a block of memory (10 Bytes)
; from one RAM location to another RAM location.

.include "8515def.inc"

.def temp = r0
.def count = r16

.org 0
ldi ZL,0x60 ;Lets fill the RAM with some numbers
ldi ZH,0x00 ;to copy, so we can check is it working
ldi count,10 ;Load count
fill:
st Z+,count ;Store value to RAM location
dec count
brne fill

ldi ZL,0x60 ;Load memory location to copy from
ldi ZH,0x00
ldi YL,0x90 ;Load destination memory location
ldi YH,0x00
ldi count,10 ;Load count

copy:
ld temp,Z+ ;Load value to temporary register
st Y+,temp ;Store it to location
dec count ;decrement counter
brne copy

end:
rjmp end ;End of program...




Program 6: Sorting of 10 numbers
CODE:
;Program to sort 10 numbers
;in ascending order
;10 numbers are stored in ROM
;and sorted answer is stored in RAM
;at location 0x0060

.include "8515def.inc"

.def count1 = r17 ;First Count
.def count2 = r18 ;Second count
.def temp = r0 ;Temp reg for swap
.def num1 = r1 ;Num 1
.def num2 = r2 ;Num 2

.cseg ;Code segment starts
.org 0
ldi Zh,high(2*mydata) ;Load memory add where
ldi Zl,low(2*mydata) ;data is stored in ROM
ldi Yh,0x00 ;Destination location
ldi Yl,0x60 ;0x0060 in RAM
ldi count1,10 ;Load count

copy:
lpm ;Load from program mem
st Y+,temp ;Store it to RAM
adiw Z,1 ;Increment Z
dec count1 ;Decrement counter
brne copy ;copy all 10 bytes

ldi ZH,0x00 ;Load first pointer
ldi ZL,0x60
ldi count1,10 ;Load counter for it

sort:
mov YL,ZL ;Load second pointer
mov YH,ZH
adiw Y,1 ;Increment it
ld num1,Z ;load first number
mov count2,count1 ;load count2
subi count2,1 ;Count2 = Count1-1
breq end ;end if last num

again:
ld num2,Y ;Load second number
cp num1,num2 ;Compare them
brlo next ;Jump if num1 mov temp,num2
mov num2,num1 ;If num1>num2 then swap
mov num1,temp
st Z,num1 ;and store them on their
st Y,num2 ;respective locations
next:
adiw Y,1 ;Increment the address
dec count2 ;dec count2 for Y pointer
brne again ;check if count is zero
adiw Z,1 ;increment Z pointer
dec count1 ;Dec count1 for Z pointer
brne sort ;finish if zero

end:
rjmp end ;End of program

mydata:
.db $10,$90,$50,$20,$91,$23,$55,$62,$39,$80





Program 7: Clear SRAM area from 0x60 to RAMEND
CODE:
;Program to clear RAM
;this program is for ATMega8515 So ram area is from
;0x60 to RAMEND

.include "8515def.inc"

.def temp = r16 ;Temporary variable
.def cnth = r25 ;Counter High byte
.def cntl = r24 ;Counter Low byte

.org 0

ldi cnth,0x02 ;Load count 0x200 to clear
ldi cntl,0x00 ;memory from 0x00 to 0x1FF
clr temp ;clear temp
ldi ZH,0x00 ;Load starting address of
ldi ZL,0x60 ;RAM 0x0060 in Z pointer

clrram:
st Z+,temp ;Store 0 in current Z location
sbiw cnth:cntl,1 ;Decrement the counter
brne clrram ;end if zero

end:
rjmp end ;End of program


No comments:

Post a Comment