Course Number
ELN - 232
Course Title
Introduction to Microprocessors
REPORT TITLE Digital Thermometer
Section
5
NUMBER Final Project
Semester Spring Year 2014 Date Performed
May 1
Instructor
Dennis Leak
Student Name
Ramon Martinez
Grade________
Date Submitted
May 7
Lab Instructor Dennis Leak
English and Spelling:____/25
Format:____/25
Content:____/50
Number of Misspelled words________
May7, 2014 ELN232-05 Ramon Martinez Lab Report Final Digital Thermometer
1.- Purpose To design and build a digital thermometer that would measure temperature and display results in fahrenheit and celsius degrees, with adjustable threshold temperature. 2.- Parts List: Parts
Designator
Quantity
Value
Microcontroller
U1
1
PIC16F87A
Voltage Regulator
U2
1
LM7805Z - 5V
LED Display
U3
1
4 digit 7 segment
Temperature Sensor
U4
1
LM335Z
Voltage Reference
U5
1
LM4040AIZ
Resistor
R1
1
330Ω
Resistor
R2,R6,R7,R8,R9,R11
6
2.2kΩ
Resistor
R3
1
4.7kΩ
Resistor
R4
1
3.9kΩ
Resistor
R5
1
2x8 DIP 330Ω
Resistor
R10
1
910Ω
Resistor
R12,R13
2
1kΩ
Transistor
Q1,Q2,Q3,Q4
4
2N3906
Capacitor
C1
1
0.1µF
Capacitor
C2
1
Tantalum 4.7µF
Capacitor
C3,C5
2
0.01µF
Capacitor
C4
1
33pF
Capacitor
C6
1
4.7µF
Capacitor
C7
1
47µF
Push Button
PB1
1
Tact Switch
Slide Switch
S1
1
SPDT
DC Plug
J1
1
Jack, DC Power
LED
LED1
1
Green LED
Table 1: Parts List
3.- Equipment List Equipment
Manufacturer
Model
Description
Hp 34401A Multimeter
Hewlett Packard
34401A
Digital Multimeter (DMM)
Breadboard
Jameco
WBU-208-R
7.3 x 7.5 3220 PNTS Breadboard
Programmer
Microchip
PickIt2
Programmer and Debugger
Oscilloscope
Sun Equipment Corp.
OS-221005
100 Mhz Oscilloscope
Table 2: Equipment List
4.- The Project A digital thermometer is a good project for this introductory course because it provides an opportunity to learn using sensors to measure analogic signals and how to make them interact to the microcontroller so it can produce an output understandable by humans. The project is based on a PIC16F876A microcontroller, a LM335Z temperature sensor and a LM4040AIZ voltage reference. The LM335Z is an analog sensor that converts the detected temperature to a proportional analog voltage, it produces an electrical output proportional to the temperature in Celsius. The output from the sensor is connected to one of the ADC channel inputs of the PIC16F876A microcontroller to obtain the equivalent temperature value in digital format, and then show it on the 4 digit 7 segment LED display. Since the experiment required the results to be in the Fahrenhet scale also, an artihmetic calculation has to be performed by means of addition and substraction to obtain such results. The switching function between Celsius values and Fahrenheit values is provided by a slide switch. A look-up table which reads the adc results and returns a set of display values used in this experiment. The down side of this approach is that it takes a lot of room.
Flow Chart
START
THERMOMETER
RETURN
FLOWCHART
SET ALL PORTS SET ADCON
DELAY
INITIALIZE
ADCON0
CONVERT TO PD
MAIN
ANALOG CONVERSION
ADC RESULTS
INCREMENT OR DECREMENT
CALCULATION RESULTS
CONVERT ADC
CELSIUS OR FAHRENHEIT CALCULATION
INITIAL VARIABLE
CELSIUS OR FAHRENHEIT THRESHOLD
THRESHOLD RESULTS
ADC CONVERSION
RETURN
SAVE RESULTS
DELAY
RETURN
SAVE RESULTS
RETURN
Block Diagram
THERMOMETER BLOCK DIAGRAM
THE DIAGRAM SHOWS THE MAJOR COMPONENTS OF A THERMOMETER CONTROLLED BY A PIC16F876A MICROPROCESSOR.
PIC 16F876A MICROCONTROLLLER
LED TO SHOW WHEN THRESHOLD HAS BEEN REACHED
TWO POSITION SWITCH TO CHANGE FROM FAHRENHEIT TO CELSIUS
7 SEGMENT 4 DIGIT DISPLAY TO SHOW TEMPERATURE READINGS
IT INCLUDES THE +5V VOLTAGE SOURCE, PUSH BUTTONS FOR THRESHOLD ADJUSTMENT, RC OSCILLATOR NETWORK, TEMPERATURE SENSOR, VOLTAGE REFERENCE, SWITCH TO GO FROM FAHRENHEIT TO CELSIUS DEGREES, SEVEN SEGMENT 4 DIGITS DISPLAY (ONLY THREE ARE USED) TO DISPLAY RESULTS AND AN LED TO SHOW WHEN THRESHOLD TEMPERATURE HAS BEEN REACHED.
+5V VOLTAGE FROM ICSP TO DRIVE THE MICROCONTROLLER PUSH BUTTONS TO ADJUST TEMPERATURE THRESHOLD
RC OSCILLATOR
LM335Z TEMPERATURE SENSOR
LM4040AIZ VOLTAGE REFERENCE IC
Parts List
Thermometer parts list with cost Quantity
Description
Provider
Cost per unit
Total
1
Microchip PIC16F876A
Jameco Electronics
$4.49
$4.49
1
DIL 330 x 8 Resistor Array
ABRA Electronics Canada
$1.80
$1.80
1
4DIGIT 7Segment Green CA 12-Pin PDIP
Jameco Electronics
$1.75
$1.75
4
2N3906 BJT Transistor
Jameco Electronics
$0.06
$0.24
6
Resistor Carbon Film 2.2k Ohm 1/4 Watt 5%
Jameco Electronics
$0.09
$0.54
1
Resistor Carbon Film 330 Ohm 1/4 Watt 5%
Jameco Electronics
$0.09
$0.09
1
Resistor Carbon Film 4.7k Ohm 1/4 Watt 5%
Jameco Electronics
$0.09
$0.09
1
Resistor Carbon Film 3.9k Ohm 1/4 Watt 5%
Jameco Electronics
$0.09
$0.09
2
Resistor Carbon Film 1k Ohm 1/4 Watt 5%
Jameco Electronics
$0.09
$0.18
1
Resistor Carbon Film 910 Ohm 1/4 Watt 5%
Jameco Electronics
$0.09
$0.09
1
Switch Slide Min Single Pole Double Throw On-On PCB Mount Jameco Electronics
$0.39
$0.39
2
.01 uF 50 Volt Ceramic Disc Capacitor
Jameco Electronics
$0.09
$0.18
1
0.1 uF 50 Volt Ceramic Disc Capacitor
Jameco Electronics
$0.09
$0.09
1
33 pF 50 Volt Ceramic Disc Capacitor
Jameco Electronics
$0.09
$0.09
1
4.7uF 35 VOLT TANTALUM CAPACITOR
Jameco Electronics
$0.49
$0.49
1
47 uF 50 Volt Radial Capacitor
Jameco Electronics
$0.09
$0.09
1
4.7 uF 50 Volt Radial Capacitor
Jameco Electronics
$0.10
$0.10
1
IM206 6x6x6mm Tact Switch
Microtivity
$0.50
$0.50
1
LM35Z Temperature Sensor Analog Serial3 Pin TO-92 Box
Jameco Electronics
$0.49
$0.49
1
LM4040 Voltage Reference Precision 5 Volt 15 mA 3-Pin TO-92 Jameco Electronics
$1.35
$1.35
1
LED Uni-Color Green 565nm 2-Pin
Jameco Electronics
$0.15
$0.15
1
LM7805CT Standard Regulator 5 Volt 1 Amp 3 Pin
Jameco Electronics
$0.45
$0.45
1
JACK,DC POWER,MALE
Jameco Electronics
$0.45
$0.45
Total
$14.18
1
PICkit 2 Starter Kit Microcontroller Programmer and Debugger
Jameco Electronics
$79.95
$79.95
1
3220-Point Solderless Breadboard 7.3"Lx7.5"W
Jameco Electronics
$36.95
$36.95
Total Including opional items
Jameco Electronics 1355 Shoreway Road Belmont, CA 94002 Phone: 1-800-831-4242 Fax: 1-800-237-6948 Email: Sales@Jameco.com
!!
ABRA Electronics Canada 1-800-361-5237 www.abra-electronics.com
!!
Amazon.com 1200 12th Ave. S., Suite 1200 Seattle, WA 98144
$131.08
5.- Conclusion The Digital thermometer was built using a 3220 Points solderless breadboard. After placing the PIC16F876A on it, it was connected to a push button through a 2,2k resistor on pin 1 and through a 0.1µF capacitor to ground, to set the Rest circuit. After this was done, the LM335Z temperature sensor which was connected to AN0 (pin2) trhough a 1kΩ resistor. To this same terminal, the +5V signal was connected through a 2.2kΩ resistor, finallly the third terminal was grounded. Third step required connecting the voltage reference LM4040AIZ to the pic using AN3 (pin5), through a 910Ω and a 1kΩ in parallel wich in turn connected to Vdd (pin20) and pin #2 of the ICSP.
The 6 pins of the programmer were connected as follows: Pin1 to MCLR of the Pic (pin1). Pin2 to a green LED through a 330Ω resistor; throuygh a 4.7kΩ resistor to the reset circuit 9pin1 on the Pic); finally to Vss2 (pin20 on the pic) through a 0.1µF ceramic capacitor. Pin3 was grounded. Pin4 to RB7 (pin 28 on the Pic) Pin5 to RB5 9pin27 on the Pic) Pin6 was not connected.
Since he ADC circuit reading can be affected due to the fact that all the system is pulling off the same +5V source, capacitors are placed by each analog input to smooth out dips and surges in the current caused by the other components. The PIC 16F876A Microcontroller offers 10 Bit Analog to Digital Conversion. When it measures an incoming voltage, it compares that voltage to a reference voltage, and produces the comparison as a 10-bit number. This result is then translated into a Celsius degree value to be displayed on the LED display.
A slide switch was installed to RB5 (pin26) to provide the function of switching from Fahrenheit to Celsius degrees and viceversa. A 4.7µF Tantallum capacitor was connected through AN3 (pin5) and ground. The RC network, which provides the clock for the Microcontroller was composed of a 3.9kΩ resistor in series with a 33pF capacitor connected to CLK1 (pin9). To provide stable external power to the circuit after it is unplugged from the programmer, a LM7805 voltage regulator was connected to Vdd using two capacitors, a 47µF to line voltage and a 4.7µF to the terminal that connects to the circuit, a Jack DC plug was used to drive the power from the external source, a 12VDC transformer. Finally a 4 digit 7 segment LED display was placed in the circuit through a 330Ω resistor array, and 4 2N3906 transistors were used to light up the LEDS. This transistors were connected to the PIC through 4 2.2kΩ resistors and all the emitter legs to a 0.01µF capacitor. All the circuit is shown as it was built on the schematics included in this report.
Main Code
;*********************************************************************** ; File Name: Main.asm ; Description: A Main program that calls other device drivers. ; ; ; Written by: RAMON MARTINEZ ; Build with: MPASM ; Processor: PIC16F876A ; Change history: ; 0.1 2011/10/02 DDL Initial version ; ;*********************************************************************** ; Pins Used: ; Oscillator is R-C network = 3.9k and 33pf => ~ 4MHz ; Port A: Being Used. ; Port B: Select bits 0-3 for the 4 digits, 0 being the right most digit ; Port C: 7-0 set as output ; Port D: Not defined for this PIC ; Port E: Not defined for this PIC ; ; *************************************************************************** #include <p16F876a.inc> #include <PIC16Macros.asm> __CONFIG _LVP_OFF & _CPD_OFF & _CP_OFF & _PWRTE_ON & _WDT_OFF & _WRT_OFF & _RC_OSC ; Declarations: cblock 0x20 W_temp STATUS_temp Digit:4 DelayCnt DelayMs KeyHold ScanCount Flags: endc
local Temperature
;============= ; Program Start: org 0 goto Start org 4 goto ISR
; Place for W reg in the Interrupt Service Rout. (ISR) ; Place to hold the Status in the ISR ; define a variable to hold the 0-4 char of LED display ; define a variable to hold DelayCnt ; define a variable to hold DelayMs ; Temporary holding place for a key ; Place for counting the scans
; Declare that temperature is in AnalogDriver.asm
; Declare to the Assembler that this code starts at 0 ; Jump to the Start routine ; Declare to the Assembler that this code starts at 4 ; Jump to the ISR code
Start: Main: Loop:
call
Initialize
decf ScanCount,F btfss STATUS,Z goto NoADC movlw .100 movwf ScanCount movlw 0 call Temperature1 call Thermo
NoADC: call LED_Scan movlw .4 call Delay goto Loop nop nop goto $+0
; See if we have exhaused the scan count ; Jump over the A/D conversion ; Set back up the scan count ; Only do ADC every .5 second (scan is 5ms) ; Set w to 0 for channel 0
; Scan the LED display ; Delay to allow LED Display Scan to be viewed
; Loop here forever
;SegmentLookUp uses a table lookup approach. Call this routine with ; binary data in the W reg where it will be translated to the scan code. This routine must be in the first ;100 bytes of the first program page. Input: W reg contains Digit 0-15, to be translated. ; Output: Translated data in W reg SegmentLookUp: clrf PCLATH addwf PCL,F retlw 0x3f retlw 0x06 retlw 0x5B retlw 0x4F retlw 0x66 retlw 0x6D retlw 0x7D retlw 0x07 retlw 0x7F retlw 0x6F retlw 0x77 retlw 0x7C retlw 0xB9 retlw 0x5E retlw 0x79 retlw 0xF1
;decode 0 ;decode 1 ;decode 2 ;decode 3 ;decode 4 ;decode 5 ;decode 6 ;decode 7 ;decode 8 ;decode 9 ;decode A ;decode B ;decode C ;decode D ;decode E ;decode F
#include <PicLEDDsplyDriver.asm> #include <AnalogDriver.asm> ;#include <PicToneDriver.asm> ;============= ; Subroutines: ; Initialize Function. This initialize routine will set up all the ports, ; timer, analog and comparator functions. ; Inputs: none ; Outputs: none Initialize: ; Initialize port data registers ; Binary used to see individual pin level bcf STATUS,RP1 ; set to RAM page 0 bcf STATUS,RP0 ; set to RAM page 0 movlw b’00000000’ ; all port pins = low movwf PORTA movlw b’11111111’ ; Set to select digit0 (active = 0) movwf PORTB movlw b’11111111’ ; Set all segments to high (off ) movwf PORTC movlw b’11111111’ ; Fosc/8; channel 0; ADC on movwf ADCON0 ; bsf STATUS,RP0 ; set RAM Page 1 for TRIS registers movlw b’10000101’ ; RA5,4,2=digital; AN3=+Vref; AN1,AN0=analog movwf ADCON1 ; Set bit 7=Right Justify A/D out. movlw b’11011111’ ; RA5=output;RA4,2=inputs movwf TRISA movlw b’11110000’ movwf TRISB movlw b’00000000’ ; except port C we want as all outputs movwf TRISC bcf STATUS,RP0 ; back to RAM page 0 clrf Digit clrf Digit+1 clrf Digit+2 clrf Digit+3 clrf CelsiusPD clrf CelsiusPD+1 return
; ISR Function. This Interrupt Service Routine (ISR) will do all the things ; necessary to service the interrupt. ; INPUTS: none ; OUTPUTS: none
ISR: movwf movf movwf movf movwf swapf swapf retfie
W_temp STATUS,w STATUS_temp STATUS_temp,w STATUS W_temp,f W_temp,w
; Stores W reg in temp register ; Stores STATUS in temp ; register ; Restore STATUS register to the ; original value ; Restores W reg to original value, ; does not affect the STATUS!
; Delay Function. Enter with number of 1mSec delays in Wreg ; INPUTS: Wreg contains number of 1 millisecond delays ; OUTPUTS: none Delay: movwf DelayMs ; this timing relies on the speed of the processor movlw .71 ; delay ~1000uS movwf DelayCnt decfsz DelayCnt,f ; this loop does 215 cycles goto $-1 decfsz DelayCnt,f ; This loop does 786 cycles goto $-1 decfsz DelayMs,f ; Delay the outerloop the number of milliseconds goto $-7 return ; This is the end of all the program code end
Analog Driver Code
;**************************************************************************** ; File Name: AnalogDriver.asm ; Title: “Digitize the Analog” ; ; Function: This assembly code will provide the Analog code ; to convert the analog voltage, appearing on the ; analog pins, to a digital value. ; ; Developed using MPLAB version 8.60. ; Targeted device: PIC16F876A ; ; ***************************************************************************
; Declare the data areas used. cblock ADCResult:2 CelsiusPD:2 CelBin:2 Far:2 FarPD:2 WregTest ThreshPD:2 endc
Temperature1: movlw 0 call AnalogConv ; Convert the A/D call TestADCResult ; Put the A/D output to the LED display. call FindCelsius ; Convert Value to celsius btfsc PORTA,2 ; Is S1 closed? Skip next instruction goto DisplayCelsius ; call Celtofar call UnpackFar ; Put value to LED buffer goto Tempfinal DisplayCelsius: call UnpackCel
; Put value to LED buffer
; ADC_Delay_us macro definition ; Input: w reg contains the # of microseconds to delay ADC_Delay_us macro addlw 0xFF btfss STATUS,Z goto $-2 endm
; Start decrementing W reg ; See if W has been decremented to zero, skip if it is ; Jump back until it is zero
; AnalogConv a subroutine that will convert the voltage on ; the analog input channel contained in W reg ; Input: w reg has analog channel to convert ; Output: ADRESH has 2 MSB and ADRESL has lower 8 bits of 10 bit AnalogConv: movwf WregTest btfsc WregTest,0 bsf ADCON0,3 btfsc WregTest,1 bsf ADCON0,4 btfsc WregTest,2 bsf ADCON0,5 movlw .20 ADC_Delay_us bsf ADCON0,2 movlw .30 ADC_Delay_us bsf STATUS,RP0 movf ADRESL,w bcf STATUS,RP0 movwf ADCResult movf ADRESH,w movwf ADCResult+1 bcf ADCON0,3 bcf ADCON0,4 bcf ADCON0,5 return
; Move analog channel to W reg Test ; Check each bit and set accordingly ; Check each bit and set accordingly ; Check each bit and set accordingly ; Move into W reg 20 for delay ; Delay the Microseconds in W reg ; Start a conversion ; Set up the ADC time delay ( 12 Tad cycles) ; Delay the Microseconds in W reg ; Move low byte to W reg ; Now move it to the analog Low location ; Move Higher byte to W reg ; Now move it to the analog High location ; Reset to channel 0
; FindCelsius a subroutine that will convert the A/D result ; to Celsius decimal digits. Since the result is ; 1 degree Kelvin per 2.5 bits, it is very hard to ; divide by 2.5, so we will multiply the result by ; 2 and divide by 5. After we do this lets convert ; it to celsius before we divide, so we have to subract ; by 273*5 =0x555. Then divide by repeated subtraction. ; Input: ADCResult has value to convert to Celsius ; Output: Digit0-3 has decimal celsius value (0 is LSD) FindCelsius: bcf STATUS,C rlf ADCResult,F rlf ADCResult+1,F subl16 ADCResult, 0x555 load16 CelsiusPD,0x9999
; Clear the carry first ; Rotate does a multiply by 2. ; Now put the carry through to the higher byte ; Subtract 273*5 =0x555 ; Start with value -1 (when incremented =0)
load16 CelBin,-1
FindCelsius2: subl16 ADCResult, 5 IncDec16 CelsiusPD inc16 CelBin btfss ADCResult+1,7 goto FindCelsius2 addl16 ADCResult,5 return Celtofar: mov16 CelBin,Far bcf STATUS,C rlf Far,f rlf Far+1,f rlf Far,f rlf Far+1,f rlf Far,f rlf Far+1,f add16 CelBin,Far addl16 Far,0xA0 load16 FarPD,0x9999 Celsius2Farh2: subl16 Far, 5 IncDec16 FarPD btfss Far+1,7 goto Celsius2Farh2 return
; Divide by 5 doing repeated subtraction ; Increment the celsius result ; Check to see if we went negative ; Add back in so it has remainder
; Start with value -1 (when incremented =0)
; Divide by 5 doing repeated subtraction ; Increment the celsius result ; Check to see if we went negative
; Unpack subroutine that uses the packed decimal and puts it into individual decimal digits. ; Input: CelsiusPD packed decimal digits ; Output: Digit0-3 has decimal celsius value (0 is LSD) UnpackCel: movf CelsiusPD,w andlw 0x0F movwf Digit+1 swapf CelsiusPD,w andlw 0x0F movwf Digit+2 movf CelsiusPD+1,w andlw 0x0F movwf Digit+3 swapf CelsiusPD+1,w andlw 0x0F movlw 0x0C
; Get the Low data ; Only look at low nibble ; Get high nibble ; Get rid of high nibble ; Get the Low data ; Only look at low nibble ; Get high nibble ; Get rid of high nibble
movwf Digit+0 return ; Unpack2LCD subroutine that uses the packed decimal and puts it into LCD Buffer. ; Input: CelsiusPD packed decimal digits ; Output: LCD Buffer with decimal celsius value (0 is LSD) UnpackFar: movf FarPD,w andlw 0x0F movwf Digit+1 swapf FarPD,w andlw 0x0F movwf Digit+2 movf FarPD+1,w andlw 0x0F movwf Digit+3 swapf FarPD+1,w andlw 0x0F movlw 0x0F movwf Digit+0 return
; Get the Low data ; Only look at low nibble ; Get high nibble ; Get rid of high nibble ; Get the Low data ; Only look at low nibble ; Get high nibble ; Get rid of high nibble
; Unpack2LCD subroutine that uses the packed decimal and puts it into LED Buffer. ; Input: CelsiusPD packed decimal digits ; Output: LCD Buffer with decimal celsius value (0 is LSD) UnpackThresh: movf ThreshPD,w ; Get the Low data andlw 0x0F ; Only look at low nibble movwf Digit+1 swapf ThreshPD,w ; Get high nibble andlw 0x0F ; Get rid of high nibble movwf Digit+2 movf ThreshPD+1,w ; Get the Low data andlw 0x0F ; Only look at low nibble movwf Digit+3 swapf ThreshPD+1,w ; Get high nibble andlw 0x0F ; Get rid of high nibble movlw 0x0C movwf Digit+0 return
; TestADCResult subroutine that uses the ADC Result and puts it on the LED display. ; Input: CelsiusPD packed decimal digits ; Output: Digit0-3 has decimal celsius value (0 is LSD) TestADCResult: movf ADCResult,w andlw 0x0F movwf Digit+1 swapf ADCResult,w andlw 0x0F movwf Digit+2 movf ADCResult+1,w andlw 0x0F movwf Digit+3 swapf ADCResult+1,w andlw 0x0F movwf Digit+4 movlw 0x0C movwf Digit+0 return CheckThresh: btfsc return
PORTA,2
Thermo: btfsc PORTB,5 goto Temp2 bsf PORTA,5 btfsc Flags,0 goto Temp4 bsf Flags,0 IncDec ThreshPD goto Temp4 Temp2: bcf Flags,0 bcf PORTA,5
; Get the Low data ; Only look at low nibble ; Get high nibble ; Get rid of high nibble ; Get the Low data ; Only look at low nibble ; Get high nibble ; Get rid of high nibble
; Check the threshold by pressing on switch 3
; This is just to test the push button 4 (count up) port with LED
; This is just to test the push button 4 (count up) PORTB5 with LED
Temp4: btfsc PORTB,4 goto Temp3 bsf PORTA,5 btfsc Flags,1 goto Tempfinal bsf Flags,1
; This is just to test push button 5 (count up) PORTB4 with LED
Temp3: bcf Flags,1 bcf PORTA,5 DecDec ThreshPD goto Tempfinal
; This is just to test push button 5 (count up) PORTB4 with LED
Tempfinal: return
LED Display Driver Code
;**************************************************************************** ; File Name: PicLEDDsplyDriver.asm ; Title: “PIC LED display Driving” ; ; Function: This assembly code will display data on a four 7 segment LED display driven on Port C, with digit selects on Port B 0-3 bits. ; The data will be in the RAM area Digit0 to Digit3. It must ; be a value 0 to 9 to be displayed. ; ; Developed using MPLAB version 8.60. ; Targeted device: PIC16F876A ; ; Pins Used: ; Oscillator is R-C network = 3.9k and 33pf => ~ 4MHz ; Port A: Not Used. ; Port B: Select bits 0-3 for the 4 digits, 0 being the right most digit. ; Port C: 7-0 set as output, with 7 seg disp 6=g,5=f,4=e,3=d,2=c,1=b,0=a. ; Port D: Not defined for this PIC ; Port E: Not defined for this PIC ; ; *************************************************************************** ; LED_Scan Routine. Shows the digits held in Display0-3 ; INPUTS: Digit 0-3 filled with the information to display ; OUTPUTS: none LED_Scan: btfss PORTB,0 ; Check to see if digit 0 is selected (bit =0) goto Display0 ; Jump because digit 0 is selected btfss PORTB,1 ; Check to see if digit 1 is selected (bit =0) goto Display1 ; Jump because digit 1 is selected btfss PORTB,2 ; Check to see if digit 2 is selected (bit =0) goto Display2 ; Jump because digit 2 is selected btfss PORTB,3 ; Check to see if digit 3 is selected (bit =0) goto Display3 ; Jump because digit 3 is selected movlw b’00001110’ ; Set to select digit0 (active=0) movwf PORTB ; Put it out to the Digit select goto DisplayEnd Display0: bsf PORTB,0 ; Set to deselect digit0 bcf PORTB,1 ; Clear the bit to select digit1 movf Digit+1,0 ; Move in digit 1 to W, we just selected it call DispSeg ; Go put out that segment value goto DisplayEnd Display1: bsf PORTB,1 ; Set to deselect digit1 bcf PORTB,2 ; Clear the bit to select digit2 movf Digit+2,0 ; Move in digit 2 to W, we just selected it call DispSeg ; Go put out that segment value goto DisplayEnd
Display2: bsf PORTB,2 bcf PORTB,3 movf Digit+3,0 call DispSeg goto DisplayEnd Display3: bsf PORTB,3 bcf PORTB,0 movf Digit,0 call DispSeg goto DisplayEnd DisplayEnd: return
; Set to deselect digit2 ; Clear the bit to select digit3 ; Move in digit 3 to W, we just selected it ; Go put out that segment value
; Set to deselect digit3 ; Clear the bit to select digit0 ; Move in digit 0 to W, we just selected it ; Go put out that segment value
; DispSeg Routine. Translates the digit to segments and puts it out. ; INPUTS: Digit to display in W reg. ; OUTPUTS: none DispSeg: call SegmentLookUp ; Translate the digit to the segment value xorlw 0xFF ; Invert the W reg, because the port is - active movwf PORTC ; Set Segment data W into port C ;xorlw 0xFF ; This is to activate the PORT A if we need to light on the red light ;movwf PORTC return
; IncDigits Routine. Increments the Digits in decimal format, one per byte. ; INPUTS: Decimal digit in Digit 0-3. ; OUTPUTS: The decimal digits incremented by 1. IncDigits: incf Digit,1 ; Increment the display count. movfw Digit ; Get that digit to see if it exceeded 9 xorlw 0x0A ; see if the digit is a 0x0A which is above 9 btfss STATUS,Z ; If they were equal W would be 0, (Z=1), so skip next if Z=1 goto IncDigitEnd ; Jump because digit 0A was not found clrf Digit incf Digit+1,1 ; Increment the display count. movfw Digit+1 ; Get that digit to see if it exceeded 9 xorlw 0x0A ; see if the digit is a 0x0A which is above 9 btfss STATUS,Z ; If they were equal W would be 0, (Z=1), so skip next if Z=1 goto IncDigitEnd ; Jump because digit 0A was not found clrf Digit+1 incf Digit+2,1 ; Increment the display count. movfw Digit+2 ; Get that digit to see if it exceeded 9 xorlw 0x0A ; see if the digit is a 0x0A which is above 9 btfss STATUS,Z ; If they were equal W would be 0, (Z=1), so skip next if Z=1
goto IncDigitEnd clrf Digit+2 incf Digit+3,1 movfw Digit+3 xorlw 0x0A btfss STATUS,Z goto IncDigitEnd clrf Digit clrf Digit+1 clrf Digit+2 clrf Digit+3 IncDigitEnd: return
; Jump because digit 0A was not found ; Increment the display count. ; Get that digit to see if it exceeded 9 ; see if the digit is a 0x0A which is above 9 ; If they were equal W would be 0, (Z=1), so skip next if Z=1 ; Jump because digit 0A was not found
Macros Code
;**************************************************************************** ; File Name: PIC16Macros.asm ; Title: “Supplies general purpose 16 bit macros” ; ; Function: This assembly code will provide 16 bit macros for general usage. ; ; Developed using MPLAB version 8.60. ; Targeted device: PIC16F876A but useful for all PICs ; ; *************************************************************************** ; All these macros use the “Little Endian” style of data storage organization. ; The Least Significant Byte is stored first ( like 0x20) and Most Significant ; byte is stored in the next higher address ( 0x21 ). ; add16 macro does a unsigned 16 bit addition with carry out. The Source is preserved; Destination is replaced, with Carry set appropriately. (assume high byte is +1 in the General Purpose data area) ; Input: Destination and Source ; Output: Destination add16 macro Destination,Source movf Source,w ; Get low byte addwf Destination,f ; Add to the Destination movf Source+1,w ; Get high byte btfsc STATUS,C ; See if carry incf Source+1,w ; Add if carry addwf Destination+1,f ; Add high byte into Destination endm
; load16 macro loads up a 16 bit value into a variable ; Input: Immediate literal value ; Output: Variable loaded with data load16 macro Variable, Literal movlw low (Literal) ; Get the low byte of the immediate value (Literal)mod256. movwf Variable ; Put it in the desired variable movlw high (Literal) ; Now use the upper 8 bits (Literal)/256 movwf Variable+1 ; Move it into the upper 8 bits. endm
; addl16 macro will add a 16 bit variable to a literal or immediate value ; Input: Literal or immediate value, and Destination ; Output: Result is in Destination, carry set appropriately addl16 macro Destination, Literal movlw low(Literal) ; Get the low 8 bits of the Literal addwf Destination,f ; Add it to the low of the Dest. movlw high(Literal) ; Now get the upper 8 bits of the Lit. btfsc STATUS,C ; Jump over the movlw if C=1 movlw (high(Literal))+1 ; If no carry, get the upper 8 plus 1 addwf (Destination)+1,f ; Finish off by adding it to the high 8 endm
; sub16 macro will accomplish a 16 bit unsigned subtraction with carry out. ; The Source is subtracted from the Destination and carry (-borrow) ; is set appropriately. ; Input: Source and Destination variables ; Output: Destination has the result and the carry (-borrow) is set appropriately sub16 macro Destination, Source movf Source,w ; Get low byte of what is being subtracted subwf Destination,f ; Subtract low byte of the Source from low byte Dest. movf Source+1,w ; Now get high byte of subtrahend btfss STATUS,C ; If there was a borrow, we inc ( if -B is inactive skip inc) incf Source+1,w ; the Source high byte instead of decrementing the Dest. subwf Destination+1,f ; Subtract the high byte of Destination - Source endm ; subl16 macro will accomplish a 16 bit unsigned subtraction with Literal value, with carry out. The Literal is subtracted from the Destination and carry (-borrow) is set appropriately. ; Input: Source and Destination variables ; Output: Destination has the result and the carry (-borrow) is set appropriately subl16 macro Destination, Literal movlw low (Literal) ; Get low byte of what is being subtracted subwf Destination, f ; Subtract the low Literal from low byte Destination movlw high (Literal) ; Get the high byte of Literal btfss STATUS,C ; If -Borrow is active low, s movlw (high (Literal))+1 ; Replace it, if borrow active, with an incremented Literal subwf Destination+1,f ; Now subtract endm
; mov16 macro moves 16 bits of information from the Source to the Destination ; Input: Source with 16 bits of information ; Output: Destination with the SourceĂs information mov16 macro Source, Destination movf Source,w ; Get the source low movwf Destination ; Put it into the destination low movf Source+1,w ; Do the same for the source high movwf Destination+1 ; And destination high endm ; inc16 macro will increment a 16 bit value, and sets Z appropriately. ; Input: Destination which will have 1 added to it. ; Output: Destination inc16 macro Destination incfsz Destination,w ; Increment the low byte decf Destination+1,f ; No carry (negates next step) incf Destination+1,f ; Add one to high byte movwf Destination ; Store updated low byte back. iorwf Destination+1,w ; Set the z flag appropriately endm
; twoscom16 macro will do a 2Ăs compliment of a 16 bit value ; Input: Destination value to find the 2Ăs compliment of ; Output: Destination twoscom16 macro Destination comf Destination ; First compliment the 16 bit value comf Destination+1 inc16 Destination ; Then add 1 using the increment 16 bit macro. endm
; There must be a 16 bit register defined that is used by the 16 BIT operations cblock 0x7e _Xreg endc ; cmp16 macro compares two 16 bit unsigned values A and B, returns Z and C set appropriately ; Input: A and B values ; Output: Flags set where if Z=1 then A & B are equal, if C=1 then A>B, and if C=0 then A<B. cmp16 macro A, B mov16 A, _Xreg ; Use the 16 bit move macro sub16 _Xreg,B ; Now subtract using the 16 bit macro movf _Xreg,w ; Set the Z flag bit iorwf _Xreg+1,w ; The OR only changes the Z flag bit. endm ; IncDec macro to increment a variable in packed decimal ; Input: Packed Decimal number address. ; Output: Packed Decimal number incremented, C set if overflow IncDec macro PD incf PD,f ; Increment the packed decimal normal movf PD,w ; Move byte into W andlw 0x0F ; Only look at lower 4 bits. sublw 0x0A ; Sub w from literal: 0A - W bcf STATUS,C ; Clear the Carry Flag btfss STATUS,Z ; if equal skip next opcode goto $+.10 ; Low decimal digit OK, so jump. movlw 0x06 ; Set up W to add 06 to PackDec addwf PD,f ; Add the 06 to correct movf PD,w ; Get the PackDec again sublw 0xA0 ; See if upper digit has overflowed. bcf STATUS,C ; Clear the Carry btfss STATUS,Z ; if equal skip next opcode goto $+3 ; Jump if not exceeded digit. movlw 0x60 ; Correct upper digit addwf PD,f ; Add it in to PackDec endm
DecDec macro PD decf PD,f movf PD,w andlw 0x0F sublw 0x0F bcf STATUS,C btfss STATUS,Z goto $+.10 movlw 0x0F subwf PD,f movf PD,w sublw 0x06 bcf STATUS,C btfss STATUS,Z goto $+3 movlw 0x0F subwf PD,f endm
; Decrement the packed decimal normal ; Move byte into W ; Only look at lower 4 bits. ; Sub w from literal: 0A - W ; Clear the Carry Flag ; if equal skip next opcode ; Low decimal digit OK, so jump. ; Set up W to subtract 0F to PackDec ; Subtract the 06 to correct ; Get the PackDec again ; See if upper digit has overflowed ; Clear the Carry ; if equal skip next opcode ; Jump if not exceeded digit. ; Correct upper digit ; Subtract it in to PackDec
; IncDec16 macro to increment a 16bit variable in packed decimal ; Input: Packed Decimal number address. ; Output: Packed Decimal number incremented, C set if overflow IncDec16 macro PD IncDec PD ; Call the macro btfss STATUS,C ; Skip if carry, jump if not goto $+2 IncDec PD+1 ; Call the macro endm
Digital Thermometer Schematics