Program description

What does it do?

The Decision program demonstrates how to make decisions in your programs.

New instructions

None. But, you will learn about two different ways in which the movf instruction can be used.

Decision programming activity

Now that you've seen the basics of PIC Math instructions, the Decision program demonstrates how to use decision structures in your code. Decision structures are typically composed of math instructions followed by conditional tests of the status register flag bits, allowing you to check for equality, do less than or greater than comparisons, and find zero results.

What you should know before starting

Status register bits

Three of the Status register bits, Z (Zero) bit, DC (Digit Carry) and C (Carry), are affected by all math operations. The code in the decision program will (mostly) perform a subtraction operation and then check the state of these bits to determine if two variables are equal, or which one is greater or smaller. Checking for zero can be done without subtracting.

Remember that during simulation, the state of the Z, DC, and C bits is shown in the bottom status bar of the MPLAB IDE. Their state is represented by the letter state—an upper-case letter means the bit is set, and a lower case letter means the bit is clear. For example, seeing Z dc C indicates that a Carry has taken place, the result of the operation is zero, and no digit carry occurred. Of course, you can also open a watch window to check the Status state.

Each Status register bit corresponds to specific states:

Program requirements

To use this program you will need:

An assembled CHRP 3 board, an optional power supply, a programmer and/or programming cable, and a computer with the MPLAB IDE or MPLAB X software as described in the Output activity.

Create the program

The entire DECISION.ASM program is shown below. Create a Decision project in MPLAB, copy this code into it, and build the program.


;Decision		v3.1	January 14, 2013
;===============================================================================
;Description:	Demonstrates math between constants, constants and registers,
;				and registers.

;Configure MPLAB and the microcontroller.

	include	"p16f886.inc"		;Include processor definitions

	__config _CONFIG1, _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTOSCIO
	__config _CONFIG2, _WRT_OFF & _BOR40V

;Set RAM register equates.

num1			equ	20h				;RAM storage register for the first number
num2			equ	21h				;RAM storage register for the second number

;Start the program at the reset vector.

				org	00h				;Reset vector - start of program memory

				clrf	PORTA		;Clear all port outputs before configuring
				clrf	PORTB		;port TRIS registers. Clearing RA4 turns on
				clrf	PORTC		;the Run LED when TRISA is initialized.

				goto	initPorts	;Jump to initialize routine

				org	05h				;Continue program after the interrupt vector

initPorts       ;Configures PORTA and PORTB for digital I/O.

				banksel	ANSEL		;Switch register banks
				clrf	ANSEL		;Set all PORTA pins to digital
				clrf	ANSELH		;Set all PORTB pins to digital
				movlw	01010111b	;Enable Port B pull-ups, TMR0 internal
				movwf	OPTION_REG	;clock, and 256 prescaler
				banksel	TRISA		;Switch register banks
				movlw	00101111b	;Set piezo and LED pins as outputs and
				movwf	TRISA		;all other PORTA pins as inputs
				clrf	TRISB		;Set all PORTB pins as outputs for LEDs
				banksel	PORTA		;Return to register bank 0

main			movlw	6			;Preload the number registers for later use
				movwf	num1
				movlw	0
				movwf	num2

equalsZero		;Decide if a number is zero by checking the Z flag

				movf	num1,W		;Copy the contents of num1 into W and
				btfsc	STATUS,Z	;check for zero result
				bsf		PORTB,0		;If zero, turn an LED on

				movf	num2,F		;Evaluate the contents of num2 and
				btfsc	STATUS,Z	;check for zero result
				bsf		PORTB,0		;If zero, turn an LED on

equalsNumber	;Decide if one number equals another by subtracting one number
				;from the other and checking for a zero result.

				movwf	num2		;Copy the contents of W into num2

				movf	num1,W		;Copy contents of num1 into W and
				subwf	num2,W		;compare with num2 by subtraction
				btfsc	STATUS,Z	;Skip if the result is not zero (Z=0)
				bsf		PORTB,1		;Turn an LED on if numbers are equal

greaterThan		;Decide if one number is larger than another by subtracting
				;and checking the Carry/!Borrow bit. Carry is set at the start
				;of a subtraction and is borrowed from (cleared) if necessary.

				movlw	4			;Preload num2 with a new number
				movwf	num2

				movf	num1,W		;Copy contents of num1 into W and
				subwf	num2,W		;compare by subtracting from num2
				btfss	STATUS,C	;Skip if no borrow occurred (C=1)
				bsf		PORTB,2		;If borrow occurred, num1 > num2

lessThan		;Decide if one number is smaller than another by subtracting
				;and checking the Carry/!Borrow bit. As above, but checks the
				;opposite order and condition.

				movf	num2,W		;Copy contents of num2 into W and
				subwf	num1,W		;compare with num1 by subtraction
				btfsc	STATUS,C	;Skip if a borrow occurred (C=0)
				bsf		PORTB,3		;If no borrow occurred, num1 < num2

				sleep				;Stop at end of program

				end
		

As with Math, you won't need to download this program to your CHRP board—just run it in the MPLAB Sim debugger. Set up a watch window to watch the contents of the W register and file registers 20h and 21h. You can also watch the Status register if you like, or just check the Z, DC and C bits in the status bar at the bottom of the MPLAB window. Step through the program and observe the contents of the registers and Status bits after each step.

How the program works

Similar to the Math program, there is nothing really complex happening in this code. You should be able to fully understand what is happening by working your way through the code or watching the code run in the simulator. There are, however, some hints that might make it easier for you to use decision structures in your programs.

Hint 1 - "Touch it" to check for zero


equalsZero		;Decide if a number is zero by checking the Z flag

				movf	num1,W		;Copy the contents of num1 into W and
				btfsc	STATUS,Z	;check for zero result
				bsf		PORTB,0		;If zero, turn an LED on

				movf	num2,F		;Evaluate the contents of num2 and
				btfsc	STATUS,Z	;check for zero result
				bsf		PORTB,0		;If zero, turn an LED on
		

Both of the above code structures check for zero. The first copies a number into W, the second does not. It's perfectly ok to check the state of a register (zero or non-zero) by moving the register to itself using ,f (essentially, just 'touching' it), with the added advantage that another number can be retained in W during this process.

To demonstrate this, the content of num1 is copied into num2 in the next step, after num2 is checked for zero:


equalsNumber	;Decide if one number equals another by subtracting one number
				;from the other and checking for a zero result.

				movwf	num2		;Copy the contents of W into num2
		

Hint 2 - Skip over to continue

The PIC microcontroller's bit test and skip instructions skip over one line of code if the condition is true. If the code that will execute if the condition is false fits on one line of code, add it inline (as shown):


				movf	num1,W		;Copy contents of num1 into W and
				subwf	num2,W		;compare with num2 by subtraction
				btfsc	STATUS,Z	;Skip if the result is not zero (Z=0)
				bsf		PORTB,1		;Turn an LED on if numbers are equal
		

In this subroutine, a zero result turns on an LED – an operation that can execute in one line. If the code that needs to execute after a false condition is longer than one line, you'll have to use a goto to branch to a subroutine containing the code, like this:

				movf	num1,W		;Copy contents of num1 into W and
				subwf	num2,W		;compare with num2 by subtraction
				btfsc	STATUS,Z	;Skip if the result is not zero (Z=0)
				goto	doZeroCode	;Goto a subroutine that handles zero result
				more	code		;Continue executing code if not zero
		

Hint 3 - Don't destroy your variables


				movf	num1,W		;Copy contents of num1 into W and
				subwf	num2,W		;compare by subtracting from num2
				btfss	STATUS,C	;Skip if no borrow occurred (C=1)
				bsf		PORTB,2		;If borrow occurred, num1 > num2
		

In the example code, above, W is used to store both the first number for the comparison and also the result of the comparison test. By doing the math in W, the original variables are maintained and are available for use in later subroutines.

Test your knowledge

  1. How does movf register,W differ from movf register,f?
  2. What is the order of subtraction in a subwf instruction. How do you know?
  3. Does the example code in the decision program make it possible to check for one number being less than or equal to another? Why or why not?

Apply your skills

  1. Modify the Analogue program to compare an analogue input with a fixed threshold, or to compare one analogue input to another, and then indicate the difference using the LEDs. For example, you could check the level of the potentiometer and light an LED if it exceeds the value of 200 and another LED if it falls below 60. Or, you could compare the amount of light seen by Q1 with Q2 and light one LED if Q1's light level is greater and another LED if Q2's light level is greater. Make sure to document your program well.