📄 ds1820.asm
字号:
bsf status,c ; shift a 1 into quotient ;; ( rl rh ^ ql qh nl nh dl dh sign count ) sb_divide_skip_2 ;; shift the quotient left decf fsr,f ; ->ql rlf indf,f ; ql decf fsr,f ; ->qh rlf indf,f ; qh ;; loop until all bits checked movlw d'6' subwf fsr,f ; ->count decfsz indf,f ; count goto sb_divide_loop popl ; drop count ;; ( rl rh ql qh nl nh dl dh sign ) ;; adjust stack popf r_ephemeral movlw d'4' addwf fsr,f ; drop nl nh dl dh ;; ( rl rh ql qh ) ;; check effective sign difference and adjust quotient btfss r_ephemeral,7 retlw 0 ; signs were same ;; signs different, negate quotient goto sb_negate;;; bank 1 follows ifdef __12c509 org 0x200 ; push main to high bank endif;;;;;; main program;;; main ;; clear stack movlw stack movwf fsr ;; clear output port clrf port ;; clear tris mirror clrf r_trism bsf r_trism,b_ow0 bsf r_trism,b_ow1 bsf r_trism,b_in bsf r_trism,b_ow2 bsf r_trism,b_ow3 movf r_trism,w movwt ;; set option register to enable pull-ups and enable GP2 ifdef __12c509 movlw b'10011111' ; NOT_GPPU, T0CS option endif ;; set option register ifdef __16f84 ;; enable port b weak pullups (NOT_RBPU=0) ;; free RA4/TOCKI pin (T0CS=0) ;; prescaler to WDT (PSA=1) ;; prescaler at 1:64, 18ms x 64 = 1.152sec movlw b'01011110' movwf OPTION_REG endif ;; pause for 0.5s to let supply stabilise before chatting pushl d'195'pause_loop pushl d'0' ; 2.65ms bank0 call us10 bank1 decfsz indf,f goto pause_loop popl ;; test for fahrenheit mode, gp3 low ;; (if left open, it is pulled up to high) btfss port,b_in bsf r_trism,b_fahre ifdef notdefnoisy ;; need to account for gp0 being input now ;; test for noisy mode; gp0 connected to gp3 bank1 bsf port,gp0 ; turn on gp0 btfss port,gp3 ; see if gp3 goto noisy_skip bcf port,gp0 btfsc port,gp3 goto noisy_skip bsf b_noisy,r_trism goto noisy_donenoisy_skip noisy_done endif ;; say g'daygday pushl 'R' ; reset bank0 call tx_header pushl 0 ; start at beginning of tablegday_loop movf indf,w ; pull down index bank0 call t_gday ; get the byte from the string iorlw 0 ; is zero? bank1 bz gday_exit ; if so, exit loop pushw bank0 call tx_byte ; transmit the character incf indf,f ; increment index bank1 goto gday_loopgday_exit ;; print C or F according to b_fahre movlw 'C' ; assume low btfsc r_trism,b_fahre movlw 'F' ; set high if non zero pushw bank0 call tx_space call tx_byte ; display the F or C call tx_crlf ; followed by a new line pair ;; select starting sensor movlw 1<<b_ow0 movwf r_which ;; main loop begins hereloop ;; determine displayable sensor number movlw 0 ; initialise sensor counter movwf r_ephemeral movf r_which,w ; copy selection mask to temporary movwf r_temporary bank1 which_loop btfsc r_temporary,0 ; have we shifted the bit down yet? goto which_exit ; yes, exit the loop rrf r_temporary,f ; shift the bit down incf r_ephemeral,f ; increment the sensor number goto which_loop which_exit movf r_ephemeral,w bank0 call t_which ; translate to printable pushw ; save on stack ;; reset bus to determine if sensor is present ;; bank0 call ow_reset ; ( -- flag ) popw iorlw 0x0 ; set zero flag if sensor absent bank1 bnz present ;; if non-verbose, don't report pins without sensors ;; bank1 ;; btfss port,b_in ; verbose mode on? goto hello_skip ; no, skip it ;; report a sensorless pin bank0 call tx_header ; transmit the sensor number movf r_which,w ; fetch the selection mask andwf port,w ; keep the port bit we want movlw 'L' ; assume low skpz movlw 'H' ; set high if non zero pushw ;; bank0 call tx_byte ; display the L or H call tx_crlf bank1 goto absent hello_skip popl ; drop the sensor number goto absentpresent bank0 call tx_header ; transmit the sensor number ;; skip rom check sequence pushl ow_command_skip bank0 call ow_tx ;; commence conversion pushl ow_command_convert call ow_tx ;; wait until sensor not busy ;; ??? we wait until we get eight bits of 1's, which could take ;; longer than just waiting for one bit of 1. try waiting for 1? ;; ds1820 specification says 200ms typical, 500ms maximumbusy bank0 call ow_rx ; fetch a byte popw ; pop the byte from stack xorlw 0xff ; test for 0xff bank1 bnz busy ; loop if not equal ;; ask sensor for data ;; reset bus bank0 call ow_reset ; ( -- flag ) popw iorlw 0x0 ; set zero flag if sensor absent bank1 bz absent ;; skip rom check sequence pushl ow_command_skip bank0 call ow_tx ;; request data pushl ow_command_read call ow_tx ;; read data from sensorow_get macro m_byte ; get byte to address ;; bank0 call ow_rx popf m_byte endm ow_get r_ds_lsb ow_get r_ds_msb ow_get r_ds_rem ; ignore low alarm byte ow_get r_ds_rem ; ignore high alarm byte ow_get r_ds_rem ; ignore reserved byte ow_get r_ds_rem ; ignore reserved byte ow_get r_ds_rem ow_get r_ds_count ow_get r_ds_crc ;; ??? check the crc some day! ;; in verbose mode, dump the data in hexdata bank1 ;; btfss port,b_in ; verbose mode on? goto data_skip ; no, skip it tx_put r_ds_lsb tx_put r_ds_msb tx_put r_ds_rem tx_put r_ds_count tx_put r_ds_crc call tx_spacedata_skip;;;;;; dump stack pointer at top value;;; if debug == 1dump macro m_label pushl m_label ; print the label byte bank0 call tx_byte tx_put fsr ; ??? stack check call tx_space endm elsedump macro m_label ; null macro endm endif;;;;;; Calculation of high resolution temperature from the count per degrees;;; c and remaining count values fetched from the DS1820 scratchpad.;;;;;; high-res-temp = ( temperature >> 1 ) - 0.25;;; + (count-per-c - count-remain) / (count-per-c);;; ;;; Problem: Result is truncated to two decimal places rather than being;;; rounded. Solution not yet planned.;;; ;; move temperature as read to accumulator pushf16 r_ds_lsb ;; shift right to truncate 0.5C LSB bcf status,c ; start with a clear carry flag rrf indf,f incf fsr,f rrf indf,f decf fsr,f ;; multiply by 100 to scale to hundredths of degrees pushl16 d'100' bank0 call sb_multiply dump 'A' ;; subtract 25 from accumulator pushl16 d'25' ;; bank0 call sb_subtract dump 'B' ;; keep on stack for later use ;; take eight bit count per degrees c ;; subtract count remaining movf r_ds_rem,w ; get count remaining subwf r_ds_count,w ; subtract it from count per degrees c pushw ; place on stack pushl d'0' ; extend to sixteen bits ;; multiply by 100 to scale pushl16 d'100' ;; bank0 call sb_multiply dump 'C' ;; divide by count per degrees c pushf r_ds_count pushl d'0' ; extend to sixteen bits ;; bank0 call sb_divide call sb_nip ; drop remainder dump 'D' ;; we now have offset from temperature in hundredths of degrees ;; add to previouosly saved value ;; bank0 call sb_add dump 'E' ;; we now have the measurement in degrees centigrade, scaled by ;; 100, such that 23.54 degrees is binary value for decimal 2354 ;; convert to fahrenheit bank1 btfss r_trism,b_fahre ; if bit zero, degrees C goto fahrenheit_skip ; yes, skip it bank0 pushl16 d'9' ; multiply by nine call sb_multiply pushl16 d'5' ; divide by five (therefore multiply by 1.8) call sb_divide call sb_nip ; drop remainder pushl d'128' ; add thirty two (3200) pushl d'12' call sb_add fahrenheit_skip ;; check sign of result bank1 btfss indf,7 ; sign bit of signed integer result goto skip ; bit cleared, it is positive ;; issue negative sign to output pushl '-' bank0 call tx_byte ;; subtract from zero call sb_negateskip ;; convert value to bcd bank0 call sb_bcd dump 'F' ;; transmit the bcd output buffer call tx_byte_hex ; d2 (msd) call tx_byte_hex ; d1 pushl '.' ; interject the decimal place '0655.35' call tx_byte call tx_byte_hex ; d0 (lsd) ;; finish the output off with a newline call tx_crlf ;; delay for a while between outputs, try to get 500ms bank1 ;; btfsc port,b_in ; verbose mode on? ;; goto snooze_skip ; yes, skip it ;; (above takes 279ms, so we need 221ms) pushl d'85' ; ( outer ) [experimental figure]snooze_loop pushl d'250' ; ( outer inner ) bank0 call us10 bank1 decfsz indf,f ; ( outer ) goto snooze_loop popl ; ( )snooze_skip absent ;; switch to next sensor by spinning the mask around to next combo btfss r_which,7 ; propogate bit 7 to carry flag bcf status,c btfsc r_which,7 bsf status,c rlf r_which,f ; logical left rotate (spin bits) movlw m_ow ; is it a bit we can use? andwf r_which,w bz absent ; no, so spin it again ;; clear watchdog timer! clrwdt ;; and do it all again goto looplast2 retlw 0 ; define the last byte used in page 2/3 ;; ease determination of last used data address cblock r_zzz endc ;; calibration for 12C509-JW part ifdef __12c509 ifdef jw org 0x3ff movlw 0x50 ; 12c509 #1 ; movlw 0x30 ; 12c509 #2 endif endif ;; cross-checks ifdef __12c509 if r_zzz > 0x1f messg "error: last allocated file register is not in bank 0" endif if last0 > 0xff messg "error: last function in page 0 is beyond call limit" endif if last2 > 0x3ff messg "error: code in page 3 runs over to page 4 (>0x3ff)" endif endif end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -