;=======DI_1298.asm=============================================8/27/01 ; Written by Ted Salazar (^_^) ; ;This program uses the pic16f84 to read the temperature from the ;MAX1298 temperature sensor. The value read from the MAX1298 is 12-bit ;binary output code proportional to absolute temperature in degrees ;Kelvin. One LSB corresponds to 1/8 of a degree. Convert to Celsius by ;subtracting 273 from the temperature inferred from the ADC output. ;After all temperature calculations are made, the binary Celcius code ;must be converted to BCD in order for it to be displayed on the 7-segment ;LEDs using the MAX7221 LED display driver: ; ; binary code / 8 = Kelvin ; Kelvin - 273 = oC ; oC (binary) to oC (BCD) ; ; Program Status: This program is working. ; ; Special Thanks to John Payson, Rudy Wieser, and everyone involved ; with the PIC Forum. ;---------------------------------- list p=16f84 radix hex ;---------------------------------- ; memory map pc equ 0x02 status equ 0x03 c equ 0 ; bit 0 is the carry flag porta equ 0x05 portb equ 0x06 r_wconf_hbyte equ 0x0c r_wconf_lbyte equ 0x0d r_rconf_hbyte equ 0x0e r_rconf_lbyte equ 0x0f r_wdata_hbyte equ 0x10 r_wdata_lbyte equ 0x11 r_rdata_hbyte equ 0x12 r_rdata_lbyte equ 0x13 r_temp equ 0x14 ncount equ 0x15 xcount equ 0x16 kcount equ 0x17 mcount equ 0x18 dout equ 0x19 dout1 equ 0x1a dout2 equ 0x1b dout3 equ 0x1c dout4 equ 0x1d muxcount equ 0x1e charcount equ 0x1f dout7 equ 0x20 dout8 equ 0x21 dout9 equ 0x22 dout10 equ 0x23 dout11 equ 0x24 dout12 equ 0x25 dout13 equ 0x26 dout14 equ 0x27 dout15 equ 0x28 dout16 equ 0x29 dout17 equ 0x2a dout18 equ 0x2b dout19 equ 0x2c dout20 equ 0x2d NumH equ 0x2e NumL equ 0x2f TenK equ 0x30 Thou equ 0x31 Hund equ 0x32 Tens equ 0x33 Ones equ 0x34 r2lo equ 0x35 r2hi equ 0x36 nooponce_outofshutdown equ 0x37 ;---------------------------------------------- ;***** ;Main ;***** org 0x000 start movlw 0x24 ;RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 ; 0 0 1 0 0 1 0 0 ouput = 0 input =1 ;sclk cs1\ dout din cs2\ strb tris portb ;dout = RB5 = an input ;all other ports b's are outputs movlw 0x4b ;0x4b to w movwf portb ;sclk=0 1=high 0=low ;cs1\=1 ;dout=input ;din=0 ;cs2\=1 ;strb = input ;RB1 =1 LED1 ;RB0 =1 LED2 call delay2sec ;------------------------------------------------ ;********************* ;Put MAX7221 In Display Test Mode ;********************* bcf portb,6 ;cs1\=0 movlw 0x0f ;0x0f to w movwf r_wconf_hbyte ;w to register movf r_wconf_hbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% movlw 0x01 ;0x01 to w movwf r_wconf_lbyte ;w to register movf r_wconf_lbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bsf portb,6 ;cs1\=1 call delay2sec ;------------------------------------------------ ;------------------------------------------------ ;********************* ;Setting the scan rate for MAX7221 ;********************* bcf portb,6 ;cs1\=0 movlw 0x0b ;0x0b to w movwf r_wconf_hbyte ;w to register movf r_wconf_hbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% movlw 0x07 ;0x07 to w movwf r_wconf_lbyte ;w to register movf r_wconf_lbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bsf portb,6 ;cs1\=1 call delay200ms ;------------------------------------------------ ;------------------------------------------------ ;********************* ;Setting the intensity for MAX7221 ;********************* bcf portb,6 ;cs1\=0 movlw 0x0a ;0x0a to w movwf r_wconf_hbyte ;w to register movf r_wconf_hbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% movlw 0x07 ;0x07 to w movwf r_wconf_lbyte ;w to register movf r_wconf_lbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bsf portb,6 ;cs1\=1 call delay200ms ;------------------------------------------------ ;------------------------------------------------ ;********************* ;Setting Decode Mode to Code B for segments 0,1,2 of the MAX7221 ;Setting No-Decode Mode for segment 3 of the MAX7221 ;********************* bcf portb,6 ;cs1\=0 movlw 0x09 ;0x09 to w movwf r_wconf_hbyte ;w to register movf r_wconf_hbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% movlw 0x07 ;0x07 to w movwf r_wconf_lbyte ;w to register movf r_wconf_lbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bsf portb,6 ;cs1\=1 call delay200ms ;------------------------------------------------ ;------------------------------------------------ ;********************* ;Read the temperature from the internal diode of the MAX1298 ;********************* movlw 0x00 ;0x00 to w movwf nooponce_outofshutdown ;w to register used above circle 1 ;don't display first read until MAX1298 is configured circle1 bcf portb,3 ;cs2\=0 movlw 0x87 ;0x87 to w movwf r_wconf_hbyte ;w to register movf r_wconf_hbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;=> movf dout,0 ; to w movwf dout1 ; dout to dout1 Remember that dout1 is high byte ;=> ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% movlw 0xa7 ;0xa7 to w movwf r_wconf_lbyte ;w to register movf r_wconf_lbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;=> movf dout,0 ; to w movwf dout2 ; dout to dout2 Remember that dout2 is low byte ;=> ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bsf portb,3 ;cs2\=1 call delay200ms ;------------------------------------------------ ;------------------------------------------------ ;********************* ; Rotate high byte (dout1) to the right three times and rotate it into low byte (dout2) ; This is basically to accomplish the divide by 8. (Code/8 - 273 = oC) ;********************* ;The data needs to be arranged in the correct position ; first bit bcf status,c ;clear carry flag rrf dout1,1 ;rotate bits right (lsb into carry flag) result in dout1 btfsc status,c ;test carry flag and skip next instruction if carry flag is clear bsf status,c ;set carry flag rrf dout2,1 ;rotate bits right (carry flag into msb) result in dout2 ; second bit bcf status,c ;clear carry flag rrf dout1,1 ;rotate bits right (lsb into carry flag) result in dout1 btfsc status,c ;test carry flag and skip next instruction if carry flag is clear bsf status,c ;set carry flag rrf dout2,f ;rotate bits right (carry flag into msb) result in dout2 ; Start the divide by 8 shift rights ; first bit bcf status,c ;clear carry flag rrf dout1,1 ;rotate bits right (lsb into carry flag) result in dout1 btfsc status,c ;test carry flag and skip next instruction if carry flag is clear bsf status,c ;set carry flag rrf dout2,1 ;rotate bits right (carry flag into msb) result in dout2 ; second bit bcf status,c ;clear carry flag rrf dout1,1 ;rotate bits right (lsb into carry flag) result in dout1 btfsc status,c ;test carry flag and skip next instruction if carry flag is clear bsf status,c ;set carry flag rrf dout2,f ;rotate bits right (carry flag into msb) result in dout2 ; third bit bcf status,c ;clear carry flag rrf dout1,1 ;rotate bits right (lsb into carry flag) result in dout1 btfsc status,c ;test carry flag and skip next instruction if carry flag is clear bsf status,c ;set carry flag rrf dout2,1 ;rotate bits right (carry flag into msb) result in dout2 ;------------------------------------------------ ;------------------------------------------------ ;********************* ; Subtracting 273 decimal from the (high byte/8) + (low byte/8) ;********************* ; 16bit subtract ; r1 => dout1 + dout2 => XXXX XXXX XXXX XXXX ; - r2 => 273 => 0000 0001 0001 0001 => 0x01 0x11 ;-------- movlw 0x11 ;0x11 to w movwf r2lo ;w to register movlw 0x01 ;0x01 to w movwf r2hi ;w to register movf r2lo,0 subwf dout2,f movf r2hi,0 btfss status,c incfsz r2hi,0 subwf dout1,f movf dout1,0 ;register to w movwf NumH ;w to register movf dout2,0 ;register to w movwf NumL ;w to register call Convert ;------------------------------------------------ ;********************* ;Setting 7seg LED0 of MAX7221 ;********************* bcf portb,6 ;cs1\=0 movlw 0x01 ;0x01 to w movwf r_wconf_hbyte ;w to register movf r_wconf_hbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% movlw 0x0f ;0x0f to w movwf r_wconf_lbyte ;w to register movf r_wconf_lbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bsf portb,6 ;cs1\=1 call delay200ms ;------------------------------------------------ ;------------------------------------------------ ;********************* ;Setting 7seg LED1 of MAX7221 ;********************* bcf portb,6 ;cs1\=0 movlw 0x02 ;0x02 to w movwf r_wconf_hbyte ;w to register movf r_wconf_hbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% movf Tens,0 ; moves copy of contents of Tens into w movwf r_wconf_lbyte ;w to register movf r_wconf_lbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bsf portb,6 ;cs1\=1 call delay200ms ;------------------------------------------------ ;------------------------------------------------ ;********************* ;Setting 7seg LED2 of MAX7221 ;********************* bcf portb,6 ;cs\=0 movlw 0x03 ;0x03 to w movwf r_wconf_hbyte ;w to register movf r_wconf_hbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% movf Ones,0 ; moves copy of contents of Ones into w movwf r_wconf_lbyte ;w to register movf r_wconf_lbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bsf portb,6 ;cs\=1 call delay200ms ;------------------------------------------------ ;------------------------------------------------ ;********************* ;Setting 7seg LED3 to "3" of MAX7221 ;********************* bcf portb,6 ;cs\=0 movlw 0x04 ;0x04 to w movwf r_wconf_hbyte ;w to register movf r_wconf_hbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% movlw 0xce ;0xce to w movwf r_wconf_lbyte ;w to register movf r_wconf_lbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bsf portb,6 ;cs\=1 call delay200ms ;------------------------------------------------ ;------------------------------------------------ ;********************* ;Take MAX7221 Out of Display Test Mode ;********************* bcf portb,6 ;cs\=0 movlw 0x0f ;0x0f to w movwf r_wconf_hbyte ;w to register movf r_wconf_hbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% movlw 0x00 ;0x00 to w movwf r_wconf_lbyte ;w to register movf r_wconf_lbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bsf portb,6 ;cs\=1 call delay200ms ;------------------------------------------------ ;------------------------------------------------ ;********************* ;Take MAX7221 Out of Shutdown ;********************* bcf portb,6 ;cs\=0 movf nooponce_outofshutdown,0 ;don't display first read until MAX1298 is configured call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% movlw 0x01 ;0x01 to w movwf r_wconf_lbyte ;w to register movf r_wconf_lbyte,0 ; to w call spi_8bit_word ; call subroutine ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bsf portb,6 ;cs\=1 call delay200ms ;------------------------------------------------ ;------------------------------------------------ movlw 0x0c ;0x0c to w movwf nooponce_outofshutdown ;w to register used above circle 1 ;don't display first read until MAX1298 is configured bcf portb,0 ; turn off b0 LED bcf portb,1 ; turn off b1 LED ; Adjust the temperature update time here as desired. It is currently set to update ; every 2.2sec call delay200ms call delay2sec goto circle1 ;------------------------------------------------ ;********************** ; 16bit binary 2 BCD ;********************** Convert ; Takes number in NumH:NumL ; Returns decimal in ; TenK:Thou:Hund:Tens:Ones swapf NumH,w andlw 0x0f addlw 0xf0 movwf Thou addwf Thou,f addlw 0xe2 movwf Hund addlw 0x32 movwf Ones movf NumH,w andlw 0x0f addwf Hund,f addwf Hund,f addwf Ones,f addlw 0xe9 movwf Tens addwf Tens,f addwf Tens,f swapf NumL,w andlw 0x0f addwf Tens,f addwf Ones,f rlf Tens,f rlf Ones,f comf Ones,f rlf Ones,f movf NumL,w andlw 0x0f addwf Ones,f rlf Thou,f movlw 0x07 movwf TenK movlw 0x0a Lb1: addwf Ones,f decf Tens,f btfss 3,0 goto Lb1 Lb2: addwf Tens,f decf Hund,f btfss 3,0 goto Lb2 Lb3: addwf Hund,f decf Thou,f btfss 3,0 goto Lb3 Lb4: addwf Thou,f decf TenK,f btfss 3,0 goto Lb4 retlw 0 ;------------------------------------------------ ;------------------------------------------------ ;The "spi_8bit_word" subroutine takes the contents of ;the various _hbyte and _lbyte's and shifts them out ;through the GPIO port B to create a bit banged SPI port. ;This subroutine is generic and can be used for any SPI ;device requiring sclk, din and dout. CS\ is taken care of before and after this subroutine but within it. ;************ spi_8bit_word ;************ movwf r_temp ;r_temp = w movlw 0x08 ;0x08 to w movwf ncount ;0x08 to ncount btfline btfsc r_temp,7;test bit 7 of r_temp ;skip if clear goto spi_hi ;spi_low rlf r_temp,f nop bsf portb,7 ;sclk=1 nop ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;=> btfsc portb,5 ;test DOUT of UART goto dout_hi_spi_low rlf dout,f bcf dout,0 ;=> ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sclklw1 bcf portb,7 ;sclk=0 decfsz ncount goto btfline out return spi_hi rlf r_temp,f bsf portb,4 ;Din=1 nop bsf portb,7 ;sclk=1 ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ; => btfsc portb,5 ;test DOUT of UART goto dout_hi_spi_hi rlf dout,f bcf dout,0 ;=> ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% nop sclklw2 bcf portb,7 ;sclk=0 bcf portb,4 ;Din=0 decfsz ncount goto btfline goto out ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;=> dout_hi_spi_low rlf dout,f bsf dout,0 goto sclklw1 ;=> ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;=> dout_hi_spi_hi rlf dout,f bsf dout,0 goto sclklw2 ;=> ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;----------------------------------------------------- ;Delay Subroutine ;xcount controls the delay time ;i.e. xcount x 200ms = delay ;******** delay2sec ;******** movlw 0x0A ;0x0A to w movwf xcount ;to xcount loadm movlw 0xff ;0xff to w movwf mcount ;to mcount loadk movlw 0xff ;0xff to w movwf kcount ;to kcount deck decfsz kcount,f;dec k goto deck decfsz mcount,f;dec m goto loadk ;jump to loadk decfsz xcount,f;dec x goto loadm ;jump to loadm return ;----------------------------------------------------- ;----------------------------------------------------- ;Delay Subroutine ;xcount controls the delay time ;i.e. xcount x 200ms = delay ;******** delay200ms ;******** movlw 0x01 ;0x01 to w movwf xcount ;to xcount loadm2 movlw 0xff ;0xff to w movwf mcount ;to mcount loadk2 movlw 0xff ;0xff to w movwf kcount ;to kcount deck2 decfsz kcount,f;dec k goto deck2 decfsz mcount,f;dec m goto loadk2 ;jump to loadk decfsz xcount,f;dec x goto loadm2 ;jump to loadm return ;---------------------------------------- ;****** end ;****** ;======================================== ; Flash Program Settings: ; memory unprotected ; watchdog timer disabled (default enabled) ; standard crystal (4Mhz) ; power-up timer on ;========================================