;******************************************************************
;* *
;* Filename: 16F628A DS18B20.asm *
;* Author: Mike McLaren, K8LH *
;* Date: 21-May-10 *
;* *
;* *
;* *
;* MPLab: 8.50 (tabs = 8) *
;* MPAsm: 5.35 *
;* *
;******************************************************************
include "P16F628A.inc"
errorlevel -302 ; suppress bank warnings
list st=off ; suppress symbol table
radix dec ; default radix = decimal
__CONFIG _LVP_OFF&_WDT_OFF&_INTOSC_OSC_NOCLKOUT&_MCLRE_OFF
;--< variables >---------------------------------------------------
column equ 0x20 ; column number, 0..2
colsel equ 0x21 ; column select bit
huns equ 0x22 ; huns, 0..1
tens equ 0x23 ; tens, 0..9
ones equ 0x24 ; ones, 0..9
tenths equ 0x25 ; tenths, 0..9
TempLo equ 0x26 ;
TempHi equ 0x27 ;
flags equ 0x28 ;
w_isr equ 0x70 ;
s_isr equ 0x71 ;
p_isr equ 0x72 ;
f_isr equ 0x73 ;
;--< constants >---------------------------------------------------
#define negflag flags,0 ; "negative" flag bit
;******************************************************************
; reset vector *
;******************************************************************
org 0x000
vReset
clrf STATUS ; force bank 0, IRP = 0 |B0
goto Init ; |B0
;******************************************************************
; interrupt vector, 1 msec Timer 2 interrupts *
;******************************************************************
org 0x004
vInt
movwf w_isr ; save WREG |B?
swapf STATUS,W ; don't change STATUS bits |B?
movwf s_isr ; save STATUS reg |B?
clrf STATUS ; bank 0 |B0
movf PCLATH,W ; |B0
movwf p_isr ; save PCLATH |B0
clrf PCLATH ; force page 0 |B0
movf FSR,W ; |B0
movwf f_isr ; save FSR |B0
bcf PIR1,TMR2IF ; clear TMR2 interrupt flag |B0
;
; refresh display
;
clrf PORTB ; blank the display |B0
movf PORTA,W ; |B0
andlw b'11111000' ; clear column select bits |B0
iorwf colsel,W ; 00000100,00000010, or 00000001 |B0
movwf PORTA ; select new column |B0
movf column,W ; column number, 0..2 |B0
addlw tens ; add to 'tens' address |B0
movwf FSR ; FSR = &tens, &ones, or &tenths |B0
movf INDF,W ; WREG = 0..9 |B0
call segtable ; get segment data |B0
btfsc colsel,1 ; 2nd column? no, skip, else |B0
iorlw 1 ; set "decimal point" bit |B0
movwf PORTB ; display new column |B0
;
; prepare for next column interrupt
;
incf column,F ; bump column number |B0
clrc ; |B0
rrf colsel,F ; advance column select bit |B0
skpnc ; last column? no, skip, else |B0
bsf colsel,2 ; reset to column 1 (00000100) |B0
skpnc ; last column? no, skip, else |B0
clrf column ; reset column number |B0
;
; restore context
;
movf f_isr,W ; |B0
movwf FSR ; restore FSR |B0
movf p_isr,W ; |B0
movwf PCLATH ; restore PCLATH |B0
swapf s_isr,W ; |B0
movwf STATUS ; restore STATUS |B?
swapf w_isr,f ; don't change STATUS bits |B?
swapf w_isr,W ; restore WREG |B?
retfie ; |B?
;
; segment data table (caveat, non-boundary tolerant)
;
segtable ; map B|A|F|G|E|D|C|P
addwf PCL,F ; |B0
retlw b'11101110' ; "0" B|A|F|-|E|D|C|- |B0
retlw b'10000010' ; "1" B|-|-|-|-|-|C|- |B0
retlw b'11011100' ; "2" B|A|-|G|E|D|-|- |B0
retlw b'11010110' ; "3" B|A|-|G|-|D|C|- |B0
retlw b'10110010' ; "4" B|-|F|G|-|-|C|- |B0
retlw b'01110110' ; "5" -|A|F|G|-|D|C|- |B0
retlw b'01111110' ; "6" -|A|F|G|E|D|C|- |B0
retlw b'11000010' ; "7" B|A|-|-|-|-|C|- |B0
retlw b'11111110' ; "8" B|A|F|G|E|D|C|- |B0
retlw b'11110110' ; "9" B|A|F|G|-|D|C|- |B0
;******************************************************************
; main.init *
;******************************************************************
Init
bsf STATUS,RP0 ; bank 1 |B1
clrf TRISA ; porta all outputs |B1
clrf TRISB ; portb all outputs |B1
bcf STATUS,RP0 ; bank 0 |B0
clrf PORTB ; clear portb output latches |B0
;
; init program variables
;
clrf column ; column = 0 (1st column) |B0
movlw b'00000100' ; column select bit mask |B0
movwf colsel ; |B0
clrf tens ; |B0
clrf ones ; |B0
clrf tenths ; |B0
clrf TempLo ; |B0
clrf TempHi ; |B0
;
; setup TMR2 for 1 msec periodic interrupts (4 MHz clock)
;
clrf TMR2 ; clear TMR2 register |B0
bsf STATUS,RP0 ; bank 1 |B1
clrf PIE1 ; mask all peripheral irqs |B1
bsf PIE1,TMR2IE ; except for TMR2 irq |B1
bcf STATUS,RP0 ; bank 0 |B0
clrf PIR1 ; clear peripheral irq flags |B0
movlw b'00000001' ; '00000001' |B0
; '0-------' unused
; '-0000---' postscale 1
; '-----0--' TMR2 off
; '------01' prescale 4
movwf T2CON ; for 4-usec ticks (4-MHz clk) |B0
bsf STATUS,RP0 ; bank 1 |B1
movlw d'250'-1 ; 250 X 4-usec ticks = 1-msec |B1
movwf PR2 ; for 1-msec interrupts |B1
bcf STATUS,RP0 ; bank 0 |B0
bsf INTCON,GIE ; enable global irqs |B0
bsf INTCON,PEIE ; enable peripheral irqs |B0
bsf T2CON,TMR2ON ; start TMR2 |B0
;******************************************************************
; main.loop *
;******************************************************************
Loop
;
; dummy GetTemp code puts 22.0°C value in TempHi:TempLo vars
;
movlw 0x0B ; |B0
movwf TempHi ; |B0
movlw 0x00 ; |B0
movwf TempLo ; |B0
;
; TempHi:TempLo -> BBBBBHHH IIIIFFFF (HHH IIII = Integer 0..125)
;
AbsFunc
bcf negflag ; clear "neg" flag |B0
btfss TempHi,7 ; negative temperature? |B0
goto BinPrep ; no, branch, else |B0
comf TempLo,F ; two's compliment it |B0
comf TempHi,F ; |B0
incf TempLo,F ; |B0
skpnz ; |B0
incf TempHi,F ; |B0
bsf negflag ; indicate "negative" |B0
;
; put the 7-bit Integer temperature (0..127) in WREG and
; leave the 4-bit fraction in TempLo
;
BinPrep
movlw 0xF0 ; W = 11110000 |B0
andwf TempLo,W ; W = LLLL0000, F = LLLLFFFF |B0
iorwf TempHi,F ; F = LLLL0HHH |B0
swapf TempHi,W ; W = 0HHHLLLL, 0..125 |B0
;
; 8-bit binary to 3 digit half-packed BCD (isochronous)
;
; input: WREG, 0..255 (0x00..0xFF)
; output: huns, 0..2
; tens, 0..9
; ones, 0..9
;
clrf huns ; |B0
clrf tens ; |B0
addlw -200 ; W = W - 200 |B0
rlf huns,F ; pick up Carry result |B0
btfss huns,0 ; borrow? no, skip, else |B0
addlw 200 ; add 200 back |B0
addlw -100 ; subtract 100 |B0
rlf huns,F ; pick up Carry result |B0
btfss huns,0 ; borrow? no, skip, else |B0
addlw 100 ; add 100 back |B0
addlw -80 ; |B0
rlf tens,F ; |B0
btfss tens,0 ; |B0
addlw 80 ; |B0
addlw -40 ; |B0
rlf tens,F ; |B0
btfss tens,0 ; |B0
addlw 40 ; |B0
addlw -20 ; |B0
rlf tens,F ; |B0
btfss tens,0 ; |B0
addlw 20 ; |B0
addlw -10 ; |B0
rlf tens,F ; |B0
btfss tens,0 ; |B0
addlw 10 ; |B0
movwf ones ; |B0
;
; "tenths" = fraction * 10 / 16
;
movlw 0x0F ; |B0
andwf TempLo,F ; |B0
movf TempLo,W ; |B0
addwf TempLo,F ; *2, C=0 |B0
rlf TempLo,F ; *4, C=0 |B0
addwf TempLo,F ; *5, C=0 |B0
rlf TempLo,F ; *10 |B0
swapf TempLo,W ; pseudo divide by 16 |B0
andlw 0x0F ; |B0
movwf tenths ; |B0
goto Loop ; |B0
;******************************************************************
; subroutines *
;******************************************************************
;******************************************************************
end