PIC microcontroller for digital temperature sensor

Status
Not open for further replies.

muralijoy

New Member
I have found this code for the PIC microcontroller for digital temperature sensor, could you please help me? How do I compile this code and which software I can use it? Which programmer do you suggest me to upload this code to microcontroller. I am an engineering student I just started to study about assembly language. please advice me.

Thanks

LIST P=PIC16F628A
INCLUDE P16F628A.INC
__config _CP_OFF & DATA_CP_OFF & _LVP_OFF & _BODEN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
errorlevel -302 ;Eliminate bank warning


CBLOCK H'20'
HUNS ; Jump pointer for Hundreds digit
TENS ; Jump pointer for Tens digit
ONES ; Jump pointer for Ones digit
DECI ; Jump pointer for Decimal digit
THOU_COL ; 7 Segment Display Thousands Column, used within ISR
HUNS_COL ; 7 Segment Display Hundreds Column, used within ISR
TENS_COL ; 7 Segment Display Tens Column, used within ISR
ONES_COL ; 7 Segment Display Ones Column, used within ISR
COLSEL ; Stores COLUMN SELECT information
DIGIT ; Used for Indirect Addressing in Interrupt Service Routine
TEMPLO_C ; BS18B20 Celsius Temperature Result Low Byte
TEMPHI_C ; BS18B20 Celsius Temperature Result High Byte
COUNT ; For counting execution times in various routines
SHIFT ; For storing data to shift into and out of the DS18B20
DELAYGPR1 ; Used in delay subroutines
FLAGS ; -------X Unused

ENDC

W_ISR EQU H'70'
S_ISR EQU H'71'
P_ISR EQU H'72'
F_ISR EQU H'73'


ORG H'000' ; Processor reset vector location. On power up, the program jumps here
GOTO SETUP ;

ORG H'004' ; Interrupt vector location. When an Interupt occurs, the program jumps here
; (Thanks Mike, K8LH for help with this ISR routine. Contact via Electro-Tech-Online.com)
; Save
MOVWF W_ISR ; Save W to W_ISR
SWAPF STATUS, W ; Use SWAPF instruction so status bits don't change
MOVWF S_ISR ; Save Status to S_ISR
CLRF STATUS ; Switch to Bank 0
MOVF PCLATH, W ; Move PCLATH to W register
MOVWF P_ISR ; Save PCLATH to P_ISR
CLRF PCLATH ; Force page 0
MOVF FSR, W ; Move FSR to W register
MOVWF F_ISR ; Save FSR to F_ISR

; Refresh display
CLRF PORTB ; Blank the display
MOVF PORTA, W ; Move PORTA's current state to W
ANDLW B'11100000' ; Clear ONLY Column Select Bits & leave upper nibble unchanged
IORWF COLSEL, W ; Inclusive OR above with COLSEL register
MOVWF PORTA ; Leave upper nibble of PORTA unchanged & select new column

MOVF DIGIT, W ; Column number (DIGIT is initialised to 0. Used for Indirect Addressing)
ADDLW THOU_COL ; Add 'DIGIT' to 'THOU_COL' GPR address
MOVWF FSR ; FSR = THOU_COL + (0forTHOUS, 1forHUNS, 2forTENS & 3forONES) as they are in sequencial order in RAM
MOVF INDF, W ; W register now holds the jump pointer for the corresponding digit to be displayed
CALL SEGMENT_TABLE ; Get 7 segment arrangement from SEGMENT_TABLE for corresponding digit

BTFSC COLSEL, 1 ; Is TENS Column active
IORLW B'00000001' ; Yes, so activate TEN's column deciaml point
MOVWF PORTB ; NO, hide deciaml point and display new column

; Prepare for next column interrupt
INCF DIGIT, F ; Increment DIGIT jump pointer (used when indirect addressing above)
BCF STATUS, C ; Clear C bit of STATUS register
RRF COLSEL, F ; Advance column select bit
BTFSS STATUS,C ; Was that the last column? (or, Is Carry Flag Set?)
GOTO $+D'3' ; NO, do not reset DIGIT and COLumnSELect
CLRF DIGIT ; Reset DIGIT jump pointer
BSF COLSEL, 3 ; Reset column select to THOU_COL (1XXX) (00001000)

; RESTORE
BCF PIR1, TMR2IF ; Clear TMR2 interrupt flag while still in Bank 0
MOVF F_ISR, W ; MOVE F_ISR to W
MOVWF FSR ; Restore FSR
MOVF P_ISR, W ; MOVE P_ISR to W
MOVWF PCLATH ; Restore PCLATH
SWAPF S_ISR, W ; Undo previous SWAPF, place result in W
MOVWF STATUS ; Restore STATUS
SWAPF W_ISR, F ; Use SWAPF instruction so status bits don't change
SWAPF W_ISR, W ; Undo previous SWAPF and restore W register
RETFIE ; Return From Interrupt

; 7 Segment Display Arrangement Lookup
SEGMENT_TABLE ; This routine assigns on/off arrangement to the 7 Segment Display
ADDWF PCL, F
; BAFGEDCp JUMP B|A|F|G|E|D|C|p DISPLAY
RETLW B'11101110' ; 0 B|A|F|-|E|D|C|- 0
RETLW B'10000010' ; 1 B|-|-|-|-|-|C|- 1
RETLW B'11011100' ; 2 B|A|-|G|E|D|-|- 2
RETLW B'11010110' ; 3 B|A|-|G|-|D|C|- 3
RETLW B'10110010' ; 4 B|-|F|G|-|-|C|- 4
RETLW B'01110110' ; 5 -|A|F|G|-|D|C|- 5
RETLW B'01111110' ; 6 -|A|F|G|E|D|C|- 6
RETLW B'11000010' ; 7 B|A|-|-|-|-|C|- 7
RETLW B'11111110' ; 8 B|A|F|G|E|D|C|- 8
RETLW B'11110110' ; 9 B|A|F|G|-|D|C|- 9
RETLW B'00000000' ; 10 -|-|-|-|-|-|-|- BLANK
RETLW B'00010000' ; 11 -|-|-|G|-|-|-|- -
RETURN

; Program Orgiginates Here
SETUP ; This rountine sets up the Microcontroller's Inputs and Outputs
MOVLW H'07' ; Turn Comparators off and enable pins for I/O functions
MOVWF CMCON ;
BSF STATUS, RP0 ; Bank 1
MOVLW B'01010000' ; RA<7><5><3:0> Output, RA<6><4> Input
MOVWF TRISA ;
CLRF TRISB ; RB<7:0> Outputs
BCF STATUS, RP0 ; Bank 0

CLRF PORTA
CLRF PORTB

ONE_OFF_INITIALISE
; Clear ALL Bank 0 RAM from 0X20 - 0X7F (96 bytes)
BCF STATUS, IRP ; Indirect addressing Bank 0/1
MOVLW H'20' ; Initialise pointer to RAM
MOVWF FSR ; (File Select Register)
CLRF INDF ; Clear Register indirectly
INCF FSR, F ; Increment pointer
BTFSS FSR, 7 ; All done?
GOTO $-D'3' ; No, Clear next byte

; Initialise Column Select
BSF COLSEL, 3 ; Set column select to THOU_COL (1XXX) (00001000)

; Setup TMR2 for 0.0005s or 500uS Interrupts
CLRF TMR2 ; Clear TMR2 register
BSF STATUS, RP0 ; Bank 1
MOVLW B'00000010' ; 00000010
MOVWF PIE1 ; -------0 Disable TMR1IE - TMR1 Overflow Interrupt Enable bit

BCF STATUS, RP0 ; Bank 0
CLRF PIR1 ; Clear Peripheral Interrupt Flags
MOVLW B'00000001' ; 00000001
MOVWF T2CON ; ------01 Prescale 1:4
; -----0-- TMR2 OFF
; -0000--- Postscale 1:1
; 0------- Unused
BSF STATUS, RP0 ; Bank 1
MOVLW D'250' ;
MOVWF PR2 ; Interrupt every 0.001s or 1mS
BCF STATUS, RP0 ; Bank 0
BSF INTCON, GIE ; Enable Global Interrupts
BSF INTCON, PEIE ; Enable Peripheral Interrupts
BSF T2CON, TMR2ON ; Start TMR2

GOTO GET_TEMP

; Dallas DS18B20 Temperature Sensor 'One Wire' Communication Routines
DS18B20_RESET ; This routine Resets the DS18B20
CALL DQ_LL ; Force the DQ Line to Logic Low
MOVLW (D'480'-5)/5 ; Reset pulse must be held a minimum of 480uS.
CALL DELAY ; For delays from 10uS to 1285uS. Example, MOVLW D'10' for 10uS, MOVLW D'500' for 500uS. (D'n'-5)/5; n must be divisable by 5
CALL DQ_HIZ ; Release DQ Line
MOVLW (D'60'-5)/5 ; Wait for recovery
CALL DELAY ;
BTFSC PORTA, 4 ; Test for 'Presence Pulse'
GOTO DS18B20_RESET ; If not present, Reset
MOVLW (D'420'-5)/5 ; Must wait a minmum of 480uS from when DQ line is released before moving on
CALL DELAY ;
RETURN ;

DS18B20_READ_BYTE ; This routine reads a byte of data from the DS18B20
MOVLW H'08' ; Amount of bits to shift out
MOVWF COUNT ; Store in COUNT GPR
CALL DS18B20_READ_BIT ; Read bit
RRF SHIFT, F ; Rotate bit out of carry into SHIFT GPR
DECFSZ COUNT, F ; Decrement COUNT
GOTO $-D'3' ; If not zero, read next bit
MOVF SHIFT, W ; If zero, move SHIFT GPR to W
RETURN ;

DS18B20_READ_BIT ; This routine reads one bit of data from the DS18B20
BCF INTCON, GIE ; Disable Global Interrupts
CALL DQ_LL ; Force the DQ Line to Logic Low
CALL DQ_HIZ ; Release DQ Line
BSF STATUS, C ; Preset Carry Flag
BTFSS PORTA, 4 ; Test DQ Line
BCF STATUS, C ; If zero, Clear Carry Flag
BSF INTCON, GIE ; Enable Global Interrupts
MOVLW (D'60'-5)/5 ; Wait for Time Slot to end
CALL DELAY ;
RETURN ;

DS18B20_WRITE_BYTE ; This routine writes a byte of data to the DS18B20
MOVWF SHIFT ; Move data to shift into DS18B20 to SHIFT GPR
MOVLW D'08' ; Amount of bits to shift in
MOVWF COUNT ; Store in COUNT GPR
RRF SHIFT, F ; Rotate valid data into Carry Flag
CALL DS18B20_WRITE_BIT ; Write bit
DECFSZ COUNT, F ; Decrement COUNT
GOTO $-D'3' ; If not zero, read next bit
RETURN ; If zero, RETURN

DS18B20_WRITE_BIT ; This routine writes one bit of data to the DS18B20
BCF INTCON, GIE ; Disable Global Interrupts
CALL DQ_LL ; Force the DQ Line to Logic Low
BTFSS STATUS, C ; Test Carry Flag
GOTO $+D'2' ; If zero, leave DQ Line Logic Low
CALL DQ_HIZ ; If not zero, release DQ Line to Logic High
MOVLW (D'60'-5)/5 ; Hold Logic Low, write 0
CALL DELAY ;
CALL DQ_HIZ ; If not zero, release DQ Line to Logic High, write 1
BSF INTCON, GIE ; Enable Global Interrupts
RETURN ;

DQ_HIZ ; This routine forces the DQ Line to an Input / High Impedance state
BSF STATUS, RP0 ; Bank 1
BSF TRISA, 4 ; Make Pin 3 an input, Pullup resistor forces line to logic 1, unless DS18B20 pulls it low
BCF STATUS, RP0 ; Bank 0
RETURN

DQ_LL ; This routine forces the DQ Line to Logic Low
BCF PORTA, 4 ; Clear output latch
BSF STATUS, RP0 ; Bank 1
BCF TRISA, 4 ; Make Pin 3 an output
BCF STATUS, RP0 ; Bank 0
RETURN

DELAY ; This routine can provide delays from 10uS to 1285uS depending on the number moved to the Working register prior to calling the delay
MOVWF DELAYGPR1 ; Move integer to GPR
NOP ; No Operation
NOP ; No Operation
DECFSZ DELAYGPR1, F ; Decrement GPR and place back in itself
GOTO $-D'3' ; Not finished, GOTO here - 3 instructions
RETURN ; Finished, Return

GET_TEMP
CALL DS18B20_RESET ; Reset
MOVLW H'CC' ; Skiprom
CALL DS18B20_WRITE_BYTE ; Skiprom
MOVLW H'44' ; Convert T
CALL DS18B20_WRITE_BYTE ; Convert T

CALL DS18B20_READ_BIT ; Initiate Read Time Slots
BTFSS STATUS, C ; DS18B20 transmits a 0 while the temperature conversion is in progress and a 1 when the conversion is done
GOTO $-D'2' ; Transmitting 0 therefore NOT done

CALL DS18B20_RESET ; Reset
MOVLW H'CC' ; Skiprom
CALL DS18B20_WRITE_BYTE ; Skiprom
MOVLW H'BE' ; Read Scratchpad
CALL DS18B20_WRITE_BYTE ; Read Scratchpad

CALL DS18B20_READ_BYTE ; Move Scrachpad Byte 0 to W
MOVWF TEMPLO_C ; Store in Celsius TEMPLO GPR
CALL DS18B20_READ_BYTE ; Move Scrachpad Byte 1 to W
MOVWF TEMPHI_C ; Store in Celsius TEMPHI GPR

DISPLAY_TEMP
BCF FLAGS, 1 ; Clear Negative Flag
BTFSS TEMPHI_C, 7 ; Test if Temperature is negative (2's complement format)
GOTO REARRANGE_DATA ; NOT Negative, skip 'Undo 2's Complement'
BSF FLAGS, 1 ; Set Negative Flag; used later


; Example Negative Temperature TEMPHI = 1111 1110 TEMPLO = 0110 1110 = -25.1250 (see datasheet)
COMF TEMPLO_C, F ; Invert TEMPLO
COMF TEMPHI_C, F ; Invert TEMPHI
INCFSZ TEMPLO_C, F ; Increment TEMPLO once; After inverting the data, add one to acheive equivalent positive number (see 2's complement)
GOTO $+D'2' ; No overflow skip next instruction
INCF TEMPHI_C, F ; Overflow occured, increment upper byte
; Example Negative Temperature AFTER undo TEMPHI = 0000 0001 TEMPLO = 1001 0010 = +25.1250

REARRANGE_DATA ; This routine rearranges the 2 Temperature result bytes into useable data.

MOVLW B'11110000' ; W = 1111 0000
ANDWF TEMPLO_C, W ; F = 1001 0001 W = 1001 0000
IORWF TEMPHI_C, F ; F = 0000 0011 F = 1001 0011
SWAPF TEMPHI_C, F ; F = 1001 0011 F = 0011 1001 (New TEMPHI_C)
MOVLW B'00001111' ; W = 0000 1111
ANDWF TEMPLO_C, F ; F = 1001 0001 F = 0000 0001 (New TEMPLO_C)



BIN_TO_DEC_C ; This routine converts the 8-bit number held in TEMPHI_C to Decimal and stores it in 3 GPR's; HUNS, TENS & ONES


INCF TEMPHI_C ; Preload TEMPHI + 1
CLRF HUNS ; HUNS = 0000 0000

MOVLW D'246' ; MOVE Decimal'246' to W
MOVWF TENS ; TENS GPR = 1111 0101
MOVWF ONES ; ONES GPR = 1111 0101
DECFSZ TEMPHI_C, F ; Decement TEMPHI register
GOTO $+D'2' ; NOT 0, skip next instruction
GOTO $+D'7' ; IS 0, TEMPHI = 0000 0000, skip next 6 instructions and calculate how many tens and hundreds
INCFSZ ONES, F ; Increment ONES register, skip if 0
GOTO $-D'4' ; NOT 0, GOTO here - 4 instructions
INCFSZ TENS, F ; IS 0, Increment TENS register skip if 0
GOTO $-D'7' ; GOTO here - 7 instructions & reset the ONES register to D'246'
INCF HUNS, F ; TENS overflowed, Increment HUNS
GOTO $-D'10' ; GOTO here - 10 instructions & reset the ONES and TENS registers to D'246'

SUBWF TENS, F ; W still holds D'246 so subract it from TENS register to determine how many 'TENS'
SUBWF ONES, F ; W still holds D'246 so subract it from ONES register to determine how many 'ONES'

FRACTION_ROUND ; This routine rounds the fraction portion of the Temperature data to the nearest .1
; Provided by & used with his permission from 'Pommy'. Contact via Electro-Tech-Online.com
; Examples
; TENTHS = Fraction * 10 / 16
; TENTHS = 00000100 ( D'4' * 0.0625 = 0.2500 Degrees C) * 10 / 16 = 3
; TENTHS = 00001001 ( D'9' * 0.0625 = 0.5625 Degrees C) * 10 / 16 = 6
; TENTHS = 00001101 (D'13' * 0.0625 = 0.8125 Degrees C) * 10 / 16 = 8
MOVLW B'00001111' ;
ANDWF TEMPLO_C, F ;
MOVF TEMPLO_C, W ;
ADDWF TEMPLO_C, F ; *2, C=0
RLF TEMPLO_C, F ; *4, C=0
ADDWF TEMPLO_C, F ; *5, C=0

BTFSS STATUS, Z ; Does HUNS = not 0?
GOTO $+D'5' ; Yes, do not blank TENS
MOVF TENS, W ; MOVF instruction affects Z bit of STATUS register
BTFSC STATUS, Z ; Does TENS = 0?
MOVLW B'00001010' ; Yes, jump Pointer for blank arrangement
MOVWF TENS ;


BCF INTCON, GIE ; Disable Interrupts
MOVF HUNS, W
MOVWF THOU_COL
MOVF TENS, W
MOVWF HUNS_COL
MOVF ONES, W
MOVWF TENS_COL
MOVF DECI, W
MOVWF ONES_COL
BSF INTCON, GIE ; Enable Interrupts

GOTO GET_TEMP
END
 
Hi,

The first thing you need to do is download MPlab from the Microchip site.

There are two versions, the newer MplabX and the original MPLAB IDE V8.89 which I would suggest for starting with is the simpler and better route.
https://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469

MPlab includes an Assembler so you just create a new project and copy that code into it.
I have just done that and it Assembles ok.
See the MPlab manuals and Help files on how to set up a project, also many Ytubes etc.

You always have to be careful about web based projects, many are incomplete or non functional for many reasons.
Without seeing the link to the whole project and circuit its hard to say if this one will work 100% though the code does look promising.

Be aware that the sensor used , the DS18B20 must be that type, there are other versions around.


A Microchip Pickit2 or Pickit3 are the ones to go for.

The PK2 if your budget is tight, the PK3 if you want to use all the very latest chips.
 

Attachments

  • sensor.asm
    12.9 KB · Views: 212
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…