Program description
What does it do?
The analogue program inputs an analogue value from the potentiometer or one of the other analogue devices on the CHRP board, and displays the result on the LEDs.
New instructions
During this activity, you will learn about these microcontroller instructions:
| nop | 'no operation' - causes the microcontroller do to nothing for one clock cycle. nop is often used to add a pad a loop or subroutine to achieve precise timing. |
Analogue programming activity
The Analogue program demonstrates the process of converting an external input to a binary value, as well as showing the use of the W register to pass a variable during a subroutine call.
What you should know before starting
Microcontroller related information
The PIC16F886 microcontroller hardware contains a 10-bit analogue-to-digital (A-D) converter which is connected to 11 of the Port A and Port B input pins through an input selector. The A-D converter is a separate circuit from the microcontroller core, and must be powered up and initialized before a conversion can begin. It can be powered down at any time between conversions to reduce the microcontroller's current consumption.
The A-D conversion process is performed by successive approximation using a successive approximation register, D-A converter and a comparator. In other words, the A-D converter zeroes in on the analogue value by repeatedly guessing the voltage, comparing its guess to the input, and reducing its possibilities by half each time. (eg. If I'm thinking of a number between 1 and 10, a good first guess would be 5. If the number was higher, your next guess might be 7, and so on.) Using this method, it takes 10 A-D converter clocks to arrive at the final output value. The A-D converter clock is independent of the microcontroller clock and typically runs at a slower rate.
The 10-bit digital conversion result is stored in two registers and can be configured to be read out as a right- or left-justified number. This program will only use the eight most significant bits of the result, providing a possible 256 states, rather than the full 1024 states a 10-bit conversion would provide.
Program requirements
To use this program you will need:
An assembled CHRP board, microcontroller, and power supply, a programming cable, and a Windows PC with the MPLAB IDE software and downloader software as described in the Output activity.
Create the program
The entire ANALOGUE.ASM program is shown below. Create an Analogue project in MPLAB, copy this code into it, and build the program.
;ANALOGUE.ASM v2.1 Last modified on January 17, 2011 ;=============================================================================== ;Description: Displays the analogue input level as a binary number on the 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. ;Start of hardware equates LED10 equ 7 ;Port A bit position of LED10 ;End of hardware equates ;Start of software equates adQ1 equ 00000000b ;A-D channel 0 (Q1 phototransistor) adQ2 equ 00000100b ;A-D channel 1 (Q2 phototransistor) adPot equ 00001000b ;A-D channel 2 (VR1 potentiometer) adTemp equ 00001100b ;A-D channel 3 (U7 temperature sensor) ;End of software equates org 00h ;Start of program memory clrf PORTA ;Turn off all port outputs clrf PORTB clrf PORTC goto initPorts ;Jump to initialize subroutine org 05h adConvert ;First, select the A-D channel by non-destructively writing the ;channel code from W into ADCON0 (see channel constants, above). ;Then, initiate A-D conversion on the selected A-D channel. Keep ;polling the Go_Done bit until conversion finishes. bsf ADCON0,ADON ;Turn A-D converter on movwf ADRESH ;Use ADRES as temporary channel storage movlw 11000011b ;Load W with 11000111 and andwf ADCON0,F ;AND with ADCON0 to clear CHS0-2 movf ADRESH,W ;Get channel select bits from ADRES iorwf ADCON0,F ;OR with ADCON0 to set channel bits nop ;Allow input to settle after ch switch bsf ADCON0,GO_DONE ;Start A/D conversion adConLoop btfsc ADCON0,GO_DONE ;Check GO_DONE for end of conversion goto adConLoop ;and keep checking until done bcf ADCON0,ADON ;Turn A-D converter off return initPorts ;Set Ports A, B and C to support the attached CHRP circuitry. banksel ADCON1 ;Switch register banks clrf ADCON1 ;Set A-D for left justified result, banksel ADCON0 ;VDD reference voltage movlw 01000000b ;Set A/D conversion clock for 4MHz movwf ADCON0 ;operation, but leave A/D off banksel ANSEL ;Switch register banks movlw 01010111b ;Enable Port B pull-ups, TMR0 internal movwf OPTION_REG ;clock, and 256 prescaler movlw 00001111b ;Set PORT A pins 0-3 as analogue, movwf ANSEL ;and the others as digital I/O clrf ANSELH ;Set all PORTB pins to digital I/O banksel TRISA ;Switch register banks movlw 01011111b ;Setup LED and beeper outputs, and movwf TRISA ;make all other PORTA pins inputs clrf TRISB ;Make all PORTB pins outputs movlw 10110000b ;Setup serial input and output pins, movwf TRISC ;disable LCD control, set motor outputs banksel PORTB ;Return to PORTB register bank bsf PORTA,LED10 ;Turn on LED10 as light source for Q1, Q2 adTest ;Display analogue value on Port B LEDs. movlw adPot ;Set A-D to potentiometer input and call adConvert ;start A-D conversion movf ADRESH,W ;Copy A-D result into W and movwf PORTB ;display it on LEDs call timeDelay ;Pause for ~50ms goto adTest ;Continue forever timeDelay movlw 61 ;Preload TMR0 for 50ms time period movwf TMR0 checkTimer movf TMR0,W ;Check TMR0 value btfss STATUS,Z goto checkTimer ;Repeat until TMR0 = 0 return ;Return when done end
Download the program into the CHRP and verify its operation by turning the potentiometer. The Port B LEDs will output the binary number corresponding to the position of the potentiometer.
How the program works
The start of the program and port initialization are similar to the previous programs, except that this program performs A-D initialization and configures the analogue input pins. The initPorts subroutine also follows the adConvert subroutine instead of being the first block of code after the reset code. The relative positions of the subroutines is not important, but by placing initPorts just about the main program code no goto instruction is required to continue the program.
initPorts ;Set Ports A, B and C to support the attached CHRP circuitry. banksel ADCON1 ;Switch register banks clrf ADCON1 ;Set A-D for left justified result, banksel ADCON0 ;VDD reference voltage movlw 01000000b ;Set A/D conversion clock for 4MHz movwf ADCON0 ;operation, but leave A/D off banksel ANSEL ;Switch register banks movlw 01010111b ;Enable Port B pull-ups, TMR0 internal movwf OPTION_REG ;clock, and 256 prescaler movlw 00001111b ;Set PORT A pins 0-3 as analogue, movwf ANSEL ;and the others as digital I/O clrf ANSELH ;Set all PORTB pins to digital I/O banksel TRISA ;Switch register banks movlw 01011111b ;Setup LED and beeper outputs, and movwf TRISA ;make all other PORTA pins inputs
The ADCON0 and ADCON1 registers control the operation of the A-D converter (see the microcontroller datasheet for all of the A-D converter setup details and channel selection). ANSEL is used to configure whether PORTA pins will be analogue or digital inputs, and the TRISA register must be configured with the analogue pins set as inputs.
Following port initialization, the floor LED, LED10, is turned on. It may or may not be installed in your CHRP board, but LED10 is the source of IR illumination for the phototransistors Q1 and Q2.
The program continues with the movlw adPot instruction. adPot was previously equated to a constant that will be used by the adConvert subroutine to select the potentiometer input. The adPot value will be held in W during the call and will be used by the adConvert subroutine to select the requested input channel for conversion.
adConvert ;First, select the A-D channel by non-destructively writing the ;channel code from W into ADCON0 (see channel constants, above). ;Then, initiate A-D conversion on the selected A-D channel. Keep ;polling the Go_Done bit until conversion finishes. bsf ADCON0,ADON ;Turn A-D converter on movwf ADRESH ;Use ADRES as temporary channel storage movlw 11000011b ;Load W with 11000111 and andwf ADCON0,F ;AND with ADCON0 to clear CHS0-2 movf ADRESH,W ;Get channel select bits from ADRES iorwf ADCON0,F ;OR with ADCON0 to set channel bits nop ;Allow input to settle after ch switch bsf ADCON0,GO_DONE ;Start A/D conversion adConLoop btfsc ADCON0,GO_DONE ;Check GO_DONE for end of conversion goto adConLoop ;and keep checking until done bcf ADCON0,ADON ;Turn A-D converter off return
adConvert first enables the A-D converter by powering it up using bsf ADCON0,ADON. Two logical operations, an AND followed by an OR will be used to selectively clear and then set the A-D channel selection bits. Before that can happen though, the channel value written into W before the call must be temporarily saved. movwf ADRESH copies the channel value into the A-D converter result register. Since the conversion hasn't yet started, the result register will either contain invalid data (if this is the first time the A-D is used), or the result of the previous conversion (which will be overwritten anyway), and can therefore be used as temporary storage without requiring the use of a separate RAM register.
After the conversion channel is stored, the next two lines selectively clear the A-D channel selection bits in preparation for the movf ADRESH,W and iorwf ADCON0,F instructions which OR the channel value into ADCON0. After selecting or switching channels, the A-D input capacitor needs time to charge to the new value. A one-cycle time delay is provided by the nop instruction.
Finally, setting the ADCON0,GO_DONE bit starts the conversion process. When the conversion is complete, the A-D converter circuit will reset the GO_DONE bit, but this won't happen until 10 A-D clock cycles have passed. adConLoop waits until the conversion is complete and then turn off the A-D converter for energy savings before returning to the calling subroutine.
The new A-D conversion result is in the ADRESH (A-D RESult High) register, one of two that holds the 10-bit conversion result. By left-justifying the result and reading only the high byte the program retrieves only the most significant eight bits of the conversion. Since ten bits of accuracy are not required, processing an eight bit result is more convenient but only resolves 256 states instead of 1024. The 8-bit conversion result is displayed on the LEDs, and after a short time delay, the conversion process repeats
Test your knowledge
- Rotate the potentiometer all the way counterclockwise. Record the conversion value. Next, rotate the potentiometer all the way clockwise. Record this value. What binary value should correspond to the mid-way position?
- What is the bit address of the GO_DONE bit, and which register is it found in?
- Use the simulator to determine how many clock cycles an A-D conversion takes to complete once the GO_DONE bit is set.
Apply your skills
- The A-D converter performs a 10-bit conversion, but this program only shows the eight most significant bits. The two least significant bits are found in the ADRES (no 'H') register. Modify your program to output the two least significant bits to bits 4 and 5 of PORTC.

