6th December 2007

Tutorial 2 – “Hello World” Program in Assembly Language

Tutorial Goal: Create and test a simple assembly program

Highly recommended reading/reference:
MPASM Assembler Help, found at :\Program Files\Microchip\MPASM Suite, especially the MPASM Assembler/Directives section.

Unlike a Windows C/C++ Hello World tutorial, we will not be printing output to the console. Instead we will connect an LED to an input/output pin on the microcontroller and create a simple assembly program to turn the LED on.I will try to avoid making real schematics until it becomes really necessary, so here is a picture of the setup:
Tutorial Setup - LED with 1KOhm resistor
GND — 1KOhm — LED — (20)

With the hardware done, it’s time to move on to the software.

  • Open MPLAB
  • Select Project/Project Wizard… Click Next
  • Select your microcontroller (PIC18F4550). Click Next
  • Choose Microchip MPASM Toolsuite. The locations should already be set up, but in case they aren’t, you can find the files in :\Program Files\Microchip\MPASM Suite\. Click Next
  • Click Browse… and select a directory and name for your project Tutorial2. For some reason, Microchip tools have some problem with long file paths, so you are limited to a maximum 62 character project path. A good directory might be :\pic\tutorial2 Click Next
  • Don’t add any files. Keep clicking Next, then click FinishYou should now see the project window titled Tutorial2.mcw. If you don’t, click View/Project. Similarly, click View/Output if you do not see the output window. Windows inside the IDE can be docked by right clicking the blue title bar, selecting Dockable and dragging the window to an edge of the IDE. Click File/New to open a new editor window. Rearrage your windows to your liking.
  • Mine looks like this:

    MPLAB IDE setup

    Type

    #include<18f4550>
    

    at the top of the text file. Wow! Your first line of code. Better save! Click File/Save As…, find the project directory and save file as tutorial2.asm. Note: You need to make sure that the file saves with the .asm extension by typing it yourself.

    To add the file into your project, right click Source Files and click Add Files…. Select tutorial2.asm and click Open.

    It may also be helpful to add the include file into the project for reference. Right click Header Files and click Add Files…. Cruise to :\Program Files\Microchip\MPASM Suite and find the file P18F4550.INC.

    Open the include file by double clicking on it. Note the comment (comments are marked by semicolons) toward the top:

    	;  This header file defines configurations, registers, and other useful;  bits of information for the PIC18F4550 microcontroller.  These names
    	;  are taken to match the data sheets as closely as possible.
    

    Unfortunately, this means that you will have to become friends with the datasheet. Anytime you wish to use a peripheral, you need to consult the datasheet to find out which file registers perform the task you need. Then, confirm in the include file that the register names are consistent by searching for them.

    Back to the tutorial2.asm..

    Before any real coding gets done, the configuration bits (described in the datasheet – Section 25.1) must be set. These bits configure various aspects of the microcontroller’s operation that must be set before any code actually runs. Some recommend setting all of the configuration bits to make sure that everything is correct, but we will not be doing that at this point. Instead, we will set a few important bits that will allow our program to run:

    	CONFIG WDT=OFF; disable watchdog timer
    	CONFIG MCLRE = ON; MCLEAR Pin on
    	CONFIG DEBUG = ON; Enable Debug Mode
    	CONFIG LVP = OFF; Low-Voltage programming disabled (necessary for debugging)
    	CONFIG FOSC = INTOSCIO_EC;Internal oscillator, port function on RA6
    

    The watchdog timer is a failsafe mechanism that resets the microcontroller in case there is a problem in the code. This may receive a tutorial later on. It’s mainly useful for commercial applications and will only be a hindrance in this tutorial. Therefore it will be turned off.

    The MCLEAR pin (1) needs to be enabled to be able to use the debugging features (which we will be using shortly).

    The DEBUG bit dedicates RB6 (39) and RB7 (40) to the debugger, instead of leaving them as I/O pins.

    LVP will be disabled if you are programming with the PicKit 2 since it uses high voltage programming.

    Last, but not least (the least least, actually) is the oscillator setup. We will use the internal oscillator. This means that the clock signal for the microcontroller will be generated inside the PIC. However, the default setting is an external oscillator (meaning that it will expect a clock signal on one of the pins), meaning that this must be set, or this tutorial will not work.

    	org 0; start code at 0
    

    According to the MPASM Help (referenced above), the org directive allows the user to :
    Set the program origin for subsequent code at the address defined in expr (0 in this case). If no org is specified, code generation will begin at address zero.For PIC18 devices, only even-numbered expr values are allowed.
    This means that org dictates where in the microcontroller’s memory to place the data following it. Even though the default behavior is to start the code at memory location 0, it is a good idea to have this directive to mark the start of the code.

    Now, the real code begins. A brief explanation of what this program does might help make the code easier to understand. First, the variables are declared and set to 0. Then, a pin is set up to output a value to turn the LED on and off. We will be using PORT D, PIN 1 (20). Note that this is the second pin on PORT D (after pin 0). I chose this port/pin for two reasons. First, it is at the end of the chip, making it easy to access. Second, PORT D is the only port that does not have some non-digital-I/O action using some of its pins by default, making it easiest to set up. Once the port is set up correctly, PIN 1 (20) is toggled. Then, a delay is necessary as the PIC runs at a default speed of 1Mhz (blinking far too fast to see). After the delay loop, the code goes back and toggles the pin. This cycle continues indefinitely.

    Delay1 res 1 ;reserve 1 byte for the variable Delay1
    Delay2 res 1 ;reserve 1 byte for the variable Delay2
    

    The res directive reserves memory for variables.
    This is a good time to mention that there are 3 types of “words” that you can use in assembler:
    Directives/Instructions (blue): Must be preceeded with a tab or space
    Labels (purple): Variable names are considered labels. Should start at the beginning of a line
    Literals (black): Numbers and strings are literals, meaning that they do not have symbolic meaning other than the number/letter sequence they represent. These usually follow some instruction

    Start:
    	CLRF PORTD
    	CLRF TRISD
    	CLRF Delay1
    	CLRF Delay2
    

    The label Start, followed by a colon represents a point in the code that can be returned to using the goto/call instructions. A goto instruction simply moves program flow to a specified address or label. The call instruction will be covered later, but it performs a similar action to calling a C function (which returns to the same point once it is finished).
    PORT D can be accessed in two different ways. The PORTD register allows the port values to be written. However, it may be useful to read back an output value set on a certain pin. A latch attached to each PORT D pin allows this value to be stored. LATD is the register that allows access to the pin latches. A write to PORTD and LATD has the same result. Only a LATD read, however, will provide the correct output value of a pin. CLRF is an instruction that clears the file register (F) supplied. In this case, the PORTD register is cleared. According to the datasheet, this initializes PORTD by clearing the data latches. Next, the data direction must be set. PORTD pins can function either as digital inputs or digital outputs. In this case we want outputs, to control the LED. The register TRISD controls the direction of the port. A good way to remember how to set the direction is that in TRISD 0s are Outputs and 1s are Inputs. Therefore, we clear TRISD to set the whole port to output. Note: TRISD bits control the same pins as the PORTD bits. For example, PORT D PIN 1 is set to input or output by the second bit in TRISD and written to by the second bit in PORTD.
    The Delay variables are also set to 0.

    MainLoop:
    	BTG PORTD,RD1 ;Toggle PORT D PIN 1 (20)
    Delay:
    	DECFSZ Delay1,1 ;Decrement Delay1 by 1, skip next instruction if Delay1 is 0
    	GOTO Delay DECFSZ Delay2,1
    	GOTO Delay
    	GOTO MainLoop
    end
    

    In the main loop, PORT D PIN 1 is toggled, followed by a delay loop.

    (The delay algorithm has been taken from the example code in the MicroChip 16F 44-Pin Demo Board User Guide). The decfsz instruction subtracts the requested amount (second argument) from the file register (F) provided (first argument) and then checks the value of that register. If it is 0, the following instruction is ignored. This delay loop is actually a nested loop. Since Delay1 was 0 at the start, decrementing 1 from this 8 bit register turns it into 255. The goto instruction then moves the program flow back to the decfsz instruction. This continues until Delay1 reaches 1. When decfsz runs again, Delay1 becomes 0. As promised, the following goto instruction is skipped so the second decfsz instruction is run, subtracting 1 from Delay 2. Delay 2 was also 0 and becomes 255. The following goto instruction brings it back to the FIRST decfsz instruction, causing Delay1 to be decremented another 255 times before decrementing another 1 from Delay2. To quantify the delay, a reference from the MicroChip 16F 44-Pin Demo Board User Guide: Each loop takes 3 instruction times; one for the decrement and two for the GOTO and the counter will force it to go around 256 times, which takes it a total of 768 instruction times (768 µs) to execute. The inner loop (Delay1) takes 768 µs plus 3 for the outer loop(Delay2), but now it’s executed another 256 times, (768 + 3) * 256 = 197376 µs = 0.197s.

    Once the delay code is finished (the second goto is skipped because Delay2 turns to 0), the goto MainLoop instruction is executed and the cycle begins again. The end directive is also present, as it must be in every assembly program. However, it should never be reached.

    The program is now complete. Click Project/Build All to build it. You should see BUILD SUCCEEDED in the build tab in the output window. Then, click Programmer/Select Programmer and choose PicKit2. You should see

    Found PICkit 2 - Operating System Version 2.20.0
    Target power detected ( 5.00V)
    PIC18F4550 found (a3)
    PICkit 2 Ready
    

    in the PicKit2 tab in the output window.
    Click Programmer/Program to program your PIC.
    Click Programmer/Release from Reset to run your program.
    Enjoy..
    PIC18F4550 Controlled Blinking LED
    Files: tutorial2.asm

This entry was posted on Thursday, December 6th, 2007 at 3:28 am and is filed under 18F4550 Assembly Tutorial. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

There are currently 19 responses to “Tutorial 2 – “Hello World” Program in Assembly Language”

Why not let us know what you think by adding your own comment! Your opinion is as valid as anyone elses, so come on... let us know what you think.

  1. 1 On January 19th, 2008, Chris Prince said:

    Yeah! Thanks for this tutorial! I just got my first program working with an 18f4553 and a pickit2! With the help of a electronics shop, I had to to put together my own 6 pin connector for the pickit2 also.

  2. 2 On February 7th, 2008, Chris Prince said:

    Hmmm. It seems I may have spoken too soon. I think I had a bug in my initial program that allowed me to get the results I was expecting (the flashing LED). When I now use the program as you have posted, I don’t get a flashing LED. Some debugging shows that when I comment out both Delay loops, I get a voltage out of pin 20 of 1.3V. With just the Delay2 loop commented out, I get a voltage on pin 20 of 1.6V. With both loops in place, I get a voltage output on pin 20 of 2.5V. But no flashing in any of these cases. It seems I’ve managed to do some kind of odd Pulse Width Modulation. I’m not sure why the voltage of pin 20 is growing larger with increasing delay though. The clock rate of my PIC 18f4553 seems to be 48 MHz. Perhaps that’s a faster clock rate on the PIC you were using originally? Any thoughts would be appreciated.

  3. 3 On February 9th, 2008, vanneop said:

    Andrey,

    Thank you very much for your excellent tutorials. Just a small thing–please note that there are some typos on this page:

    http://www.pic18f.com/tutorial/2007/12/06/tutorial-2-hello-world/

    and as a result, I was not able to compile tutorial2. However, when I used the file “tutorial2.asm” everything went well.

    Thanks again.

  4. 4 On February 28th, 2008, Chris Prince said:

    Ok. Finally, I think I’ve figured out where my problems were. I’m working with the PIC 18f4553 and I was getting flaky operation of the LED in this circuit. It would work for a while, then not work. At most, though the LED would flash a dozen times. After pretty much replacing each component of the circuit (PIC, breadboard, wires etc), I narrowed the problem down to the MCLR pin (pin 1). It seems static electricity was generating enough electrical variation to cause a MCLR signal. Actually, that pin needs to be high (I think), so perhaps this isn’t that unusual. I am running the programmed PIC with the programmer disconnected, so I’m not sure if that’s a factor here. I now have the MCLR pin tied to +5v. All is well!! (Also, I don’t think this has any immediate bearing on the problem I was having, but I have placed a pair of 0.1 microfarad capacators on the Vdd lines. I’m reading a book by Myke Predko “Programming and Customizing the PIC Microcontroller — 3rd Ed” and this was recommended. Myke you didn’t proof check the code figures in that book– they have line wrap!!).

    Cheers,
    Chris.

  5. 5 On March 5th, 2008, Mostafa Ahmed said:

    dude thats great tutorial but, why dont u use C language ? i think this will be very useful thanks alot.

  6. 6 On March 7th, 2008, Andrey said:

    Mostafa,
    I hope to find some free time in the near future to finish a few more simple assembly tutorials and move to C. This website was originally a way for me to start documenting my work with the 18F4550, but turned into a series of tutorials because I was unable to find any reliable sources of assembly tutorials for these microcontrollers. Please do check back in the future..

    Also, if you have any specific questions, feel free to ask them in the forum

    -Andrey

  7. 7 On April 1st, 2008, guest said:

    “The decfsz instruction subtracts the requested amount (second argument)…”
    second argument is the destination register…i think

    great job, nice and easy tutorial for the beginner like me!

  8. 8 On April 12th, 2008, Alarcon said:

    Hi, I implemented you program and though I make it work I still have the big problem that it only works for two cycles and then the led doesn’t turn off, any suggestions will be welcome

  9. 9 On June 10th, 2008, Art said:

    Interesting tutorial looking forward to more , My first foray into PICs has not been very encouraging , but these tutorials have cleared up a few things , Use of Assembly helps a lot

  10. 10 On July 6th, 2008, hkBattousai said:

    Thank you for this tutorial, it did work quite nice and made a good start for me.

    I have question, how should I modify my code if I want to use and external crystal oscillator with or without USB support at values 20MHz and 48MHz?

  11. 11 On October 20th, 2008, Winfield said:

    Thanks so much. it is really helpful.

  12. 12 On December 5th, 2008, Danny said:

    Just found this thanks. :)

  13. 13 On January 30th, 2009, vaclav said:

    You did not set BSR to 0x0f ? And it still works ? IMHO after RESET, BSR = 0×00. And all special registers like PORTD, TRISD etc. are on page 15. Can you explain it for me ? I programmed only 16F processors and they are a little bit different…

  14. 14 On June 18th, 2009, angad said:

    THANK YOU SO MUCH… This was a godsend

  15. 15 On June 25th, 2009, Jasper said:

    great site, short and understandable tutorials

  16. 16 On October 12th, 2009, István Cserny said:

    Hi!

    I would like to note that the data space reservation at the beginning of your program test2.asm is wrong. The MPASM compiler says: “No memory has been reserved by this instruction”. This will result in an infinite loop (instead of a finite delay) and the LED will not blink.

    The correct code would be:
    CBLOCK 0×00
    Delay1:1
    Delay2:1
    ENDC

    ORG 0×00
    ….

    Best regards: I. Cserny

  17. 17 On November 16th, 2009, Tutorial 4 - “Hello World” Program in C » PIC18F.COM - Tutorials and Sample Code said:

    [...] the basics of PIC18F C programming and provide simple sample code for a blinking LED, similar to tutorial 2. If I receive positive feedback, more tutorials will follow. This tutorial assumes minimal [...]

  18. 18 On December 8th, 2009, Demolishun said:

    This is such an awesome tutorial. I have programmed PIC16s and am now learning the PIC18. I needed a quick start for testing my setup to see how things are working. The ability to toggle an LED allows me to gauge how the oscillator is working by the output switching and giving me a value my freq counter can read.

    Thanks for doing such a nice job!

  19. 19 On February 24th, 2010, Shawn said:

    Thanks for the great tutorial, Andrey!
    I’m just getting started with PIC controllers and I don’t think I would have been able to find a better “Getting-started” tutorial. This has really helped my frustration level go WAYYYY down.

Leave a Reply

  • Sponsored Links

  •  

  • December 2007
    M T W T F S S
        Nov »
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31  
  • Donate