Program description

What does it do?

The output program shows you how to light up the CHRP board LEDs. Once you know how to turn on lights, it's just as easy to turn on motors and other output devices.

New instructions

During this activity, you will learn how to use these microcontroller instructions:

goto jump to (or continue running the program from) a new location (called an address) or a label
movlw 'move literal to W' - move a number (also known as a literal, or constant) into W (the working register)
movwf 'move W to file register' - move the number in W (the working register) to a file register (a RAM location)
clrf 'clear file register' - clear the contents of a file register (a RAM location)
sleep stop the microcontroller clock and shut down the processing unit. During sleep, port output pins remain in their last state.

New directives

This program introduces many directives. Just like instructions, directives are a part of the program. But, unlike instructions, which actually control the microcontroller, directives control the operation of the MPLAB assembler, the programmer or the downloader.

include inserts the named file into the program
__config sets up the hardware features of the microcontroller (dependent on a programmer that can read these settings)
org 'origin' - sets the program memory address for the next instruction
banksel 'bank select' - inserts instructions for the PIC microcontroller to switch to the bank of file registers (RAM bank) containing the requested register
end signifies the end of the program

Output programming activity

Let's start CHRP programming by turning on some LEDs. If you assembled your CHRP from scratch, this is a good place to start because you can use the Output program to test the functionality of your circuit as well as your LEDs.

Program requirements

To use this program you will need:

• An assembled CHRP board.

• A computer with either the MPLAB X or MPLAB IDE (Integrated Development Environment).

• A Microchip PIC-kit 2 or PIC-kit 3 USB programmer or a stand-alone PIC programmer

• A 6-12V wall adapter, or a power supply, or batteries to power the CHRP.

Before you continue, you will need to know how to edit, assemble and simulate a program in MPLAB (see the MPLAB tutorial).

What you should know before starting

CHRP related information

This program controls the LEDs connected to PORTB of the PIC microcontroller (see the CHRP 3.0 schematic to examine the PORTB circuitry).

Microcontroller related information

PORTB is an 8-bit RAM register (known as a file register Microchip terminology) that connects the processing unit core to external I/O (input/output) pins. PORTB is an 8-bit port, so it can control 8 individual circuits. Each of the PORTB pins can be set to be either an input or an output, depending on the value of an associated bit in the TRISB register.

TRISB (TRIState for port B) is, like PORTB, also an 8-bit file register (or, RAM memory location). Each bit of the TRISB register controls the input/output status of its associated PORTB I/O pin. When a value of 0 is written into a TRISB bit, it makes the corresponding PORTB pin an output. Conversely, when a value of 1 is written into a TRISB bit, it makes the corresponding PORTB pin an input. For example, writing the 8-bit number 00000111 into TRISB would cause the upper five PORTB pins (referring to the left-most bits, or highest digits as the 'upper' pins) to become outputs, and the lower three PORTB pins to become inputs.

The PORTB and TRISB file registers are located in two different file register pages (or, RAM banks) inside the microcontroller (see the simplified PIC16F886 block diagram for an architectural overview of the microcontroller). The PIC contains a register known as the STATUS register, which controls access to the register banks, amongst other thing. In the Output program, we'll use the banksel directive (see New Directives at left for its description) to indirectly control the STATUS register, because it makes programming easier for us than controlling the STATUS register directly.

Another register that will see a lot of use is the W, or Working register (see the simplified block diagram, above). Almost all math, logic and data movement instructions in the PIC microcontroller involve the use of W. The Output program, for example, lights the LEDs by moving a pattern entered in the program (and stored in the program memory) to the W register first, and then from W to the PORTB file register. In PIC microcontrollers, any movement of data from the program memory to a RAM file register requires this same kind of two-step movement—first to move data into W, then to move the date to its destination file register.

Create the program

The entire OUTPUT.ASM program is shown below. Start a new MPLAB project, copy all of the OUTPUT.ASM code into the project, and assemble (make) the program.


;OUTPUT			v3.1	January 14, 2013
;===============================================================================
;Description:	Output test program. Initializes the PIC16F886 I/O pins for LED
;				output on the CHRP 3.0, and demonstrates port output.

;Configure MPLAB and the microcongtroller

	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

;Start the program at the reset vector

				org	00h				;Reset vector - start of program memory

				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
				
				clrf	PORTA		;Clear all PORTA outputs and turn on Run LED

main			movlw	11000011b	;Send this pattern to the
				movwf	PORTB		;Port B LEDs

				sleep				;Done - shut down microcontroller core

				end
		

If the program does not assemble, or generates errors or warnings during assembly, check that you didn't accidentally miss any of the code (such as the first semi-colon, or the end statement), and that the project settings disable case sensitivity and use decimal as the default radix (review the steps in the MPLAB tutorial).

Once the Output program builds successfully, program it into your microcontroller to see it work. Four lights should be lit—the top two (LED3 and LED4), and the bottom two (LED9 and LED10).

How the program works

You might want to reference the simplified PIC16F886 block diagram to help visualize what happens inside the microcontroller during the following explanations.

Comments and directives

This program, like most programs, starts with some comments. In MPLAB, any characters following a semi-colon (;) are treated as comments and are ignored by the assembler. Comments are included in programs to provide additional information for us humans, the programmers.


;OUTPUT			v3.1	January 14, 2013
;===============================================================================
;Description:	Output test program. Initializes the PIC16F886 I/O pins for LED
;				output on the CHRP 3.0, and demonstrates port output.

;Configure MPLAB and the microcongtroller

	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

;Start the program at the reset vector

				org	00h				;Reset vector - start of program memory

				goto	initPorts	;Jump to initialize routine

				org	05h				;Continue program after the interrupt vector
		

The include and __config directives prepare MPLAB to support the chosen processor type by inserting, or including, a file containing information about the processor into the program, and by configuring the processor's hardware functions.

Directives are commands meant to be read and understood only by the assembler—they are not the same as the instructions which will be programmed into the microcontroller.

org 00h is a directive that tells the assembler where to write program instructions into the micrcocontroller's program memory. By using a data address of 00h, org tells MPLAB to store the first program instruction in the first memory location (address 0000h), which is also known as the Reset Vector. The Reset Vector is the first location that the microcontroller goes to on power-up or after a hardware reset. As a result, the first program instruction must always be stored there.

Immediately following the org 00h directive is the goto initPorts instruction. The data portion of the instruction, initPorts, refers to the initPorts label (two lines further down in the program), but MPLAB wouldn't know this yet—computers can't read ahead like we can. The MPLAB assembler will actually read the entire program twice: the first time (called the first pass) it tries do resolve labels and their addresses, and then it re-reads the program (the second pass), substituting the details it didn't know the first time as it generates the program code. Since the initPorts label follows the org 05h directive, this instruction actually becomes goto 05h after the assembler's second pass. Rather than having to code that ourselves, though, using label names helps to make the programming more flexible and readable for us.

Processor initialization


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
				
				clrf	PORTA		;Clear all PORTA outputs and turn on Run LED
		

The initPorts label identifies the next group of instructions. As the label implies, this section of the program prepares the microcontroller ports so that they can output to the LEDs. The word initPorts itself has no other meaning than just being a name for this part of the program. We could have named the routine by any other name instead, but it just makes sense to give program subroutines names that describe what they actually do—initialize the input/output (I/O) ports, in this case.

banksel ANSEL is a directive that tells MPLAB to insert the instruction(s) needed to switch to the file register bank (RAM bank) containing the ANSEL register. The microcontroller block diagram shows us that the ANSEL register is in bank 3 of the file memory. We need the banksel directive to tell the microcontroller to switch memory banks because it powers up in bank 0, or restarts there after a reset.

The next two instructions clear (writes zeros into) the ANSEL and ANSELH registers in RAM. The comments explain that clearing these registers sets the port pins to digital I/O mode. How would we know this? The microcontroller datasheet provides all of the information on how to configure the ports and it turns out that PORTA and PORTB are configured as analogue input pins on power-up. Clearing the ANSEL registers sets up the ports for digital I/O.

The following two instructions work together to change the contents of a the Option_Reg register, also in RAM. In fact, this pairing of instructions is very common in PIC assembly code and will occur a few more times in this program. movlw stands for 'move literal to W', and it does just that. It moves the value supplied by the program into W. In this case, movlw 01010111b moves the data 01010111 (which is the literal) from the PIC's program memory into the W (working) register inside the core of the processing unit.

From there, movwf OPTION_REG moves the data from W to the OPTION_REG register in bank 3. movwf is the assembly code instruction 'move W to file register'. The value in OPTION_REG controls a number of the microcontroller's internal features, but we'll look at its function more closely in some of the following activities.

Now that OPTION_REG has been modified, it's time to set up some of the external I/O ports. To do so, we'll use the banksel directive again to switch to the register page containing the TRISA register, and the movlw, movwf instructions to set and clear individual TRISA bits. After this, clrf TRISB clears all of the TRISB register bits.

Writing zeros into all of the TRISB bits makes all of the PORTB pins outputs—which is exactly what we want since the PORTB pins connect to the LEDs. Conversely, writing ones into TRIS bits would have made those I/O pins into inputs. Any combination of zeros and ones can be used to set some register pins as inputs and some as outputs. But, for this program, we want all of the PORTB pins to be outputs.

Finally, banksel PORTA tells the assembler to switch back to addresses in file register bank 0, so that the next instruction, clrf PORTA will act on the PORTA register. Clearing all of the PORTA pins turns off the beeper and infrared LEDs and turns on the Run LED. So far, all that all of this code has accomplished is to get the microcontroller ready to turn on the LEDs

The main subroutine


main			movlw	11000011b	;Send this pattern to the
				movwf	PORTB		;Port B LEDs

				sleep				;Done - shut down microcontroller core

				end
		

The main label starts the functional code of the output program. As with the initPorts label, main has no inherent meaning and could have been named anything else instead.

Also, as seen earlier, the combination of movlw 11000011b and movwf PORTB instructions moves data from the program memory, through W, into the microcontroller's file (RAM) registers. Since the PORTB register connects to the LEDs, the LEDs light up in a pattern matching the data. By referring to the schematic diagram and the circuit board while programming, you can choose which LEDs to light. To light just LED3 (the top LED) for example, change the data to 00000001b.

Finishing up

sleep is probably fairly self-explanatory, which is a good thing since you're probably a bit frazzled from having digested so much assembly code! During sleep, the micrcocontroller shuts its processing core down, but keeps its I/O circuits powered. So, although no more instructions are being executed by the microcontroller, the LEDs will remain lit while the processor core is asleep.

The end directive is required to tell the assembler when it has reached the end of the program code. MPLAB ignores anything written after end, so you can use the space below the program to keep notes about the program, write reminders to yourself about new features, create a shopping list, etc. (Okay, maybe you should find a better way to do a shopping list!)

Program simulation

MPLAB has a built-in program simulator called MPLAB-Sim. The simulator can be used to verify the operation of the Output program before downloading it into your microcontroller. The simulator gives you a virtual peek inside the processor, so you can visually watch what your program code is doing—or, sometimes, not doing! Simulators are also able to time the execution of your program, which becomes very important in many microcontroller applications.

Oh, in case you were wondering, running this program in a 4MHz PICmicro takes 18µs (microseconds), or eightteen millionths of a second. Then, with it's work all done and the appropriate lights turned on, the microcontroller goes to sleep.

Test your knowledge

  1. Assembly code programs contain comments, labels, directives, instructions, and data. What is the difference between a directive and an instruction? What is the difference between a comment and a label?
  2. The Output program contains five different directives. List each directive and describe its function.
  3. The PIC16F886A microcontroller contains more than one type of memory. What type of memory are the file registers made of? What special features do the PORTA, PORTB, and PORTC file registers have?
  4. We refer to registers by name, but the microcontroller refers to registers by their numeric address. What are the addresses of the TRISB and PORTB registers?
  5. What is the W register, and in what part of the microcontroller is it located?
  6. What is the function of the TRISA, TRISB, and TRISC registers?
  7. What value would need to be written into the TRISB register to make the bottom six LEDs of the CHRP board into outputs, and the other PORTB pins into inputs?
  8. Each program instruction takes one or more processor clock cycles to execute. Use the stopwatch in the MPLAB simulator to determine how many clock cycles each instruction takes to run. (Set the processor frequency to 4MHz to match the PIC in the CHRP board.)

Apply your skills

  1. Modify the Output program to turn on all of PORTB LEDs (useful for testing your circuit board if you haven't already done so).
  2. Modify the Output program to repeatedly display two or more different light patterns on the LEDs and program it into your CHRP (hint: create another output pattern, and use a goto instruction to repeat both patterns). Run the program and describe its output. Is it what you expected? Explain why not.
  3. The CHRP's motor driver IC can control two DC motors based on the data into the low nybble (the 4 least significant bits) of PORTB. Use the schematic diagram to help you determine the bit patterns required to make each motor turn forward, reverse, or stop. Connect motors to your CHRP board and verify their operation.