📄 ds1820.asm
字号:
;; ;; $Id: ds1820.asm,v 1.1 2001/12/27 22:46:51 james Exp james $;; ;; ds1820.asm, a PIC 12C509 or 16F84 based DS1820 translator;; Copyright (C) 2002 James Cameron (quozl@us.netrek.org);;;; This program is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 2 of the License, or;; (at your option) any later version.;;;; This program is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;; GNU General Public License for more details.;;;; You should have received a copy of the GNU General Public License;; along with this program; if not, write to the Free Software;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA;;;;;; Refer to http://quozl.netrek.org/ts/ or http://quozl.linux.org.au/ts/;; for further documentation.;; ;; Variable prefix conventions;; b_ bit number;; m_ bit mask;; r_ static file register;; ;; Function prefix conventions;; t_ entry point for a lookup table;; ow_ one wire bus communication functions;; tx_ serial data transmission functions;; sb_ sixteen bit math functions;;;; Source code reading hints;; - INDF is a data stack pointer, FSR is top of stack,;; - stack macros are used, check their definitions carefully,;; - explicit bank switching is done in the code, using macros.;; ifdef __16f84 processor 16f84 list f=inhx8m include "p16f84.inc" __config _cp_off & _wdt_on & _hs_osc endif ifdef __12c509 processor 12c509 list f=inhx8m include "p12c509a.inc" ifdef jw __config _mclre_off & _cp_off & _wdt_on & _iNTrc_osc endif ifdef cp __config _mclre_off & _cp_on & _wdt_on & _iNTrc_osc endif endif ifdef __16f84base equ 0x0c ; first free file register addressstack equ 0x4f+1 ; end address of stackport equ portb ; port on which bits are usedmovwt macro ; move w to tris tris trisb endmbank0 macro endmbank1 macro endm endif ifdef __16f84 endif ifdef __12c509base equ 0x07 ; first free file register addressstack equ 0x1f+1 ; end address of stackport equ gpio ; port on which bits are usedmovwt macro ; move w to tris tris gpio endmbank0 macro ; select low bank for goto/call bcf status,pa0 endmbank1 macro ; select high bank for goto/call bsf status,pa0 endm endifdebug equ 0 ; set to one to enable calculation stack trace ;; port bit allocationsb_ow0 equ 0 ; one wire bus to first DS1820b_ow1 equ 1 ; one wire bus to second DS1820b_tx equ 2 ; serial output 2400 baud to hostb_in equ 3 ; mode flag inputb_ow2 equ 4 ; one wire bus to third DS1820b_ow3 equ 5 ; one wire bus to fourth DS1820 ;; r_trism extra allocationsb_noisy equ 6 ; display more datab_fahre equ 7 ; display in fahrenheit ;; mask of one wire bus valid bits m_ow equ 1<<b_ow0|1<<b_ow1|1<<b_ow2|1<<b_ow3 ;; data stack macros, to reduce memory use ;; fsr points to top element of stack ;; stack grows downward in memory addresses (upward on paper) ;; initial fsr high in register space popw macro ; pop to w from stack movf indf,w incf fsr,f endmpushw macro ; push from w to stack decf fsr,f movwf indf endmpopl macro ; pop literal (aka drop) from stack incf fsr,f endmpushl macro m_literal ; push literal to stack movlw m_literal pushw endmpopf macro m_to ; pop to file addresss (uses w) popw movwf m_to endmpushf macro m_from ; push from file address (uses w) movf m_from,w pushw endmpopf16 macro m_to ; pop 16-bit value popf m_to+1 popf m_to endmpushf16 macro m_from ; push 16-bit value pushf m_from pushf m_from+1 endmpushl16 macro m_literal ; push literal to stack pushl m_literal pushl 0 endmpopl16 macro ; pop literal (aka 2drop) popl popl endmmov16 macro m_from,m_to ; move 16 bit value movf m_from+0,w movwf m_to+0 movf m_from+1,w movwf m_to+1 endm clr16 macro m_from clrf m_from+0 clrf m_from+1 endm ;; static register allocation ;; (12c509 has 9 registers addressible regardless of bank select) cblock base r_ephemeral ; lowest stack level temporary storage r_temporary ; middle stack level temporary storage r_trism ; mirror of tristate output latch ; used by ow_high, ow_low, main r_which ; bit mask of which DS1820 to talk to ; data read from device scratchpad r_ds_lsb ; temperature lsb r_ds_msb ; temperature msb r_ds_rem ; remaining count after conversion r_ds_count ; counts per degrees c r_ds_crc ; cyclic redundancy check byte endc ;; FSR based data stack is from 0x1f to 0x10, 16 bytes. ;; register addresses 0x30 to 0x3f are unallocated due to the ;; requirement to set bit five of FSR prior to access. ;; start of executable code org 0x0 ifdef __12c509 movwf OSCCAL ; calibrate internal oscillator endif bank1 goto main ; go to main program;;;;;; t_gday, table lookup of serial number;;;;;; input: w contains offset in string;;; output: w contains table value;;; t_gday addwf pcl,f ; vector to byte in serial # ;; include "version.inc" ; fetch version from file dt "V1.0" ; or use this line dt " " ;; include "serial.inc" ; fetch serial number from file dt "quozl.netrek.org/ts" ; or use this line retlw 0 ; terminating zero for caller ;;;;;; t_which, table lookup of sensor number;;;;;; input: w contains port bit number;;; output: w contains ASCII sensor number;;; t_which addwf pcl,f dt "12 34" ;;;;;; us, delay a number of 10 microsecond cycles;;;;;; call stack: none;;; data stack: ( cycles -- ) [total 1];;; us10 nop nop nop nop nop nop nop decfsz indf,f ; loop until done goto us10 popl ; drop argument retlw 0;;;;;; ow_, routines for one wire bus communication;;;;;;;;; ow_command_*, one wire bus command bytes, from ds-1820 data sheet;;; ow_command_skip equ 0xcc ; skip rom match sequenceow_command_convert equ 0x44 ; commence temperature conversionow_command_read equ 0xbe ; read the data scratchpad;;;;;; ow_high, one wire high, allow output line to float to pull-up;;;;;; call stack: none;;; data stack: none;;; ow_high movf r_which,w ; fetch the selection mask iorwf port,f ; set that bit in port latch ; (a momentary 2uS fast pull-up) iorwf r_trism,w ; set that bit in tris mask movwf r_trism ; save tris mask movwt ; set tris retlw 0;;;;;; ow_low, one wire low, drive output line to ground;;;;;; call stack: none;;; data stack: none;;; ow_low comf r_which,w ; fetch inverted selection bits andwf port,f ; reset selected bits of port andwf r_trism,f ; reset selected bits of tris mirror movf r_trism,w ; fetch tris mirror movwt ; set tris retlw 0;;;;;; ow_reset, one wire reset, signal the slave that we want a bus reset;;;;;; call stack: calls others that do not call;;; data stack: ( -- slave-present-flag ) [total 1];;; ow_reset ;; allow the bus to go high call ow_high pushl d'9' ; 60us delay call us10 ;; now check to see if the bus is sick (no pull-up) movf port,w ; read port bits once only andwf r_which,w ; keep bits we want bz ow_reset_fail ; bus is being held down, fail ;; bus is healthy, now issue a reset call ow_low pushl d'50' ; 500us delay (480 to 960us) call us10 call ow_high pushl d'9' ; 60us delay call us10 movf port,w ; read port bits once only andwf r_which,w ; keep bits we want bz ow_reset_ok pushl d'39' ; total 480us delay call us10 ow_reset_fail pushl 0 ; return failure status retlw 0ow_reset_ok pushl d'39' ; total 480us delay call us10 pushl 1 ; return success status retlw 0;;;;;; ow_rx, one wire receive, receive a byte from the bus;;;;;; call stack: calls others that do not call;;; data stack: ( -- received-byte ) [total 1];;; ow_rx pushl d'0' ; received data pushl d'8' ; count of bits to read inow_rx_loop call ow_low ; generate short low for slave nop call ow_high nop ; delay for 6 microseconds nop nop nop nop nop movf port,w ; read port bits once only andwf r_which,w ; keep bits we want btfsc status,z ; test if it is zero bcf status,c ; it is, so clear carry btfss status,z ; test if it is one bsf status,c ; it is, so set carry incf fsr,f ; rotate the bit into our copy rrf indf,f decf fsr,f pushl d'6' ; and wait for sixty microseconds call us10 decfsz indf,f ; decrement count of bits to read goto ow_rx_loop ; loop until end of byte incf fsr,f ; drop count of bits retlw 0 ;;;;;; ow_tx, one wire transmit, output a byte on the bus;;;;;; call stack: calls others that do not call;;; data stack: ( transmit-byte -- ) [total 3];;; ow_tx pushl d'8' ; initialise bits in byte counterow_tx_loop incf fsr,f ; rotate next bit to carry flag rrf indf,f decf fsr,f btfsc status,c ; test the bit goto ow_tx_one ow_tx_zero ; transmit a zero call ow_low ; by generating a long low pushl d'6' ; for sixty microseconds call us10 call ow_high ; then return to high goto ow_tx_skip ; and continue to next bit ow_tx_one ; transmit a one call ow_low ; by generating a short low call ow_high ; followed by a long high pushl d'6' ; for sixty microseconds call us10ow_tx_skip decfsz indf,f ; decrement bits in byte counter goto ow_tx_loop ; loop until counter zero incf fsr,f ; drop bits in byte counter incf fsr,f ; drop transmit byte retlw 0 ; return to caller;;;;;; tx_, routines for serial transmission, asynchronous;;; ;;;;;; tx_byte_hex, transmit a byte in hexadecimal;;;;;; call stack: calls others that do not call;;; data stack: ( byte-to-send -- ) [total 3];;; tx_byte_hex swapf indf,w ; send high nibble first call tx_byte_hex_digit popw tx_byte_hex_digit andlw 0x0f ; keep low nibble only pushw ; save to data stack movlw 0x0a ; test for greater than nine subwf indf,w ; by subtraction movlw 0x30 ; assume numeric btfsc status,c ; test result of subtraction movlw 0x37 ; alphabetic addwf indf,f ; offset to ASCII character; goto tx_byte ; fall-through optimisation;;;;;; tx_byte, transmit byte, serially send at 2400 ;;;;;; call stack: none;;; data stack: ( transmit-byte -- ) [total 2];;; tx_byte pushl 9 ; bit count bcf status,c ; start bit tx_byte_loop_1 btfsc status,c ; echo bit to output bcf port,b_tx btfss status,c bsf port,b_tx pushl d'134' ; set timer for 416us, 2400 baud ;; [cycles=7]tx_byte_loop_2 decfsz indf,f goto tx_byte_loop_2 popl ; drop timer incf fsr,f ; rotate byte to send rrf indf,f decf fsr,f ;; [cycles=11+134*3] decfsz indf,f ; decrement bit count and loop goto tx_byte_loop_1 ;; [cycles=14+134*3], therefore 2403.8 baud bcf port,b_tx ; send stop bit movlw d'134' ; set timer pushw
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -