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.
During this activity, you will learn about these microcontroller instructions:
|goto||jump to (or continue running the program) from 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.|
This program introduces many directives. 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 to switch the PIC microcontroller to the bank of file register locations (RAM bank) containing the specified register|
|res||'reserve memory' - reserves the specified number of program memory addresses|
|end||signifies the end of the program|
Output programming activity
Let's start CHRP programming by making it turn 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.
To use this program you will need:
• An assembled CHRP board.
• A Windows PC with the MPLAB IDE software.
• A Microchip PIC-kit2 USB programmer, a stand-alone PIC programmer, or a PIC16F886 microcontroller pre-programmed with bootloader code (see the PIC info page)
• 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 2.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 arthitectural 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.ASM v2.0 Last modified on December 1, 2008 ;=============================================================================== ;Description: Output test program. Lights up PORTB LEDs. ;Start of MPLAB and processor configuration. 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 ;End of MPLAB and processor configuration. org 00h ;Start of program memory goto initPorts ;Jump to initialize routine org 05h initPorts ;Set Ports B and C to support CHRP digital circuitry. banksel ANSELH ;Switch register banks movlw 01010111b ;Enable Port B pull-ups, TMR0 internal movwf OPTION_REG ;clock, and 256 prescaler clrf ANSELH ;Set all PORTB pins to digital clrf TRISB ;Set all PORTB pins as outputs for LEDs banksel TRISC ;Switch register banks movlw 10110000b ;Setup serial input and output pins, movwf TRISC ;and set motor outputs banksel PORTB ;Return to PORTB register bank main movlw 11000011b ;Send light pattern to movwf PORTB ;Port B LEDs sleep ;Done. Shut down org 1F00h ;Start of bootloader code area res 256 ;Reserve memory for bootloader 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, that the __config directives are entered exactly as shown, and that the project settings for the program disable case sensitivity and use decimal as the default radix (see 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 (LED2 and LED3), and the bottom two (LED8 and LED9).
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.ASM v2.0 Last modified on December 1, 2008 ;=============================================================================== ;Description: Output test program. Lights up PORTB LEDs. ;Start of MPLAB and processor configuration. 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 ;End of MPLAB and processor configuration. org 00h ;Start of program memory goto initPorts ;Jump to initialize routine org 05h
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 the program into the micrcocontroller's program memory. By using a data address of 00h, org tells MPLAB to store the first program instruction into the first memory location (address 0000h), which is also known as the Reset Vector. The Reset Vector in the PIC is the first memory location that the microcontroller goes to on power-up or after a hardware reset, so 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. Since the initPorts label follows the org 05h directive, this instruction actually becomes goto 05h after the assembler's second pass. Rather that say that, though, using label names helps to make the program more readable for us.
initPorts ;Set Ports B and C to support CHRP digital circuitry. banksel ANSELH ;Switch register banks movlw 01010111b ;Enable Port B pull-ups, TMR0 internal movwf OPTION_REG ;clock, and 256 prescaler clrf ANSELH ;Set all PORTB pins to digital clrf TRISB ;Set all PORTB pins as outputs for LEDs banksel TRISC ;Switch register banks movlw 10110000b ;Setup serial input and output pins, movwf TRISC ;and set motor outputs banksel PORTB ;Return to PORTB register bank
The initPorts label identifies the next group of instructions. As the label implies, this section of the program prepares the microcontroller ports so that we can get it ready for outputting 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 ANSELH is a directive that tells MPLAB to insert the instruction(s) needed to switch to the file register bank (RAM bank) containing the ANSELH register. The microcontroller block diagram shows us that the ANSELH register is in bank 1 of the file memory. We need to use this instruction to tell the microcontroller to switch memory banks because it powers up in bank 0.
The next two instructions work together to change the contents of a file register (RAM). In fact, this will be a very common pairing that 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 1. movwf is the assembly code instruction 'move W to file register'. But, why did we specify the ANSELH register when we did the bank switch? Shouldn't we have used OPTION_REG instead? Even though we used the banksel to specify ANSELH, we can now write to OPTION_REG because both registers reside in bank 1—and ANSELH is easier to type. 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, we'll work on ANSELH. The clrf ANSELH instruction is a quick way to fill the ANSELH register with zeros. clrf represents the 'clear file register' function, and doing so sets PORTB to digital I/O mode—this microcontroller starts up with PORTB in analogue I/O mode. In the next line, writing zeros into all of the TRISB bits makes all of the PORTB pins (those connected to the LEDs) into outputs. Conversely, putting ones into TRIS bits would have made those I/O pins into inputs. But, since the purpose of this program is to test the LEDs, we want all of the PORTB pins to be outputs.
movlw 10110000b and movwf TRISC write the data 10110000 into the TRISC register to make some of the PORTC pins outputs, while keeping some as inputs (on power-up all of the I/O pins are inputs by default). If you look at the parts connected to PORTC on the CHRP schematic, and it should become clear why this combination of inputs and outputs is used.
Finally, banksel PORTB tells the assembler to switch back to addresses in file register bank 0, finishing the initPorts subroutine. All that code, and the only thing that's been accomplished is getting the microcontroller ready to turn on the LEDs.
The main subroutine
main movlw 11000011b ;Send light pattern to movwf PORTB ;Port B LEDs sleep ;Done. Shut down org 1F00h ;Start of bootloader code area res 256 ;Reserve memory for bootloader 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 LED2 (the top LED) for example, change the data to 00000001b.
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.
Finally, the org 1F00h and res 256 directives instruct MPLAB to reserve the last 256 locations of the microcontroller's memory, protecting the contents of these addresses from being overwritten. These last 256 program memory addresses may contain a bootloader program (depending on how you're programming your particular PIC), and these directives protect this space to ensure the bootloader isn't accidentally over-written.
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!)
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, sometime, 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 16µs (microseconds), or sixteen 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
- 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?
- The Output program contains six different directives. List each directive and describe its function.
- The PIC16F886A microcontroller contains more than one kind of memory. What kind of memory are the file registers made of? What special features do the PORTA, PORTB, and PORTC file registers have?
- 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?
- What is the W register, and in what part of the microcontroller is it located?
- What is the function of the TRISA, TRISB, and TRISC registers?
- 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?
- 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
- Modify the Output program to turn on all of PORTB LEDs (useful for testing your circuit board if you haven't already done so).
- 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.
- The CHRP motor driver IC can control two DC motors by moving data into the low nybble (the 4 least significant bits) of PORTC. Use the schematic diagram to help you determine the bit patterns required to make each motor turn forward, reverse, or stop. Connect motors to the CHRP board and verify their operation.