Dignostyka magistrli 1-Wire

Nov 01, 2006 23 Replies

Witam,



Wykonałem sobie prościutki układzik DS9097E (pasywny interfejs RS232<=>1-Wire) i podpiąłem pod niego DS1820. Niestety, nie jest on wykrywany.



Jak bez oscyloskopu zdiagnozować poprawność działania interfejsu?


jaki program? Dokladnie 10x sprawdzales schemat (wez te z elektrody), moze zle policzyles piny DB9 czy cos takiego. Zobacz na innym RS.

Ja mam podobne przeboje. Uk³ad na Atmega8 i DS1820 + LCD. Pokazuje mi sygna³ obecno¶ci i melduje siê na LCD ale potem jak próbujê cokolwiek zrobiæ to wychodz± dziwactwa. Odczytanie seriala powoduje wy¶wietlenie zawsze tej samej warto¶ci ale innej ni¿ nadrukowana na uk³±dzie. Temp. to ju¿ w ogóle pokazuje z kosmosu. Mam oscyloskop i w³a¶nie siê zastanaiwa³em czy tam siê co¶ zobaczy. Bardziej chyba jaki¶ analizator. Nie wiem jak usi±¶æ do problemu.

Rafa³

U¿ytkownik "Pawe³" snipped-for-privacy@WYTNIJires.pl napisa³ w wiadomo¶ci news:eiaq5a$1pn$ snipped-for-privacy@inews.gazeta.pl...

Sprawdzałem na dwóch COMach, pinout na DB9 sprawdzałem chyba z 10x (schemat był pod DB25 więc pod uwagę brałem opisy sygnałów a nie numery pinów).

Sprawdziłem soft z

formatting link
, i ten skandynawski pod okienka i ten konsolowy. Konsolowy na COM1 musiałem przekompilować.

Nie hula, brak numeru seryjnego czujnika i już.

U¿ytkownik "Pawe³" snipped-for-privacy@WYTNIJires.pl napisa³ w wiadomo¶ci news:eiaq5a$1pn$ snipped-for-privacy@inews.gazeta.pl...

Witam!!

Wyslij znak reset (poziom niski przez min 480 us). Zaraz po wyslaniu zmieniasz kierunek linii (z wysylania na czytanie), zrob petle, ktora bedzie czekala, az ds18b20 ustawi poziom niski. Wtedy bedziesz wiedzial, czy to dziala...

No i teraz ja mam problem z tym ukladem :) Sprawa wyglada tak...juz sam reset jest dziwny. W aplikacji jest napisane, ze po wyslaniu resetu jest opoznienie 15-60 us i pozniej ds podaje stan niski przez 60-240 us. W tym problem, ze u mnie opoznienie po resecie wynosi

8 us to jeszcze ds podaje stan niski przez 32 us. Wartosci sprawdzone na oscyloskopie ze znacznikiem, wiec o pomylce raczej nie ma mowy...

Kolejna sprawa, przy wysylaniu rozkazow...tutaj juz nic zupelnie ds nie odpowiada, ktorykolwiek rozkaz bym wyslal... Czasy i algorytm wysylania mam dobry (porownanie oscyloskopu i aplikacji ds18d20). Ktos moze ma jakis pomysl? Czy mogl sie uklad zwalic, jak zostal na poczatku zle spolaryzowany, a pozniej jeszcze na wejscie zostal podany sygnal wysoki, podczas gdy zasilanie bylo rowne 0 V? Pewnie tak, ale na reset reaguje :). Nie wiem...jutro polece po nowego ds :)

Pozdrawiam!!

moze DSek upalony? Zobacz z innym czyms na 1wire jak masz :) Soft od maxima odpal, ten w javie np. Mi dzialalo od 1 podlaczenia.

DS dobrze podlaczasz mam nadzieje, spiete 2 zewnetrzne nozki i do masy, srodkowa to byla DATA chyba.

W wiadomości od Papkin odebranej 2006-11-01 22:23 mogłem przeczytać:

Właśnie tego chcę się dowiedzieć. Przez eliminację błędu w interfejsie. Taniej wyjdzie kupić np uwaloną Diode Shottky'ego niż DS1820.

Nie mam :|

Szukałem na ich WWW, nie znalazłem. Mogę o linkę prosić?

Tak, chociaż można jeszcze 3 podpiąć pod zewnętrzne +5V, tylko że wtedy inaczej wyglądają cykle rozkazowe.

znjaomy walczyl ostatnio kilka dni i okazalo sie ze sampel od maxima nie dzialal, kupil nowe i ruszylo..

probowales na innym egzemplarzu? takie dziwactwa tez obserwowalem na uszkodzonych

Wed, 01 Nov 2006 23:06:53 +0100, na pl.misc.elektronika, Paweł napisał(a):

formatting link

"Greg\(G.Kasprowicz\)" snipped-for-privacy@gmail.com pisze:

Chcieli mieæ uk³ady cyfrowe - to maj± ;-) Analogowy obczaili by ruskim woltomierzem.

Nie wiem, jak Wy, ale ja spotka³em ze dwa uszkodzone DS1820 a ich dok³adno¶æ pozostawia wiele do ¿yczenia - 10 czujników w³o¿onych do wspólnej komory klimatycznej pokazywa³y rozrzut +/- 1.5 stopnia.

U¿ytkownik "Patryk Sielski" snipped-for-privacy@elka-usun.pw.edu.pl> napisa³ w wiadomo¶ci news:42b4d$4549c3b2$57ceab2d$ snipped-for-privacy@news.chello.pl...

Tak to ju¿ jest jest. Nie mia³e¶ wiêkszych problemów, to kupile¶ komputer i ju¿ masz problem :-)

DS18B20 jest bardzo ³atwo uszkodziæ elektrostatycznie Niektóre serie s± nieudane, a mo¿e podrobione. Wykorzystanie go bez zasilania (2 druty) wymaga spe³nienia szeregu warunków, o których zwykle siê nie wie.

Przed chwila podlaczylem swiezo kupiony egzemplarz i to samo...opoznienie 9 us, zgloszenie ds 33 us..chociaz to juz o 1 us lepiej nic poprzednio... Aha, uklad chodzi na oddzielnym zasilaniu... Jak snieg przestanie padac to moze polece po jakiegos mosfeta i podlacze w trybie parasite power. Ma ktos inny pomysl? Jeden z ds z serii c3, drugi z serii c2, wiec raczej nie powinny byc felerne...

Pozdrawiam!

Ja mialem taki problem, ze po inicjalizacji szybko samplowal dane, katalogowo po ok. 15 us, u mnie bylo szybciej. Jesli masz AVR pod reka to moge ci podeslac wsad do obslugi 1-wire to sobie przetestujesz.

U¿ytkownik "Rufous" snipped-for-privacy@wp.pl napisa³ w wiadomo¶ci news:eff03$4549d46f$57ce8542$ snipped-for-privacy@news.chello.pl...

Jak tak jest to program obs³ugi DS18B20 masz do bani Je siê prosto obs³uguje, jak siê ju¿ raz ten program napisze Ciê¿ko jednak przy pierwszym podej¶ciu napisaæ go od razu dobrze Z zewnêtrznym zasilaniem one chodz± znacznie pewniej Pobieraj± ¶rednio, mniej wiêcej pó³ miliampera

U¿ytkownik "Rufous" snipped-for-privacy@wp.pl napisa³ w wiadomo¶ci news:eff03$4549d46f$57ce8542$ snipped-for-privacy@news.chello.pl...

Obstawiam, ze nie masz prawid³owo podawanych impulsów potrzebnych dla odbioru

U¿ytkownik "wrr" snipped-for-privacy@vp.pl napisa³ w wiadomo¶ci news:eid8gq$m7b$ snipped-for-privacy@news.onet.pl...

Hm...sprawa nie jest taka prosta :) Po kolei...daje znak reset (ustawiam stan niski na wejsciu ds) przez ponad

500 us. Pozniej ustawiam port do odczytu i czekam kolejne 500 us. Zrobilem to tak, zeby sprawdzic czy to dziala w ogole...no i podlaczylem do tego oscyloskop. Z odlaczonym ds na oscyloskopie pojawia sie sygnal prostokatny o wypelnieniu 1/2 i okresie 1000 us (500 us stan niski przez podanie 0 na linie wyjscia oraz 500 us stan wysoki przez ustawienie lini na obior...rezystor ciagnie sygnal w gore). Po podlaczeniu dsa sprawa wyglada tak
  1. jest sygnal niski przez 500 us (podanie 0 na wyjscie)
  2. po przelaczeniu linni wysoko, ustawienie na odbior

- jest 8 us wysoko

-33 us nisko (tak jakby ds odpowiedzial)

-no i dalej przez jakies 440 us stan wysoki

Dziwne jest to, ze niezalenie od czasu ustawienia stanu niskiego (od 100 us do 1 ms)ds zglasza sie tak samo (8 us - 33us). Nie wiem co o tym myslec...moze ten ds nie moze byc tak czesto resetowany (jest petla, ktora robi ten sygnal prostokatny 500/500, zeby na oscyloskopie mozna bylo obserwowac przebieg...) No, ale tez probowalem robic to bez petli, jak bedzie sygnal niski po 70 us od wlaczeniu linii na odbior to zapala sie dioda...nawet nie blysnela :) Wklejam kod...moze ktos cos zobaczy... (wzorowany na tym ze strony producenta)

bsf STATUS,RP0 bsf TRISA,2 ;ustawienie linii na we (stan wysoki) bcf STATUS,RP0

bcf PORTA,2 bsf STATUS,RP0 bcf TRISA,2 ;ustawienie linii na wy i podanie od razu stanu niskiego bcf STATUS,RP0

call czeka100u ;czekamy 500 us (sprawdzane na oscyloskopie, call czeka100u ;dokladnosc do 1 us) call czeka100u call czeka100u call czeka100u

bsf STATUS,RP0 bsf TRISA,2 ;ustawienie linii na we (stan wysoki) bcf STATUS,RP0

call czeka70u ;czekamy 70 us

btfss PORTA,2 ;przeskakuje nastepna procedure jak stan wysoki goto dziala ;tu byloby najlepiej nie dziala ;)

call czeka100u ;wg specyfikacji, zeby nie robic nic call czeka100u ;przez jakies 480 us od wystapienia stanu niskiego call czeka100u call czeka100u call czeka100u koniec

no i cos tutal byloby fajnie moc napisac :)

PS. Jeden cykl rozkazowy trwa u mnie ok 500 ns. Moze sa tam jakies za szybkie przeskoki...nie wiem sam...chociaz probowalem dodawac nop po kazdym rozkazie...

Pozdrawiam!!

U¿ytkownik "Rufous" snipped-for-privacy@wp.pl napisa³ w wiadomo¶ci news:d020b$454a3693$57ce8542$ snipped-for-privacy@news.chello.pl...

Czy nadajesz impulsy odbiorcze ? Do odbioru trzeba regularnie nadawaæ stan niski przez 1us i odbieraæ czy je DS wyd³u¿y, czy nie

U¿ytkownik "Rufous" snipped-for-privacy@wp.pl napisa³ w wiadomo¶ci news:d020b$454a3693$57ce8542$ snipped-for-privacy@news.chello.pl...

Sprawa jest banalna To jest Z£Y program dla PICa Nie doczyta³e¶ w informacji do DS jak siê odbiera W ogóle nie masz impulsów odbiorczych

Zapewne nigdy nie widziale¶ programu obs³ugi DS18B20 dla PIC To jest bardzo skomplikowane

Mo¿e to pomo¿e:

;; ;; $Id: ds18b20.asm,v 1.2 2004/08/11 10:41:50 james Exp james $ ;; ;; ds18b20.asm, a PIC 12C509 or 16F84 based DS18B20 translator ;; Copyright (C) 2005 James Cameron ( snipped-for-privacy@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

formatting link
or
formatting link
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 __12c509 base equ 0x07 ; first free file register address stack equ 0x1f+1 ; end address of stack port equ gpio ; port on which bits are used movwt macro ; move w to tris tris gpio endm bank0 macro ; select low bank for goto/call bcf status,pa0 endm bank1 macro ; select high bank for goto/call bsf status,pa0 endm endif

debug equ 0 ; set to one to enable calculation stack trace

;; port bit allocations

b_ow0 equ 0 ; one wire bus to first DS18B20 b_ow1 equ 1 ; one wire bus to second DS18B20 b_tx equ 2 ; serial output 2400 baud to host b_in equ 3 ; mode flag input b_ow2 equ 4 ; one wire bus to third DS18B20 b_ow3 equ 5 ; one wire bus to fourth DS18B20

;; r_trism extra allocations

b_noisy equ 6 ; display more data b_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 endm

pushw macro ; push from w to stack decf fsr,f movwf indf endm

popl macro ; pop literal (aka drop) from stack incf fsr,f endm

pushl macro m_literal ; push literal to stack movlw m_literal pushw endm

popf macro m_to ; pop to file addresss (uses w) popw movwf m_to endm

pushf macro m_from ; push from file address (uses w) movf m_from,w pushw endm

popf16 macro m_to ; pop 16-bit value popf m_to+1 popf m_to endm

pushf16 macro m_from ; push 16-bit value pushf m_from pushf m_from+1 endm

pushl16 macro m_literal ; push literal to stack pushl m_literal pushl 0 endm

popl16 macro ; pop literal (aka 2drop) popl popl endm

mov16 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 DS18B20 to talk to

; data read from device scratchpad r_ds_lsb ; temperature lsb r_ds_msb ; temperature msb r_ds_res ; remaining count after conversion 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.1" ; 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 sequence ow_command_convert equ 0x44 ; commence temperature conversion ow_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 0

ow_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 in

ow_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 counter

ow_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 us10

ow_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 tx_byte_loop_3 decfsz indf,f goto tx_byte_loop_3

movlw d'3' ; drop stack (timer, bit count, byte) addwf fsr,f retlw 0

;;; ;;; tx_header, transmit packet header, single byte followed by space ;;; ;;; input: none ;;; output: none ;;; stack: calls others that do not call ;;; data stack: ( byte -- ) [total 1] ;;; tx_header call tx_byte

;;; ;;; tx_space, send a single space ;;; ;;; input: none ;;; output: none ;;; stack: calls others that do not call ;;; data stack: ( -- ) [total 1] ;;; tx_space pushl 0x20 goto tx_byte

;;; ;;; tx_crlf, transmit carriage return line feed ;;; ;;; input: none ;;; output: none ;;; stack: calls others that do not call ;;; data stack: ( -- ) [total 1] ;;; tx_crlf pushl 0x0a call tx_byte pushl 0x0d goto tx_byte

;;; ;;; tx_put, macro for tx_byte_hex ;;; ;;; input: address of byte to send ;;; output: none ;;; stack: mainline macro ;;; tx_put macro m_byte pushf m_byte bank0 call tx_byte_hex endm

;;; ;;; arithmetic vector table ;;; (12c509 can't call into upper page of bank 0, 0x100 to 0x1ff) ;;; sb_bcd goto sb_bcd_ sb_bcd_fix goto sb_bcd_fix_ sb_add goto sb_add_ sb_subtract goto sb_subtract_ sb_abs goto sb_abs_ sb_negate goto sb_negate_ sb_nip goto sb_nip_ sb_over goto sb_over_ sb_multiply goto sb_multiply_ sb_divide goto sb_divide_

last0 equ sb_divide ; define the last call entry in page 0

;;; ;;; sb_bcd, convert accumulator to binary coded decimal for output ;;; ;;; data stack: ( lsb msb -- d0 d1 d2 ) [total 5] ;;; stack: calls others that do not call ;;; sb_bcd_ ;; ( lsb msb ) popf r_ephemeral ; msb popf r_temporary ; lsb movlw 0 pushw ; d0 (lsd) pushw ; d1 pushw ; d2 (msd) pushf r_temporary ; lsb pushf r_ephemeral ; msb pushl d'16' ; count

;; ( d0 d1 d2 msb lsb count ) bcf status,c

sb_bcd_loop incf fsr,f ; ( d0 d1 d2 lsb msb ^ count ) incf fsr,f ; ( d0 d1 d2 lsb ^ msb count ) rlf indf,f ; lsb decf fsr,f ; ( d0 d1 d2 lsb msb ^ count ) rlf indf,f ; msb incf fsr,f incf fsr,f incf fsr,f incf fsr,f ; ( d0 ^ d1 d2 lsb msb count ) rlf indf,f ; d0 (lsd) decf fsr,f ; ( d0 d1 ^ d2 lsb msb count ) rlf indf,f ; d1 decf fsr,f ; ( d0 d1 d2 ^ lsb msb count ) rlf indf,f ; d2 (msd)

movlw d'3' subwf fsr,f ; ( d0 d1 d2 lsb msb count )

decfsz indf,f ; count goto sb_bcd_adjust

movlw d'3' addwf fsr,f ; drop drop drop

;; ( d0 d1 d2 ) retlw 0

sb_bcd_adjust ;; ( d0 d1 d2 lsb msb count )

movlw d'3' addwf fsr,f ; ( d0 d1 d2 ^ lsb msb count )

call sb_bcd_fix ; d2 call sb_bcd_fix ; d1 call sb_bcd_fix ; d0 ; ( ^ d0 d1 d2 lsb msb count ) movlw d'6' subwf fsr,f ; ( d0 d1 d2 lsb msb count )

goto sb_bcd_loop

sb_bcd_fix_ movlw 3 addwf indf,w ; add 3 to low nibble movwf r_ephemeral ; test bits btfsc r_ephemeral,3 ; if bit three is set movwf indf ; store the adjusted value movlw 0x30 addwf indf,w ; add 3 to high nibble movwf r_ephemeral ; test bits btfsc r_ephemeral,7 ; if bit seven is set movwf indf ; store the adjusted value incf fsr,f ; move to next digit pair retlw 0

;;; ;;; sb_*, sixteen bit math functions ;;;

;;; ;;; sb_add, sixteen bit addition ;;; ;;; data stack: ( a b -- a+b ) [total 4] ;;; stack: none ;;; sb_add_ ; ( lsb1 msb1 lsb2 msb2 -- lsb3 msb3 ) movf indf,w ; msb2 incf fsr,f ; ( lsb1 msb1 lsb2 ^ msb2 ) incf fsr,f ; ( lsb1 msb1 ^ lsb2 msb2 ) addwf indf,f ; msb3 = msb1 + msb2 decf fsr,f ; ( lsb1 msb3 lsb2 ^ msb2 ) movf indf,w ; lsb2 incf fsr,f ; ( lsb1 msb3 ^ lsb2 msb2 ) incf fsr,f ; ( lsb1 ^ msb3 lsb2 msb2 ) addwf indf,f ; lsb3 = lsb1 + lsb2 decf fsr,f ; ( lsb3 msb3 ^ lsb2 msb2 ) btfsc status,c ; carry? incf indf,f ; msb3 retlw 0 ; ( lsb3 msb3 )

;;; ;;; sb_subtract, sixteen bit subtraction ;;; ;;; data stack: ( a b -- a-b ) [total 4] ;;; stack: none ;;; sb_subtract_ ; ( lsb1 msb1 lsb2 msb2 -- lsb3 msb3 ) movf indf,w ; msb2 incf fsr,f ; ( lsb1 msb1 lsb2 ^ msb2 ) incf fsr,f ; ( lsb1 msb1 ^ lsb2 msb2 ) subwf indf,f ; msb3 = msb1 - msb2 decf fsr,f ; ( lsb1 msb3 lsb2 ^ msb2 ) movf indf,w ; lsb2 incf fsr,f ; ( lsb1 msb3 ^ lsb2 msb2 ) incf fsr,f ; ( lsb1 ^ msb3 lsb2 msb2 ) subwf indf,f ; lsb3 = lsb1 - lsb2 decf fsr,f ; ( lsb3 msb3 ^ lsb2 msb2 ) btfss status,c ; underflow? decf indf,f ; msb3 retlw 0

;;; ;;; sb_abs, sixteen bit absolute value ;;; ;;; data stack: ( a -- |a| ) [total 2] ;;; stack: none ;;; sb_abs_ btfss indf,7 ; is it negative? retlw 0 ; no, so return ; fall through to negate

;;; ;;; sb_negate, sixteen bit negate ;;; ;;; data stack: ( a -- 0-a ) [total 2] ;;; stack: none ;;; sb_negate_ ; ( lsb msb -- lsb msb ) incf fsr,f ; ( lsb ^ msb ) comf indf,f ; lsb incf indf,f ; lsb decfsz fsr,f ; ( lsb msb ^ ) nop ; [decrement without losing z] btfsc status,z decf indf,f ; msb comf indf,f ; msb retlw 0 ; ( lsb msb )

;;; ;;; sb_nip, sixteen bit nip, remove item under current item ;;; ;;; data stack: ( a b -- b ) [total 4] ;;; stack: none ;;; sb_nip_ ; ( a b c d -- c d ) movf indf,w ; d @ incf fsr,f ; ->c incf fsr,f ; ->b movwf indf ; b ! decf fsr,f ; ->c movf indf,w ; c @ incf fsr,f ; ->b incf fsr,f ; ->a movwf indf ; a ! decf fsr,f ; ->b retlw 0

;;; ;;; sb_over, sixteen bit over, copy item under current item ;;; ;;; data stack: ( a b -- a b a ) [total 6] ;;; stack: none ;;; sb_over_ ; ( a b c d -- a b c d a b ) incf fsr,f ; ( a b c ^ d ) incf fsr,f ; ( a b ^ c d ) incf fsr,f ; ( a ^ b c d ) movf indf,w ; a decf fsr,f ; ( a b ^ c d ) decf fsr,f ; ( a b c ^ d ) decf fsr,f ; ( a b c d ^ ) decf fsr,f ; ( a b c d ? ^ ) movwf indf ; a incf fsr,f ; ( a b c d ^ a ) incf fsr,f ; ( a b c ^ d a ) incf fsr,f ; ( a b ^ c d a ) movf indf,w ; b decf fsr,f ; ( a b c ^ d a ) decf fsr,f ; ( a b c d ^ a ) decf fsr,f ; ( a b c d a ^ ) decf fsr,f ; ( a b c d a ? ^ ) movwf indf ; b retlw 0

;;; ;;; sb_multiply, sixteen bit multiply ;;; ;;; data stack: ( multiplicand multiplier -- product ) [total 7] ;;; stack: calls others that do not call ;;; sb_multiply_ ; ( al ah bl bh -- cl ch ) pushl16 d'0' ; clear product ;; ( al ah bl bh cl ch )

pushl d'16' ; count of bits to process ;; ( al ah bl bh cl ch count )

sb_multiply_loop ; for each bit ;; ( al ah bl bh cl ch count )

;; shift multiplier down by one movlw 5 addwf fsr,f ; ->ah rrf indf,f incf fsr,f ; ->al rrf indf,f decf fsr,f ; ->ah decf fsr,f ; ->bl

;; ( al ah bl ^ bh cl ch count ) ;; if the bit is set ... btfss status,c goto sb_multiply_skip

;; add the multiplicand to the product decf fsr,f ; ->bh movf indf,w decf fsr,f ; ->cl decf fsr,f ; ->ch addwf indf,f movlw 3 addwf fsr,f ; ->bl movf indf,w decf fsr,f ; ->bh decf fsr,f ; ->cl addwf indf,f decf fsr,f ; ->ch btfsc status,c incf indf,f movlw 3 addwf fsr,f ; ->bl

sb_multiply_skip ;; ( al ah bl ^ bh cl ch count ) ;; shift up multiplicand bcf status,c rlf indf,f decf fsr,f ; ->bh rlf indf,f

;; ( al ah bl bh ^ cl ch count ) ;; and loop for remainder of bits movlw 3 subwf fsr,f ; ->count decfsz indf,f goto sb_multiply_loop

;; ( al ah bl bh cl ch count ) popl ; count call sb_nip ; bl bh goto sb_nip ; al ah

;;; ;;; sb_divide, sixteen bit divide ;;; ;;; data stack: ( numerator denominator -- remainder quotient ) [total 10] ;;; stack: calls others that do not call ;;; sb_divide_ ; ;; ( nl nh dl dh -- rl rh ql qh )

;; prepare stack for results ;; ( nl nh dl dh ) call sb_over ;; ( nl nh dl dh nl nh ) call sb_over ;; ( nl nh dl dh nl nh dl dh ) ;; ( rl rh ql qh nl nh dl dh ) movlw d'4' addwf fsr,f ; ->qh clrf indf ; qh incf fsr,f ; ->ql clrf indf ; ql incf fsr,f ; ->rh clrf indf ; rh incf fsr,f ; ->rl clrf indf ; rl movlw d'7' subwf fsr,f ; ->dh ;; ( rl rh ql qh nl nh dl dh )

;; save effective sign difference ;; sign = xor(nh,dh) ;; ( nl nh dl dh ) movf indf,w ; dh incf fsr,f ; incf fsr,f ; ->nh xorwf indf,w ; nh decf fsr,f ; decf fsr,f ; ->dh pushw ;; ( nl nh dl dh sign )

;; force arguments to positive ;; n = abs (n) ;; ( nl nh dl dh sign ) movlw d'3' addwf fsr,f ; ->nh call sb_abs decf fsr,f ; ->dl decf fsr,f ; ->dh

;; d = abs (d) ;; ( nl nh dl dh ^ sign ) call sb_abs decf fsr,f ; ->sign

;; set the bit counter pushl d'16' ; for 16 shifts ;; ( nl nh dl dh sign count )

;; ( rl rh ql qh nl nh dl dh sign count )

sb_divide_loop ;; ( rl rh ql qh nl nh dl dh sign count )

;; shift bits left from numerator to remainder movlw d'5' addwf fsr,f ; ->nl bcf status,c ; clear status.c rlf indf,f ; nl decf fsr,f ; ->nh rlf indf,f ; nh incf fsr,f ; (must keep status.c) incf fsr,f ; incf fsr,f ; incf fsr,f ; incf fsr,f ; ->rl rlf indf,f ; rl decf fsr,f ; ->rh rlf indf,f ; rh ;; ( rl rh ^ ql qh nl nh dl dh sign count )

;; check if remainder is greater than denominator movlw d'6' subwf fsr,f ; ->dh movf indf,w ; dh movwf r_ephemeral movlw d'6' addwf fsr,f ; ->rh movf r_ephemeral,w subwf indf,w ; rh btfss status,z goto sb_divide_skip_1 ;; ( rl rh ^ ql qh nl nh dl dh sign count )

;; msb equal, so check lsb movlw d'5' subwf fsr,f ; ->dl movf indf,w ; dl movwf r_ephemeral movlw d'6' addwf fsr,f ; ->rl movf r_ephemeral,w subwf indf,w ; rl decf fsr,f ; ->rh ;; ( rl rh ^ ql qh nl nh dl dh sign count )

sb_divide_skip_1 btfss status,c goto sb_divide_skip_2 ; remainder is less ;; ( rl rh ^ ql qh nl nh dl dh sign count )

;; carry set, remainder is greater than denominator ;; subtract denominator from remainder and save in remainder movlw d'5' subwf fsr,f ; ->dl movf indf,w ; dl movwf r_ephemeral movlw d'6' addwf fsr,f ; ->rl movf r_ephemeral,w subwf indf,f ; rl decf fsr,f ; ->rh btfss status,c decf indf,f ; rh

movlw d'6' subwf fsr,f ; ->dh movf indf,w ; dh movwf r_ephemeral movlw d'6' addwf fsr,f ; ->rh movf r_ephemeral,w subwf indf,f ; rh

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 notdef noisy ;; 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_done

noisy_skip

noisy_done endif

;; say g'day gday pushl 'R' ; reset bank0 call tx_header

pushl 0 ; start at beginning of table gday_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_loop gday_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 here loop

;; 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 absent

present 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?

;; ds18b20 specification says 750ms maximum for 12-bit resolution busy 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 sensor ow_get macro m_byte ; get byte to address ;; bank0 call ow_rx popf m_byte endm

;; per spec, page 7 ow_get r_ds_lsb ow_get r_ds_msb ow_get r_ds_res ; ignore low alarm byte ow_get r_ds_res ; ignore high alarm byte ow_get r_ds_res ; ignore configuration register ow_get r_ds_res ; ignore reserved byte 5 ow_get r_ds_res ; ignore reserved byte 6 ow_get r_ds_res ; ignore reserved byte 7 ow_get r_ds_crc

;; ??? check the crc some day!

;; in verbose mode, dump the data in hex 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_crc call tx_space data_skip

;; move temperature as read to stack pushf16 r_ds_lsb

;; if fahrenheit is requested bank1 btfss r_trism,b_fahre ; if bit zero, degrees C goto fahrenheit_skip1 ; so skip this

;; convert the raw scaled value to raw scaled fahrenheit less 32 degree offset 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

fahrenheit_skip1

;; we get the measurement in integer degrees, scaled down by ;; four bits (16), but we want the value scaled by 100 instead.

;; so we should multiply by 100 and divide by 16 to get the ;; result we want, but that would cause overflow of 16-bits at ;; relatively low temperatures, so we multiply by 25 and divide ;; by 4 instead.

bank0 pushl16 d'25' call sb_multiply pushl16 d'4' call sb_divide call sb_nip ; drop remainder

;; we now have the measurement in degrees, scaled by 100, such ;; that 23.54 degrees is binary value for decimal 2354

;; if fahrenheit is requested bank1 btfss r_trism,b_fahre ; if bit zero, degrees C goto fahrenheit_skip2 ; yes, skip it

;; complete the conversion by adding the offset bank0 pushl d'128' ; add thirty two (3200 decimal) pushl d'12' call sb_add

fahrenheit_skip2

;; 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_negate

skip

;; convert value to bcd bank0 call sb_bcd

;; 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 loop

last2 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

W wiadomości od wrr odebranej 2006-11-02 11:34 mogłem przeczytać:

<ciach>

Tzn jakich?

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required