Sunteți pe pagina 1din 27

http:// http://www.ermicro.com/blog/?

p=875

Introduction to Microchip PIC Assembler Language Part 1

Learning the assembler language is one of the essential skills that still required in the embedded system, although the major drawback using the assembler language is; its required more learning curve time compared to the higher level language but once you acquainted with one type of microcontroller family such as 8-bit 8 pins Microchip PIC 12F683 then coding with assembly language to other type of PIC microcontroller families will be much easier. Im choosing the PIC 12F683 type because its one of the best 8 pins Microchip PIC microcontroller with nanoWatt technology and supporting advanced peripherals such as 8-bit/16-bit TIMER, ADC (Analog Digital Converter), PWM (Pulse Width Modulation) and Comparator with 2K word of flash. We often hear that one of the reasons we are still coding in the assembly language is the speed and the small HEX code result, but this is not usually true, because some of high optimized industrial standard C compiler can produced more compact code than the average assembler programmer can do for some simple if condition statement. Therefore I will add one more important reason why we have to code in assembler language; we are forced to use the assembly language because most of the average hobbyist could not effort to buy the industrial standard compiler for their project which use a microcontroller type that is not supported or limited supported (e.g. program size limit) by the higher level language free edition compiler; on the contrary all the microcontrollers manufacture will certainly provide free assembler language compiler that support all of their product types. But hey lets look at the bright side, we are going to learn the core of microcontroller language which gives us more deep understanding of how the microcontroller really works. So before we start with the exciting lessons, I would suggest that you could read the article Beginners AVR Assembler Language Programming 1 posted on this blog for some introduction to what is the assembler language. For the purpose of this tutorial I will assume that you are already familiar with higher level programming language such as C language.

Typical Microcontrollers based project cycle is shown on the above picture, we will use this simple cycle for practicing our Microchip PIC assembly language skill through various experiments. Ok now lets take a look at the circuit design for this tutorial:

The Microchip PIC 12F683 has 6 general purpose I/O; GP0 to GP5, the above circuit is suitable for learning such as simple digital I/O up to the advanced topics such as using the PIC 12F683 ADC and PWM peripherals. The Shopping Bag For this tutorial you will need this following hardware and software: 1. Microchip PIC 12F683 PDIP microcontroller with the datasheet downloaded from Microchip site (www.microchip.com) 2. One breadboard or prototype board with an adequate amount of jumper 3. Watt resistor: 1K (2), 10K (1), 330 (1), 10K Trimport (1) 4. Capacitor: 100nF (1), 10nF (1) 5. One 3mm LED (Light Emitting Diode) 6. One 5 Volt regulated power supply or you could use 3 AA/AAA size alkaline battery for the project power source 7. Microchip PICKit2 programmer for downloading the HEX code 8. Microchip MPLAB IDE for coding, debugging and compiling the code; downloaded from Microchip site. Bellow is the prototype of the Microchip PIC12F683 microcontroller circuit used in this tutorial.

My first Assembly Program Hello World one of the famous phrase introduced by Brian W. Kernighan and Dennis M. Ritchie on their famous book The C Programming Language when they first introduced this new programming language many years ago. As they said the only way to learn a new programming language is by writing programs in it. This is true, first time you dont have to understand the code at all, but by writing the code by your self (I mean laterally not just cut and paste the code), compiling/simulating the code, downloading the code to the microcontroller and running the code you will get the excitement to learn further for having good understanding of the code you just wrote. Ok lets write your first Hello World program, first open your Microchip MPLAB IDE application, from Project menu choose Project Wizard, after welcome screen you will get the device selection screen, choose the PIC12F683:

Next is the language Toolsuite selection screen, select the Microchip MPASM Toolsuite:

The next step brings you to the new project file creation screen; enter the full path of your project name:

The next step just press next to continue (currently you dont have any existing file to add) to the summary screen, after examining the summary information you could continue by pressing the finish button. Activate the Project and Output View from View menu; from File create New file and save it as HelloWorld.asm in your project directory.

Next on the project windows; right click on the Source Files folder and add files HelloWorld.asm to the project; now you could start typing your first Microchip PIC assemblerlanguage program as follow:
;****************************************************************************** ; File Name : HelloWorld.asm ; Version : 1.0 ; Description : Hello World Program

; Author : RWB ; Target : Microchip PIC 12F683 Microcontroller ; Compiler : Microchip Assembler (MPASM) ; IDE : Microchip MPLAB IDE v8.00 ; Programmer : PICKit2 ; Last Updated : 18 March 2009 ; ******************************************************************* #include <p12F683.inc> __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _IESO_OFF & _FCMEN_OFF) cblock 0x20 Delay1 ; Define two 8-bit variables for the Delay2 ; delay loop: Delay1 and Delay2 endc org 0 Start: bsf movlw movwf clrf clrf bcf ; Start at flash address 0 STATUS,RP0 0x70 OSCCON TRISIO ANSEL STATUS,RP0 ; Select Registers at Bank 1 ; ; ; ; ; ; ; ; ; ; Set the internal clock speed to 8 Mhz Set all General Purpose I/O to output Make all ports as digital I/O Back to Registers at Bank 0 Set GP2 Output To High Call Delay Subroutine Clear GP2 Output To Low Call Delay Subroutine No Operation Goto MainLoop

MainLoop: bsf GPIO,2 call Delay bcf GPIO,2 call Delay nop goto MainLoop Delay: movlw 0xFF movwf Delay2 DelayLoop1: movlw 0xFF movwf Delay1 DelayLoop2: decfsz Delay1,f goto DelayLoop2 decfsz Delay2,f goto DelayLoop1 return end ; EOF: HelloWorld.asm

; ; ; ; ;

Decrease Delay1, If zero skip the next instruction Not zero goto DelayLoop2 Decrease Delay2, If zero skip the next instruction Not zero goto DelayLoop1 Return to the Caller

After typing the above assembly program (remember that the __config statement is preceded by two underline character) its time to compile and simulating the code using Microchip MPLAB IDE, but before we do that; first we will activate the Watch and Special Function Registers windows by selecting them from the View menu; now add these following SFR (special function registers) on the Watch window by selecting it from the combo list and press the Add SFR button: STATUS, WREG, OSCCON, TRISIO, ANSEL and GPIO; Next we will add the two variables (Delay1 and Delay2) used in Delay subroutine start from address 020 to 021 by right clicking on the Watch window then click the Add menu, the Add Watch window will appear as follow:

Change the Start Address to 020 and the End Address to 021, after clicking the Add Address you could organize these two new windows like this following picture:

Secondly we will choose the MPLAB simulator program, from the Debugger menu -> Select Tools -> MPLAB SIM. Finally we will set the MPLAB simulator frequency to 8 Mhz as we use in the real PIC12F683 microncotroller; from the Debugger menu -> Setting:

Change the Processor Frequency to 8 Mhz and leave the other setting to their default value. Now you are ready to compile and simulating your code. Compiling and Simulating the Code I always mention through the entire introduction tutorials both AVR and PIC microcontroller that simulating or debugging the code is one of the essential steps that should be taken before downloading the HEX file to the microcontroller even for the experience embedded system designer; they should go through this step. Ok lets compile the code first by selecting Project menu and click Build All or you could use the Ctrl+F10 short key. If there are no typo errors than you will have clean output result as this following screen:

Now you are ready to run your code on the Microchip MPLAB IDE Simulation; from the Debugger menu click the Step Into or you could use the F7 short key; this will bring you to the first PIC microcontroller assembly command: bsf STATUS, RP0 as shown on this following picture:

You could reset the simulation anytime by pressing the F6 short key (Processor Reset command) and start all over again. Each time you press the F7 key (Step Into) you could always view the registers value on the Watch window. When it point to the call Delay statement, because this subroutine will take a long time to be executed by the Step Into command, alternatively you could use the Step Over command (F8) to go through (pass) this subroutine; you could change the 0xFF value with 002 value if you still want to Step Into this subroutine for getting better understanding of how the subroutine program work.
Delay: movlw movwf DelayLoop1: movlw movwf DelayLoop2: decfsz goto decfsz goto return 0x02 Delay2 0x02 Delay1 Delay1,f DelayLoop2 Delay2,f DelayLoop1 ; ; ; ; ; Decrease Delay1, If zero skip the next instruction Not zero goto DelayLoop2 Decrease Delay2, If zero skip the next instruction Not zero goto DelayLoop1 Return to the Caller

Remember to restore back the original value (0xFF) before you downloading the final HEX code; otherwise the delay will be too short to be noticed by our eyes. Downloading the HEX Code After compiling and simulating your code its time to download the code using the Microchip PICKit2 programmer, connect the PICKit2 ICSP (Microchip In Circuit Serial Programming) port to your PIC12F683 microcontroller pins then from the Programmer menu Select Programmer -> PicKit2; You will get this following result on the output windows of the Microchip MPLAB IDE:

Now you are ready to download the HEX code by selecting the Program from the Programmer menu:

Now you could enjoy you hard work by watching your first Microchip PIC12F683 microcontroller Hello World Assembly Programming:

The Final Thought You should practicing all the steps mentioned on this tutorial, this will give you the feel of building/prototyping the basic of Microchip PIC12F683 microcontroller project, Coding, Compiling, Simulating and finally downloading the HEX code. I hope this will give you enough fuel to gain more understanding to the code you just wrote on my second part of this tutorial.

Introduction to Microchip PIC Assembler Language Part 2


With only 35 instructions to learn the Microchip PIC microcontroller assembler language is considered very efficient and easy to learn; you will not find such as Atmel AVR microcontroller CP (compare) and BRNE (branch if not equal) or BRGE (branch if greater or equal) on the PIC microcontroller assembler language dialect, instead its just provide us with a very simple bit test and skip one line instruction. This fact is what makes programming the PIC microcontroller assembler language become very interesting and challenging, therefore although is easy to learn but for sure you will need a lot of flying time in order to code the PIC microcontroller efficiently. The PIC Assembler Program Skeleton: Continuing our lesson with the 8-bit, 8 pins midrange Microchip PIC12F683 microcontroller, I will start with the typical PIC microcontroller assembler program skeleton bellow:

The first part is the program comment; its always a good practice to put a comment to your program e.g. name, version, description, etc. All lines begin with ; sign is consider a comment to the MPASM (Microchip PIC Assembler) compiler. The second part is the #include <p12F683.INC> MPASM compiler directive which tell the compiler to include the PIC12F683.INC file definition which exist in the c:\Program Files\Microchip\MPASM Suite directory (MPLAB IDE v8.00 default installation). This include file contain the standard PIC microcontroller physical address to the equivalent naming convention; for example instead of using the address 005 (5 hex) for general purpose I/O, we could use GPIO which is easier to remember. The third part is the Microchip PIC microcontroller configuration bits register; this register is start at address 2007 on the PIC12F683 microcontroller and has 14 bits long. This register is one of the unique features of the PIC Microcontroller compared to other microcontroller, the PIC configuration bits could be configured on every startup of the program. The configuration bits register is used to set how the PIC microcontroller work such as choosing the internal or external clock, using the master clear or not, etc. When programmed these bits will be read as 0; for unprogrammed these bits will be read as 1. The following table shows the configuration bit used in our Hello World assembler program.

The complete description of this configuration bit could be found at page 84 on the Microchip PIC12F63 microcontroller datasheet; therefore by using the AND operator to the entire PIC MPASM configuration bit definition value we could configure the desire configuration bit register value or we could simply using just the bit value as shown on this following table:

Base on the configuration bit table shown above, we could set the PIC12F683 microcontroller configuration bit directly and this will give you the same result as the above program example:
__config 0x33D4

The fourth part is the MPASM CBLOK 020 and closed with ENDC directive; which tell the MPASM compiler to map the Delay1 and Delay2 variables to the 8-bit general purpose registers which start at the address 020 on the PIC12F683 microcontroller address BANK 0; the Delay1 will be mapped to the general purpose register at the address 020 and the Delay2 will be mapped to the general purpose register at the address 021. The following picture show all the Microchip PIC12F683 microcontroller registers address which split into 2 groups named BANK 0 and BANK 1.

One of the unique things about the PIC microcontroller registers address comparing to other microcontroller that the address is not in one continues memory but its being split into two BANKS (groups); this mean we have to switch back and forth between the BANK addresses to access the desire register. For example if we want to access the register TRISIO, we have to switch to the BANK 1 before we could access it and switch back to the BANK 0 in order to access the GPIO register.

To make it easier to understand you could consider the BANK 0 and BANK 1 are like the DIRECTORIES in your computer file system, so if you want to access the TRISIO register (just like a file reside in your directory), you have to change the directory first to the BANK 1 before you could use this register and change directory back to the BANK 0 to access the GPIO register. If you notice some of the registers such as the STATUS register is shared or appeared to the both BANKS; this mean it doesnt matter which BANK you are right now, you could always access this register. This is the same principal as the LINK file on the UNIX/Linux operating system file system, that one physical file could appear on many directories using just the link name. The fifth part is the ORIGINATE (org) MPASM compiler directive that tell the MPASM compiler that your code is start at the address 00000 of the PIC microcontroller flash memory. The sixth part is where you put your PIC assembler program code; this code could consist of main program and the subroutine or function. The last part is the end MPASM compiler directive that tell the MPASM compiler that your code is end here and its a good practice to put the EOF (end of file) comment mark in your program so whenever you cut and paste the program to the other project you could make sure that all the codes is being copied until the EOF mark. Inside the HelloWorld Program Now we will walk through the program codes, first thing I will explain the initialization routine to the PIC12F683 microcontroller; in this initialization routine you will learn the top five of the 35 PIC12F683 microcontroller assembler instructions that you will certainly use in every project. Before we start make sure you have the PIC12F683 datasheet near you and open the page 101 on the Instruction Set Summary.
Start: bsf movlw movwf clrf clrf bcf STATUS,RP0 0x70 OSCCON TRISIO ANSEL STATUS,RP0 ; Select Registers at Bank 1 ; ; ; ; Set the internal clock speed to 8 Mhz Set all General Purpose I/O to output Make all ports as digital I/O Back to Registers at Bank 0

The first thing in our initialization routine is to set the internal clock speed which can be controlled in the oscillator control register or OSCCON at BANK 1, we decide to run the PIC12F683 microcontroller with the maximum internal clock speed of 8 Mhz as shown on the OSCCON register bellow:

By making the internal oscillator selection bits IRCF2=1, IRCF1=1 and IRCF0=1 on the OSCCON register we select the 8 Mhz of internal oscillator frequency, this could be written as the following C program:

OSCCON = 0x70;

But in the PIC assembler code, before we could use the OSCCON register we have to change to the BANK 1, since the default BANK when the PIC microcontroller power up is in the BANK 0; How to instruct the PIC microcontroller to change to the BANK 1; this could be done by setting the bank selection register bits RP1 and RP0 on the STATUS register.

Because the PIC12F683 microcontroller only have two BANKS, then the RP1 bit is not use; but for some PIC microcontroller families such as PIC16F690 or PIC16F886 families have four BANK addresses; therefore for this PIC microcontroller families both RP1 and RP0 bits are used to select the BANK addresses. By setting the bit RP0 to logical 1 we instruct the PIC12F683 microcontroller to change to the BANK 1 and by clearing the bit RPO to logical 0, we instruct the PIC12F683 microcontroller to change back to the BANK 0 (default). The famous PIC set and clear bit oriented file register operation could be used to achieve this task. bsf f,b -> Bit Set f: Register Address (000 to 0x7F) and b: is the bit address bcf f,b -> Bit Clear f: Register Address (000 to 0x7F) and b: is the bit address
bsf STATUS,RP0 ; Select Registers at Bank 1

This instruction will simply tell the PIC microcontroller to SET the RPO bit (the fifth bit) on the STATUS (address 003) register and to CLEAR the RPO bit on the STATUS register we use this command bellow:
bcf STATUS,RP0 ; Back to Registers at Bank 0

As you seen from time to time we have to change the BANK address in order to access the desired registers and we always use the STATUS register to achieve this task; therefore now you understand why the PIC microcontroller shared this STATUS register through all the PICs BANK addresses, so you could always access this important register regardless of the BANK address you are in right now. After we change to the BANK 1 in order to assign the 070 value into the OSCCON register, we have to put first the value in the PIC microcontroller 8-bit accumulator register named WREG (working register) and then move this accumulator value into the OSCCON register. Again the two most used PIC assembler instructions will be used to achieve these tasks: movlw k -> Move literal (constant) to WREG, k is the 8-bit constant movwf f -> Move the WREG value to f: Register Address (000 to 0x7F)
movlw movwf 0x70 OSCCON ; Set the internal clock speed to 8 Mhz

The tri-state register TRISIO and the analog selection register ANSEL located at BANK 1 are used to set the PIC microcontroller I/O port behavior:

By setting all these bits on the TRISIO register to logical 0, we instruct the PIC12F683 microcontroller to set all of the general purpose I/O (GPIO) as the OUTPUT port.

Again by setting all these bits on the ANSEL register to logical 0, we instruct the PIC12F683 microcontroller to use all the analog ports on the PIC12F683 general purpose I/O (GPIO) as the digital port I/O. The PIC assembler instruction to achieve these tasks is by using the byte oriented file register operation bellow: clrf f -> Clear Register f: Register Address (000 to 0x7F)
clrf clrf TRISIO ANSEL ; Set all General Purpose I/O to output ; Make all ports as digital I/O

The last thing to be explained on the initialization routine is the Start: label, this label is used just to clarify that this is beginning of the code; all the labels appear in the codes automatically will be converted to the corresponding program address by the MPASM compiler when we use it such as in the loop and branch instruction. The Infinite Loop After the initialization routine we enter to the infinite loop routine, inside the infinite loop we will turn on the LED attached to the general purpose I/O GP2 do some delay and turn off the LED and do some delay again. In this infinite loop codes we will learn three more PIC assembler instruction beside the two clear bit oriented file register operation instructions youve just learned; to turn on and off the LED.
MainLoop: bsf call bcf call nop goto GPIO,2 Delay GPIO,2 Delay MainLoop ; ; ; ; ; ; Set GP2 Output To High Call Delay Subroutine Clear GP2 Output To Low Call Delay Subroutine No Operation Goto MainLoop

The main function of the infinite loop codes is to turn on and off the LED by setting GP2 bit (2) on the GPIO register to logical 1 and to logical 0.

Therefore by using the bsf and bcf instruction we could simply turn on and off the LED attached to the GP2 port on the GPIO register.
bsf bcf GPIO,2 GPIO,2 ; Set GP2 Output To High ; Clear GP2 Output To Low

Intentionally I put the number 2 instead of GP2, just to remain you that the GP2 bit definition actually is defined as 2 in the P12F683.INC include file mentioned above and also the GPIO register definition. This will become clear when you look at the disassembly code listing on the MPLAB IDE v8.0 (menu View -> Disassembly Listing); you will not get the GP2 or GPIO words, instead you will get their original value as follow:
bsf bcf 0x05,0x2 0x05,0x2 ; Set GP2 Output To High ; Clear GP2 Output To Low

The call and goto instructions are simply tell the PIC microcontroller to jump to the label (program address) and start executes the code from there. The call instruction is used to call the subroutine and when the PIC microcontroller execute this instruction it will save the next instruction program address to the hardware stack and then jump to called program address and when it encounter the return instruction it will retrieve back the program address stored in the hardware stack and put it on the program counter register so the PIC microcontroller could start execute from there.

The PIC12F683 microcontroller has 8 hardware stacks; this mean the maximum calls deep levels are 8. The last instruction inside the infinite loop is the nop (no operation) instruction; this instruction will do nothing, usually is used to put a single instruction delay to the code or simply as the break point to examine the registers content for debugging purpose. The Delay Subroutine In order to be able to watch the on/off LED operation on GP2 port, we have to put the delay subroutine. In this delay subroutine you will learn two more PIC microcontroller assembler instruction. The following is the Delay subroutine code used in the program:
Delay: movlw movwf DelayLoop1: movlw movwf DelayLoop2: decfsz goto decfsz goto return 0xFF Delay2 0xFF Delay1 Delay1,f DelayLoop2 Delay2,f DelayLoop1 ; ; ; ; ; Decrease Delay1, If zero skip the next instruction Not zero goto DelayLoop2 Decrease Delay2, If zero skip the next instruction Not zero goto DelayLoop1 Return to the Caller

The first new instruction is the decfsz which mean decrease the register f, if the register value is zero than skip one instruction: decfsz f,d -> Decreament f: Register Address (000 to 0x7F) , d: Destination -> w: WREG or f: register

If we select the WREG destination (w) than the decrement result value will be put on the WREG (working register) register, if the destination is the register (f) than the result is not passed to the WREG register. Therefore by decreasing the value of general purpose register 021 (Delay1) we could create a simple delay as follow:
DelayLoop2: decfsz Delay1,f goto DelayLoop2 ; Decrease Delay1, If zero skip the next instruction ; Not zero goto DelayLoop2

By using the two loops we could achieve the longer delay. As you see from the PIC assembler code above, the equivalent C code for the delay routine could be written as the following code:
unsigned char Delay1, Delay2; Delay2=0xff; while(Delay2--) { Delay1=0xff; while(Delay1--); }

How exactly we could measure of how long the delay subroutine will give us the desired time delay? The principal here is to calculate how long the PIC microcontroller execute the instruction, because most of the PIC microcontroller instruction will be executed in one instruction cycle than for 8 Mhz clock one instruction cycle will be executed in 0.5 us (micro second). PIC Instruction Clock = System Clock / 4 = 8 Mhz / 4 = 2 Mhz. One cycle Instruction Period = 1 / 2 Mhz = 0.5 us Therefore by calculating all the Delay subroutine PIC assembler instructions (include the loops) we could calculate the exact delay time. Wow this will certainly require a lot of time to calculate it; you may think at the first time, fortunately the Microchip MPLAB IDE v8.0 already provides you with this tool. Now go back to the Microchip MPLAB IDE v8.0 from the menu Debugger activate the StopWatch and set the breakpoint on the call Delay instruction and press the F9 (run), the program will execute until the this breakpoint as shown on this following picture:

Now on the Stopwatch window the simulator will show you the total instruction cycles with the time to execute all the PIC assembler instructions until the breakpoint at 8 Mhz processor frequency.

Click the Zero button on the Stopwatch windows to reset the Stopwatch simulation:

Now we will execute the call Delay subroutine using the simulator debugger Step-Over (F8) command; by pressing the F8 key you will get the total time needed to execute all the instructions inside the Delay subroutine:

The total cycles are 196100 and with the 8 Mhz clock the total time could be calculated as follow: 196100 cycle x 0.5 us = 98050 us = 98.050 ms

So by adding a simple nop command or assign less value to the Delay1 and Delay2 variable in the Delay subroutine you could adjust the delay time to the desired value. The last instruction in the Delay subroutine is the return instruction which simply return and execute the subroutine caller next instruction code as explained above. By learning this simple Hello World PIC assembler program youve already learned 10 of the most used PIC assembler instructions. Reading the PIC Port In our next example of PIC12F683 microcontroller assembler code, I will show you how to read the switch attached to the GP5 port on the GPIO register. This program is the modified version of the Hello World program; the switch will be used as the toggle switch to switch on and off the blinking LED, below is the complete reading port PIC assembler code:
;****************************************************************************** ; File Name : togglesw.asm ; Version : 1.0 ; Description : Toggle Switch ; Author : RWB ; Target : Microchip PIC 12F683 Microcontroller ; Compiler : Microchip Assembler (MPASM) ; IDE : Microchip MPLAB IDE v8.00 ; Programmer : PICKit2 ; Last Updated : 28 March 2009 ; **************************************************************************** #include <p12F683.inc> __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _IESO_OFF & _FCMEN_OFF) cblock 0x20 Delay:2 ; Define two registers for the Delay and Delay + 1 Mode ; Mode endc org 0 Start: bsf movlw movwf movlw movwf clrf movlw movwf bcf clrf MainLoop: btfsc goto call btfsc goto movlw call movlw xorwf NotPress: movlw subwf btfss ; Start at flash address 0 STATUS,RP0 0x70 OSCCON 0x07 CMCON0 ANSEL 0x38 TRISIO STATUS,RP0 Mode GPIO,GP5 NotPress Delay1ms GPIO,GP5 NotPress .100 DelayMs 0x01 Mode,f 0x01 Mode,w STATUS,Z ; Select Registers at Bank 1 ; Set the internal clock speed to 8 Mhz ; ; ; ; ; ; Turn off Comparator (GP0, Make all ports as digital GP3,GP4 and GP5 as Input, TRISIO = 0x38 Back to Registers at Bank Default Mode = 0, LED Off GP1, GP2) I/O GP0 to GP2 as Output 0

; if (GP5 != 0) goto NotPress ; 1 ms Delay for Simple Debounce ; if (GP5 != 0) goto NotPress ; 100 ms delay ; Call DelayMs Subroutine ; XOR the Mode Register with 0x01 ; Put the result on WREG so we could test the status ; if (Mode == 1) goto BlinkLed, else goto LedOff

goto LedOff BlinkLed: movlw (1 << GP2) xorwf GPIO,f ; Toggle GP2 bit movlw .100 ; 100 ms delay call DelayMs ; Call DelayMs Subroutine goto MainLoop ; Goto MainLoop LedOff: movlw ~(1 << GP2) andwf GPIO,f ; Turn off GP2 bit goto MainLoop ; Goto MainLoop ;----------------- DelayMs: Milisecond Delay Subroutine ---------------------; Paramater: WREG = delay amount in milisecond, max: 255 milisecond DelayMs: movwf Delay + 1 DelayLoop: call Delay1ms decfsz Delay + 1,f ; Decrease Delay + 1, If zero skip the next instruction goto DelayLoop ; Not zero goto DelayLoop return ; return to the caller ;----------------- Delay1ms: 1 ms Delay Subroutine --------------------------Delay1ms: ; Total Delay: 1998 x 0.5us ~ 1 ms movlw 0x99 movwf Delay DelayLoop1: decfsz Delay,f ; Decrease Delay, If zero skip the next instruction goto DelayLoop1 DelayLoop2: decfsz Delay,f ; Decrease Delay1, If zero skip the next instruction goto DelayLoop2 ; Not zero goto DelayLoop2 DelayLoop3: decfsz Delay,f ; Decrease Delay1, If zero skip the next instruction goto DelayLoop3 ; Not zero goto DelayLoop2 return ; Return to the caller end ; EOF: togglesw.asm

Inside the PIC Assembler Code If you notice the code from the cblock 020 PIC assembler directive; I use some variation to declare the Delay variable to the general purpose register start on address 020; by defining it as Delay:2, this statement simply tell the MPASM compiler to assign two 8-bit general purpose registers at 020 and 021 to the Delay. To access these registers we simply use Delay and Delay + 1. Another general purpose register at 022 (Mode) is use to hold the switch toggle status. In the PIC initialization routine practically there are no new instructions, I just added the instruction to turn off all the comparator port by setting the comparator configuration register (CMCON0) by assigning all the CM2, CM1 and CM0 bits to logical 1.
movlw movwf 0x07 CMCON0 ; Turn off Comparator (GP0, GP1, GP2)

To make the GP5, GP4 and GP3 ports function as the digital input ports we have to assign to the corresponding bits (TRISIO5, TRISIO4 and TRISIO3) on the TRISIO register to logical 1 (remember on PIC12F683 microcontroller the GP3 port can only be used as the input port).
movlw movwf 0x38 TRISIO ; GP3,GP4 and GP5 as Input, GP0 to GP2 as Output ; TRISIO = 0x38

The Program Main Loop Inside this infinite loop again you will learn five new PIC assembler instructions: btfsc, btfss, xorwf, subwf and andwf. To read the PIC microcontroller port we could use the bit oriented file register operation instructions: btfsc f,b -> Bit test on register f, skip one instruction if it CLEAR (0), f: Register Address (000 to 0x7F) and b: is the bit address btfss f,b -> Bit test on register f, skip one instruction if it SET (1), f: Register Address (000 to 0x7F) and b: is the bit address Therefore to test if the GP5 is pressed (logical 0) on register GPIO, we use the btfsc instruction and we read the port twice for simple debounce algorithm:
btfsc goto call btfsc goto GPIO,GP5 NotPress Delay1ms GPIO,GP5 NotPress ; if (GP5 != 0) goto NotPress ; 1 ms Delay for Simple Debounce ; if (GP5 != 0) goto NotPress

If the switch is pressed then we just toggle the Mode (general purpose register at address 022) value by using the XOR operation: xorwf f,d -> Exclusive OR WREG with register f, f: Register Address (000 to 0x7F) and d: is the result destination.
movlw xorwf 0x01 Mode,f ; XOR the Mode Register with 0x01

By always XORing the Mode register with 001 (in WREG) every time the switch is pressed we could get the desired result. The next routine is to check if Mode is equal to 1 than turn on the blinking LED and if equal to 0 than turn off the blinking LED as this following C pseudo code:
unsigned char Mode; Mode=0; ... If (GP2 == 0) { Mode = Mode ^ 0x01; } If (Mode == 1) { Turn_On_LED(); } else { Turn_Off_LED(); }

To implement this if condition in PIC assembler language we use the principal of this mathematical equation bellow: Mode = 1 Mode 1 = 0 Therefore if we subtract the Mode register (022) with 1 and the result is ZERO than we know that Mode is equal to 1; this can be done by using the PIC assembler subtract instruction and then test the Z (ZERO) bit on the STATUS register. If the Z bit is SET mean the Mode is equal to 1.

subwf f,d -> Subtract WREG with register f, f: Register Address (000 to 0x7F) and d: is the result destination.
movlw subwf btfss goto 0x01 Mode,w STATUS,Z LedOff ; Put the result on WREG so we could test the status ; if (Mode == 1) goto BlinkLed, else goto LedOff

For blinking the LED instead of using the bsf and bcf instructions like in the original Hello World program, I use XOR operation to toggle the GP2 port on GPIO register with the value from the working register (WREG).
movlw xorwf (1 << GP2) GPIO,f ; Toggle GP2 bit

The (1 << GP2) operation is automatically replace with 004 by the MPASM compiler. To turn off the LED; I use the AND instruction to the GP2 port on GPIO register with the value from the working register (WREG): andwf f,d -> AND WREG with register f, f: Register Address (000 to 0x7F) and d: is the result destination.
movlw andwf ~(1 << GP2) GPIO,f ; Turn off GP2 bit

The ~(1 << GP2) operation is automatically replace with 0xFB by the MPASM compiler. The Project Printed Circuit Board (PCB) To make it more interesting Ive designed the printed circuit board (PCB) and the schematic in the EAGLE v5.2.0 format for the Microchip PIC12F683 microcontroller project which you can download from here. The following picture shows the PIC12F683 microcontroller board used in this project:

Downloading the HEX Code After compiling and simulating your code its time to download the code using the Microchip PICKit2 programmer, connect the PICKit2 ICSP (Microchip In Circuit Serial Programming) port to your PIC12F683 microcontroller pins then from the Programmer menu Select Programmer -> PicKit2; You will get this following result on the output windows of the Microchip MPLAB IDE:

Now its time to watch your Microchip PIC12F683 microcontroller Reading the Port Assembler Programming:

The Final Thought

With 15 Microchip PIC assembler instructions youve just learned, actually its almost cover all the basic PIC assembler instructions needed to build a complex application and learning the remaining PIC instructions is not much harder that what youve already learned on this tutorial. Always practicing and reading the PIC assembler code made by other peoples; hopefully this will give you a solid understanding of how to program in PIC assembler language.

S-ar putea să vă placă și