Jump to content
43oh

Dallas/Maxim One Wire Library


Recommended Posts

Here is a basic library for 1-wire communication. It works with CPU frequency of 1 MHz or higher. Carefully crafted assembly code is used to allow operation over a wide CPU clock frequency range.

 

There are only two functions. One for setup and the other for all communication tasks.

 

// one_wire.h
void one_wire_setup(volatile unsigned char *dir, volatile unsigned char *in, unsigned bitmask, unsigned mhz);
int owex(int data, unsigned bits);

 

The library is initialized by a call to one_wire_setup(). The arguments specify the I/O pin and clock frequency.

An example for P1.4 at 16 MHz...

 

one_wire_setup(&P1DIR, &P1IN, 0x10, 16);

 

The setup function can be called repeatedly to allow communication on more than one I/O pin.

 

The owex() [One Wire EXchange] function does bus reset, tx and rx.

 

To reset the bus and detect if any devices are present, just call it with a bit count of zero....

 

p = owex(0, 0);

 

The returned value will be -1 (0xFFFF) if any devices are detected, or 0 if none are detected.

 

To send data...

 

owex(0xCC, 8); // Skip ROM command

 

The returned value should match the data sent, if it does not then there is a bus problem.

 

To receive data, use -1 (0xFFFF) for the tx data value...

 

d = owex(-1, 8); // Get 8 bits

 

1 to 16 bits can be sent/received at once.

 

This is the core code...

       .def    owex                    ; int owex(int data, unsigned bit_count)
       .def    owdport
       .def    owiport
       .def    owbit
       .def    owtiming

       .bss    owdport, 2              ; Direction port
       .bss    owiport, 2              ; Input port
       .bss    owbit, 2                ; Port bitmask
       .bss    owtiming, 0             ; Timing array
       .bss    owda, 2                 ; 28  Zero
       .bss    owdb, 2                 ; 33
       .bss    owdc, 2                 ; 39
       .bss    owdd, 2                 ; 7   One
       .bss    owde, 2                 ; 8
       .bss    owdf, 2                 ; 85
       .bss    owdg, 2                 ; 500 Reset
       .bss    owdh, 2                 ; 50
       .bss    owdi, 2                 ; 450

owex                                    ;
       tst     R13                     ; Reset?
       jeq     owrst                   ; Yes...
       push    R11                     ; Save R11, R13
       push    R13                     ;
       clr     R13                     ; Clear bit count
                                       ;
owloop                                  ; --- Tx/Rx bit loop
       rra     R12                     ; Get tx bit
       jc      owone                   ; If one...
                                       ;
                                       ; - Send and verify zero
       mov     &owda, R15              ;
       nop                             ;
       mov     &owdport, R14           ; Bus low
       bis.b   &owbit, 0(R14)          ;
                                       ;
       call    #owdelay                ; Delay 28 us
                                       ;
       mov     &owiport, R14           ; Sample bus
       mov.b   @R14, R14               ;
       bit     &owbit, R14             ;
       rrc     R11                     ;
                                       ;
       mov     &owdb, R15              ; Delay 33 us
       call    #owdelay                ;
                                       ;       
       mov     &owdc, R15              ;
       mov     &owdport, R14           ; Bus open 
       bic.b   &owbit, 0(R14)          ;
                                       ;
       jmp     ownext                  ; Delay 39 us
                                       ;       
owone                                   ; - Send one and read bit
       mov     &owdd, R15              ;
       tst     R15                     ;
       mov     &owdport, R14           ; Bus low
       bis.b   &owbit, 0(R14)          ;
                                       ;
       jn      owoneo                  ; Delay 7 us                                        
owdlyd                                  ;                                       
       sub     #8, R15                 ;
       nop                             ;
       jc      owdlyd                  ;
       subc    R15, PC                 ;
       nop                             ;
       nop                             ;
       nop                             ;
owoneo                                  ;       
       bic.b   &owbit, 0(R14)          ; Bus open
                                       ;
       jc      owones                  ; Delay 8 us                                        
       mov     &owde, R15              ;
owdlye                                  ;       
       sub     #8, R15                 ;
       nop                             ;
       jc      owdlye                  ;
       subc    R15, PC                 ;
       nop                             ;
       nop                             ;
       nop                             ;
owones                                  ;       
       mov     &owiport, R14           ; Sample bus
       mov.b   @R14, R14               ;
       bit     &owbit, R14             ;
       rrc     R11                     ;
                                       ;
       mov     &owdf, R15              ; Delay 85 us
ownext                                  ;
       call    #owdelay                ;
                                       ; - Next bit
       inc     R13                     ; Increment bit count
       cmp     R13, 0(SP)              ; Compare bit count
       jne     owloop                  ; Loop if not done...
owrxa                                   ; - Align rx data
       cmp     #16, R13                ; Rx data aligned?
       jeq     owrex                   ; Yes..
       rra     R11                     ; Shift in a zero bit
       inc     R13                     ; Inc bit count
       jmp     owrxa                   ; Next bit...       
owrex                                   ;       
       mov     R11, R12                ; Get rx data to R12
       pop     R13                     ; Restore R11, R13
       pop     R11                     ;
       ret                             ; Return                                        
                                       ;
                                       ;
owrst                                   ; - Reset and presence detect
       mov     &owdport, R14           ; Bus low
       bis.b   &owbit, 0(R14)          ;
                                       ;
       mov     &owdg, R15              ; Delay 500 us
       call    #owdelay                ;
                                       ;       
       bic.b   &owbit, 0(R14)          ; Bus open
                                       ;
       mov     &owdh, R15              ; Delay 50 us
       call    #owdelay                ;
                                       ;       
       mov     &owiport, R14           ; Sample bus
       mov.b   @R14, R14               ;
       bit     &owbit, R14             ;
       subc    R12, R12                ;
                                       ;
       mov     &owdi, R15              ; Delay 450 us
       ;jmp    owdelay                 ;  and return
                                       ;
owdelay                                 ;
       sub     #8, R15                 ;
       nop                             ;
       jc      owdelay                 ;
       subc    R15, PC                 ;
       nop                             ;
       nop                             ;
       nop                             ;
       ret                             ;
                                       ;
       .end                            ;

 

Demo program to read DS1820/1822 temperature sensor is included in zip file.

one_wire.zip

Link to post
Share on other sites
  • Replies 31
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

Here is a basic library for 1-wire communication. It works with CPU frequency of 1 MHz or higher. Carefully crafted assembly code is used to allow operation over a wide CPU clock frequency range.  

Thanks to pointers from Rickta59 here's code tuned to work in msp430-gcc. I've used it in my project to read temperature from DS sensor and it works correctly. dow.zip

Hi oPossum (Kevin?),   Combining read/write bit "slot" functions is incredibly insightful. Bravo! After looking at the separate read and write routines on an old DS18B20 + PIC 10F200 project, comb

Posted Images

May I ask how to make a project out of those pieces, please?

 

I created a project called "OneWire" and I copied the files from the zip file into the OneWire workspace folder but there doesn't appear to be a file for the "core" routines. Just not sure how you make a project with more than just a single main.c file.

 

Sorry for the dumb question...

 

Regards, Mike

Link to post
Share on other sites

Hi oPossum (Kevin?),

 

Combining read/write bit "slot" functions is incredibly insightful. Bravo! After looking at the separate read and write routines on an old DS18B20 + PIC 10F200 project, combining the routines seemed embarrassingly obvious (lol). Anyway, I can't wait to try it out. Combining the routines saves eight (8) words of program memory which is pretty significant on a 10F200 with only 255 words of program memory (lol). Since you're a PIC guy too, I thought you might appreciate seeing the (untested) results;

 

Thank you!!! Regards, Mike

 

;
;  Ow.rwByte, send byte in WREG. send 0b11111111 to read a byte 
;  with read result in 'OwByte'.
;                                 Mike McLaren, K8LH
       radix   dec
Ow.rwByte
       movwf   OwByte          ; 
       movlw   8               ;
       movwf   BitCtr          ;
       rrf     OwByte,W        ; put b0 in Carry
rwloop  call    Ow.rwBit        ;
       rrf     OwByte,F        ;
       decfsz  BitCtr,F        ; done (all 8 bits)?
       goto    rwloop          ; no, loop, else
       retlw   0               ; exit
;
;  Ow.rwBit (4..32 MHz clock), input = carry ('1' to read 
;  a bit). 'read' bit result in carry.
;
       radix   dec
Ow.rwBit
       movlw   MaskLo          ; start 60 us rw slot
       tris    GPIO            ; falling edge             0 us
       goto    $+1             ;
       goto    $+1             ;
       skpnc                   ; skip if bit = '0', else
       movlw   MaskHi          ; mask to release buss
       tris    GPIO            ; low pulse is 1..8 us
       uDlyCy (14*usecs-8)     ; 14 us minus 8 cycles
       btfss   owpin           ; sample owpin at exactly 14 us
       clrc                    ; clear Carry if '0'
       uDlyCy (47*usecs-3)     ; balance of 60 us slot
       movlw   MaskHi          ; mask to release buss
       tris    GPIO            ; read/write slot ends at 61 us
       retlw   rombuffer       ; for search rom routine
;

Link to post
Share on other sites

Here is updated one wire code that is a bit smaller. More code is shared between the zero and one tx/rx. I have also added four functions for byte/word read/write, and an export for the bus reset so it can be called directly.

 

Core asm code...

owww                                    ; - Write word
       mov     #16, R13                ;
       jmp     owdx                    ;                               
owrw                                    ; - Read word
       mov     #-1, R12                ;
       mov     #16, R13                ;
       jmp     owdx                    ;
owwb                                    ; - Write byte
       mov     #8, R13                 ;
       jmp     owdx                    ;
owrb                                    ; - Read byte
       mov     #-1, R12                ;
       mov     #8, R13                 ;
       ;jmp    owdx                    ;
owex                                    ; - Exchange / Reset
       tst     R13                     ; Reset?
       jeq     owrst                   ; Yes...
owdx                                    ;       
       push    R11                     ; Save R11, R13
       push    R13                     ;
       clr     R13                     ; Clear bit count
                                       ;
owloop                                  ; --- Tx/Rx bit loop
       mov     &owdport, R14           ;
       rra     R12                     ; Get tx bit
       jc      owone                   ; If one...
                                       ;
                                       ; - Send and verify zero
       mov     &owda, R15              ;
       nop                             ;
       bis.b   &owbit, 0(R14)          ; Bus low
                                       ;
       jmp     owdlyc                  ; Delay 15 us...                                        
                                       ;
                                       ;       
owone                                   ; - Send one and read bit
       mov     &owdb, R15              ;
       tst     R15                     ;
       bis.b   &owbit, 0(R14)          ; Bus low
                                       ;
       jn      owoneo                  ; Delay 7 us                                        
owdlyb                                  ;                                       
       sub     #8, R15                 ;
       nop                             ;
       jc      owdlyb                  ;
       subc    R15, PC                 ;
       nop                             ;
       nop                             ;
       nop                             ;
owoneo                                  ;       
       bic.b   &owbit, 0(R14)          ; Bus open
                                       ;
       jc      ows                     ; Delay 8 us                                        
       mov     &owdc, R15              ;
owdlyc                                  ;       
       sub     #8, R15                 ;
       nop                             ;
       jc      owdlyc                  ;
       subc    R15, PC                 ;
       nop                             ;
       nop                             ;
       nop                             ;
ows                                     ;       
       mov     &owiport, R14           ; Sample bus
       mov.b   @R14, R14               ;
       bit     &owbit, R14             ;
       rrc     R11                     ;
                                       ;
       mov     &owdd, R15              ; Delay 48 us
       call    #owdelay                ;
                                       ;       
       mov     &owde, R15              ;
       mov     &owdport, R14           ; Bus open 
       bic.b   &owbit, 0(R14)          ;
                                       ;
       call    #owdelay                ; Delay 37 us
                                       ;
                                       ; - Next bit
       inc     R13                     ; Increment bit count
       cmp     R13, 0(SP)              ; Compare bit count
       jne     owloop                  ; Loop if not done...
owrxa                                   ; - Align rx data
       cmp     #16, R13                ; Rx data aligned?
       jeq     owrex                   ; Yes..
       rra     R11                     ; Shift in a zero bit
       inc     R13                     ; Inc bit count
       jmp     owrxa                   ; Next bit...       
owrex                                   ;       
       mov     R11, R12                ; Put rx data in R12
       pop     R13                     ; Restore R11, R13
       pop     R11                     ;
       ret                             ; Return                                        

 

Attachment has complete asm and C code.

one_wire_new.zip

Link to post
Share on other sites

Block read with CRC.

 

Return will be zero if CRC is valid, or non-zero for invalid CRC. Length includes CRC.

 


unsigned read_block(unsigned char *d, unsigned len)
{
   unsigned crc = 0;
   unsigned n;
   for(; {
       crc ^= *d++ = owrb();
       if(!--len) break;
       n = 8; do crc = (crc & 1) ? ((crc >> 1) ^ 0x8C) : (crc >> 1); while(--n);
   }
   return crc;
}

Link to post
Share on other sites

Wow! Very similar to some of my old code;

 

;
;  Mike McLaren's Dallas one-wire 8-bit CRC code for the DS18B20
;
;  clear the CRC variable then run each byte from the scratchpad
;  read or ROM read operation through the CRC_Calc subroutine. A
;  final CRC value of '0' indicates "good data".
;
;    void CRC_Calc ()
;    { crc ^= owByte;
;      for (i = 0; i < 8; i++)
;      { if (crc & 1)
;          crc = (crc >> 1) ^ 0x8C;
;        else
;          crc =  crc >> 1;
;      }
;    }
;
;  entry: owByte contains data byte
;   exit: CRC contains cumulative CRC data
;
CRC_Calc
       movlw   d'8'            ;                                 |B0
       movwf   BitCtr          ; setup bit counter               |B0
       movf    owByte,W        ;                                 |B0
       xorwf   CRC,F           ;                                 |B0
       movlw   h'8C'           ; W = x8+x5+x4+1 polynomial       |B0
CRC_Next
       clrc                    ;                                 |B0
       rrf     CRC,F           ;                                 |B0
       skpnc                   ;                                 |B0
       xorwf   CRC,F           ; toggle b7, b3, and b2 bits      |B0
       decfsz  BitCtr,F        ; all done? yes, skip, else       |B0
       goto    CRC_Next        ; process the next IOByte bit     |B0
       return                  ;                                 |B0
;

Could I impose on you to explain this line in your code, please? The crc ^= *d++ part makes sense but not the rest, unless... is owrb() a OneWire read byte function? Yes, that's it. I see owrb() in the previous post. Sorry!

 

      crc ^= *d++ = owrb();

Link to post
Share on other sites

Do you have any equally exciting new insights on OneWire search rom code? It's a rather messy algorithm that cost me about 50 words when I implemented it on that old PIC10F200 project (please forgive me for posting more PIC code guys);

 

        clrf    LastDiscrep     ; init Last Discrepency var'
OwSearchNext
       clrf    BitIndex        ; BitIndex = 0
       clrf    LastZero        ; LastZero = 0
       movlw   b'00000001'     ;
       movwf   BitMask         ; setup rom array bit mask
       OwReset                 ; reset all 1-wire devices
       OwWrite(OwSearchRom)    ; send "search rom" command
;       movlw   RomBuffer       ; OwWrite() returns W = &RomBuffer
       movwf   FSR             ; FSR = &RomBuffer (0x10)
GetBits
       OwReadBit               ; read bit A
       rlf     OwTemp,F        ; F = -------A
       OwReadBit               ; read bit B (compliment)
       rlf     OwTemp,W        ; W = ------AB
       rrf     OwTemp,F        ; put 'A' bit back into Carry
       andlw   0x03            ; filter out unused bits
       xorlw   0x03            ; AB == 11, no response?
       bz      Restart         ; yes, branch (restart), else
       xorlw   0x03            ; AB == 00, a discrepency?
       bnz     SendRomBit      ; no, branch, use 'A' bit, else
Discrepency
       movf    BitIndex,W      ; 0..63
       subwf   LastDiscrep,W   ; 0..63
       bnc     IndexGTLD       ; index > last discrepency, use '0'
       bz      SendRomBit      ; index = last discrepency, use '1'
IndexLTLD                       ; index < last discrepency, use ROM
       movf    BitMask,W       ; get ROM bit
       andwf   INDF,W          ; is ROM bit '0'?
       bnz     SendRomBit      ; no, branch with C = 1, else
       clrc                    ; set C = 0 and
IndexGTLD
       movf    BitIndex,W      ; update 'LastZero'
       movwf   LastZero        ;
SendRomBit
       movf    BitMask,W       ; set ROM bit to value in Carry
       iorwf   INDF,F          ; set ROM bit (unconditionally)
       skpc                    ; is bit a '1'? yes, skip, else
       xorwf   INDF,F          ; clr ROM bit
       OwSendCarry             ; send direction/qualifier bit
       rlf     BitMask,W       ; 
       rlf     BitMask,F       ; advance the bit mask
       skpnc                   ; byte boundary? no, skip, else
       incf    FSR,F           ; bump RomBuffer array address
       incf    BitIndex,F      ; bump bit index, 0..63
       btfss   BitIndex,6      ; BitIndex = 64?  yes, skip, else
       goto    GetBits         ; do next bit
       movf    LastZero,W      ; update last discrepency
       movwf   LastDiscrep     ; a 0 indicates last DS18B20
;

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...