free 8051 Microcontroller Projects AVR PIC Microcontroller Projects Tutorials Ebooks Libraries, interfacing tutorials, lcd tutorial, stepper motor, dc motor 8051 assembly language programming electronics and communication ECE CSE pdf ebooks library BE final year project ideas Embedded systems
I have heard many people on forum asking for learning AVR Microcontroller. So i got this idea to start a new thread where I will post step by step information which will help you get started with AVR microcontroller. This thread not only help you understand AVR, but also it will cover all the details regarding interfacing and other stuff.. so you can say its a complete E-book for you to learn AVR. We will also discuss problems you face while working on with the assignments. So i get started with the essentials of AVR.
Note: The tutorials will be in assembly language. We can discuss about C later on.
So you can download any of the copy above as per your need more information about AVR studio can be obtained from AVR Studio 4
All documents and IDE for writing program is ready.. only thing left is a programmer, with which we are going to program our AVR. As we know almost all AVR comes with ISP (In System Programmable) ports. So you don't need any special hardware to program your AVR. Please see the link below for ISP programmer for AVR. Download PonyProg - serial device programmer
Interfacing Schematic:
Note: Do not forget to run the setup after installing PonyProg.
Setup Information: In interface setup, select parallel and then from the drop down select AVR ISP I/O. slect the LPT Port (parallel port) available on your PC. Then click ok!
To load Hex file: Go to File-> Open Program (FLASH) file then from the drop down where ".e2p" is show, select ".hex" and load your hex file.
The first step of our AVR tutorial is over... if you have any doubts please post in the link below Doubts in AVR tutorial - Step 1
[ Edited Sat Aug 18 2007, 05:27AM ] www.rickeyworld.info If you feel satisfied with the user's forum reply please click on the thank button.
I hope you've all gone through the step 1 and ready to work on the AVR Microcontroller.
So lets start with the programming and writing our first program which is "hello world" of microcontrollers..
AVR Tutorial - Step 2
Note: The program i wrote is for ATMEGA8515 and there is not much difference in other AVRs except some has extra features.
Before programming AVR, first you need to know few important programming tips and AVR registers.
CODE:
.include"8515def.inc"
This include the definition file for ATmega8515, so that we can directly address the registers with their names. All AVRs have 32 general purpose registers from R0 - R32. R0-R15 registers have certain restrictions of use, i.e. they are not allowed to load immediate value. e.g. LDI R15, $35 the above statement will give you an error, saying "Invalid Register" Where as registers from R16-R32 can be used for this purpose i.e. LDI R16,$35 is a valid statement. You can move values from one register to other by using MOV R15,R16
Not only the registers from R0 to R15 has restriction on LDI but also other commands where the use of R0-R16 is not allowed. usually all commands having immediate operands are not allowed. For the ease of programming, you can also give names to the register like
CODE:
.def myregister = R16
There are some special registers like X,Y and Z for 16-Bit operations. They are used to read and write to XRAM. They are also used for reading from program memory like reading from a lookup table (we will discuss about them when we use them). These special registers are actually combination of two 8-bit General purpose registers. i.e. X is actually R26:R27, Y is R28:R29 and Z is R30:R31. The lower byte of the 16-bit-adress is located in the lower register, the higher byte in the upper register. Both parts have their own names, e.g. the higher byte of Z is named as ZH (R31) and the lower Byte is ZL (R30). Similarly for X (XL and XH) and for Y (YL and YH). These names are defined in the standard header file for the chips (which we include while writing program). Dividing these 16-bit-pointer-names into two different bytes is done like follows:
CODE:
LDIYH,HIGH(LABEL); Set the MSB LDIYL,LOW(LABEL); Set the LSB
where LABEL is address for any lookup table or any memory location.
Some important notes for using registers
Define names for registers with the .DEF directive, never use them with their direct name Rx. This helps you making better use of registers and you will never confuse yourself while using them.
If you need pointer access reserve R26 to R31 for that purpose.
16-bit-counter are best located R25:R24.
If you need to read from the program memory, e.g. fixed tables, reserve Z (R31:R30) and R0 for that purpose.
If you plan to have access to single bits within certain registers (e.g. for testing flags), use R16 to R23 for that purpose
Now coming to ports, The information about a specific port of a certain type of AVR can be easily obtained in the AVR Datasheet. Port names are defined in the include file of the CPU.. if you don't have an include file then you can define yourself as..
CODE:
.equPORTA = $1B;incase of ATmega8515
So if you are not able to find an include file you can use the .EQU directive to define ports and other registers. Making port as i/p or o/p is purely dependent on data direction register called DDRx (DDRA for port A etc.) The DDxn bit in the DDRx Register selects the direction of this pin. If DDxn is written logic one, Pxn is configured as an output pin. If DDxn is written logic zero, Pxn is configured as an input pin. for writing and reading data to Ports, PORTx registers are there. and to read from ports PINx registers are there. for example.. writing to port
CODE:
.def output = R16 LDI output, $FF OUTDDRA, output ; making as o/p LDI output, $00 OUTPORTA, output ; clear all PORTA pins
Reading from port
CODE:
.def input = R17 LDI input, $00 OUTDDRA,input IN input,PINA
We are finished with the basics of AVR, lets try programming with simplest program. Blinking an LED!
CODE:
.include"8515def.inc";Include file
RJMP MAIN ;Reset vector
MAIN: ldi R16,low(RAMEND);Load stack with outSPL,R16 ;RAMEND - highest value ldi R16,high(RAMEND);of internal SRAM outSPH,R16 SBIDDRA,0;Make PORTA Pin 0 as o/p
DO: SBIPORTA,0;Set Pin 0 of PORTA RCALL DELAY ;Wait for some time CBIPORTA,0;Cleare Pin 0 of PORTA RCALL DELAY ;Wait for some time RJMP DO ;Forever loop!
DELAY:;The delay routine LDI R16,$20;Load some delay value
LOOP1: SER R17 ;Make R17 as $FF LOOP: DEC R17 ;Decrement R17 BRNELOOP;Jump if not zero DEC R16 ;Decrement R16 BRNE LOOP1 ;Jump if not zero RET;Return
I hope you are now familiar with the register set of AVR and instructions that deals with these registers. So let move on to our next step of the tutorial. I named it as "Dealing with load and store instructions of AVR"
Lets learn AVR Tutorial - Step 3
In this part of tutorial you will learn
Reading from Program memory
Reading from RAM
Writing to RAM
Practice programs
Here is the summary of Load and store instructions that are used for dealing with SRAM of AVR Microcontroller
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)
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
LD Rn, -X/-Y/-Z >Load Rn with value stored at location pointed by pre-decrement of address stored in X/Y/Z
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
ST X/Y/Z, Rn >Store the value of Rn to location pointed by X or Y or Z
ST X+/Y+/Z+, Rn >Store the value in Rn to location pointed by X or Y or Z and increment the address pointer
STD Y/Z+displacement, Rn >Store the value in Rn to location pointed by Y or Z + Displacement
LDS Rn, SRAM_Address >Load value from SRAM Address to the Rn register >SRAM Address is the immediate value e.g. LDS R0,0x0100
STS SRAM_Address, Rn >Store Rn to immediate SRAM location
To read from Program memory we have special instructions like
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]
LPM Rn, Z >Load Rn from program memory pointed by register Z >This instruction is not supported by all AVRs e.g ATMega8515, AT90S8515
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)
ldiZH,HIGH(2*data);Load Z with address where ldiZL,LOW(2*data);our data is stored ldiXL,$60;Load Destination RAM location ldiXH,$0 ldi count,$A ;Load count 10 Bytes
again: lpm;Load value from program memory incZL;Increment memory location stX+,Temp ;Store byte to the RAM location dec count ;Decrement Count brne again ;Check if all bytes moved end: rjmpend;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 1: 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 ldiZL,Low(2*Data);Load the program memory address ldiZH,High(2*data)
lpm;Load first number mov num2,num1 ;Move it to num2 incZL;Increment the address lpm;Load second number cp num1,num2 ;Compare them
brlt next ;Jump if num1<num2 mov num2,num1 ;If num1>num2 then move num1
next:; to num2 location incZL;Increment the address lpm;Load the third number cp num1,num2 ;Again compare
brlt final ;Check if num1<num2 mov answer,num1 ;If No, then num1 is answer
final: mov answer,num2 ;If Yes, then num2 is our answer end: rjmpend;End of program
Data:;Our 3 numbers .db $23,$23,$14;Try changing them and see results
Now you can try yourself writing some programs to make yourself more easy with load and store operations. Here is the list of programs you can try out:
I think the wait is over... now as i am not getting any questions from your side.. so i can post the answer to the assignment i gave.. which is 5 programs.. So here are the programs.. Please take a look! Swap two numbers stored in RAM
CODE:
;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
ldiZH,0x00;Assuming the two numbers are stored ldiZL,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 ldiZL,0x90;load the RAM location back stZ+,num1 ;store the first number stZ, num2 ;store the second number end: rjmpend;end of prog
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 ldiZL,Low(2*Data);Load the program memory address ldiZH,High(2*data) ldi count,4;Load count lpm;Load first number mov num2,num1 ;Move it to num2 adiwZ,1
again: lpm;Load second number cp num1,num2 ;Compare them
brlt next ;Jump if num1<num2 mov num2,num1 ;If num1>num2 then move num1
next:; to num2 location adiwZ,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: rjmpend;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.
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
.org0 ldiZL,0x60;Lets fill the RAM with some numbers ldiZH,0x00;to copy, so we can check is it working ldi count,10;Load count
fill: stZ+,count ;Store value to RAM location dec count brne fill
ldiZL,0x60;Load memory location to copy from ldiZH,0x00 ldiYL,0x90;Load destination memory location ldiYH,0x00 ldi count,10;Load count
copy: ld temp,Z+;Load value to temporary register stY+,temp ;Store it to location dec count ;decrement counter brne copy
end: rjmpend;End of program...
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
.cseg;Code segment starts .org0 ldiZh,high(2*mydata);Load memory add where ldiZl,low(2*mydata);data is stored in ROM ldiYh,0x00;Destination location ldiYl,0x60;0x0060 in RAM ldi count1,10;Load count
copy: lpm;Load from program mem stY+,temp ;Store it to RAM adiwZ,1;Increment Z dec count1 ;Decrement counter brne copy ;copy all 10 bytes
ldiZH,0x00;Load first pointer ldiZL,0x60 ldi count1,10;Load counter for it
sort: movYL,ZL;Load second pointer movYH,ZH adiwY,1;Increment it ld num1,Z;load first number mov count2,count1 ;load count2 subi count2,1;Count2 = Count1-1 breqend;end if last num
again: ld num2,Y;Load second number cp num1,num2 ;Compare them
brlo next ;Jump if num1<num2 mov temp,num2 mov num2,num1 ;If num1>num2 then swap mov num1,temp stZ,num1 ;and store them on their stY,num2 ;respective locations
next: adiwY,1;Increment the address dec count2 ;dec count2 for Y pointer brne again ;check if count is zero adiwZ,1;increment Z pointer dec count1 ;Dec count1 for Z pointer brne sort ;finish if zero
ldi cnth,0x02;Load count 0x200 to clear ldi cntl,0x00;memory from 0x00 to 0x1FF clr temp ;clear temp ldiZH,0x00;Load starting address of ldiZL,0x60;RAM 0x0060 in Z pointer
clrram: stZ+,temp ;Store 0 in current Z location sbiw cnth:cntl,1;Decrement the counter brne clrram ;end if zero
end: rjmpend;End of program
[ Edited Thu Nov 29 2007, 12:22AM ] www.rickeyworld.info If you feel satisfied with the user's forum reply please click on the thank button.
8051 Microcontroller Projects 8051 AVR tutorials PIC microcontroller, 8051 assembly language programming electronics and communication ECE CSE pdf ebooks library BE final year project ideas Embedded systems