Shop OBEX P1 Docs P2 Docs Learn Events
Help with serial interface DS1302 — Parallax Forums

Help with serial interface DS1302

JonathanLJonathanL Posts: 3
edited 2005-01-18 20:45 in General Discussion
Hi all,

I am having a lot of problems communicating with the DS1302 timekeeping chip. I have checked and rechecked everything to no avail, I cannot seem to get anything out of the chip (and maybe to it?). I verified my logic signals with a scope but I only have one probe at this time so I can't confirm clock timing for sure, but I am pretty sure it should be okay.
Below is a copy of my program, I'm new to assembly programming and this is my first one so sorry if it's strange or stupid, etc. What I am trying to do is clear the write protect register, write a value to the seconds register and then read that value back.

What I get is either nothing or just '1' in BYTE_INPUT, and I disconnected the chip from the SX and still got the 1 so I don't know where that comes from. If anyone can help me out, take a look at the program, etc. I would greatly appreciate it. The datasheet for the DS1302 can be found here: http://pdfserv.maxim-ic.com/en/ds/DS1302.pdf

Thanks for any time and help!!

Code:



;-------------------------- DEVICE DIRECTIVES --------------------------

        DEVICE        SX28,OSCHS3
        DEVICE        TURBO,STACKX,OPTIONX
        IRC_CAL        IRC_SLOW
        RESET        Initialize

;------------------------------ VARIABLES AND CONSTANTS ----------------
            
        ; General purpose temporary registers
        ; Used in timing loops and temporary storage where the W
        ; register is inappropriate.

        temp1    EQU    $08    
        temp2    EQU    $09    
        temp3    EQU    $0A

        ; Pins for general purpose serially-clocked communication

        PIN_CLOCK    =    0    ; clock pin
        PIN_IO        =    0    ; input/output pin

        BYTE_INPUT    EQU    $0B
        BYTE_OUTPUT    EQU    $0C

        ; DS timekeeping chip pin defintions

        DS_CLK    EQU    rc.2    ;pin 2 of port c, DS clock pin
        DS_IO    EQU    rc.1    ;pin 1 of port c, DS I/O pin
        DS_RST    EQU    rc.0    ;pin 0 of port c, DS reset (RST) pin.

        ; DS register address definitions (commands)
        ; start with seconds at 100000000 (0x80) and increment
        ; these are write addresses, to read add one, ex: seconds = 81h

        DS_REG_SECONDS    =    $80
        DS_REG_MINUTES    =    $82
        DS_REG_HOURS    =    $84
        DS_REG_DATE    =    $86
        DS_REG_MONTH    =    $88
        DS_REG_DAY    =    $8A
        DS_REG_YEAR    =    $8C
        DS_REG_CONTROL    =    $8E
        DS_REG_CHARGE    =    $90
        DS_REG_BURST    =    $BE    

;---------------------------- DEBUG SETTINGS ---------------------------

        FREQ     400_000
        WATCH    BYTE_INPUT,8,UBIN
        ;WATCH    temp3,8,UBIN
        ;WATCH    RC.1,8,UDEC

;------------------------ INITIALIZATION ROUTINE -----------------------

Initialize
        ;Configure port settings
        mov    rc, #%00000000        ;Port C output low
        mov    !rc,#%00000000        ;Port c output direction (all pins)
        clr BYTE_INPUT
        
        

;---------------------------- MAIN PROGRAM -----------------------------

Main        


        PIN_CLOCK = DS_CLK
        PIN_IO = DS_IO

        ;clear write protect register

        setb DS_RST
        mov BYTE_OUTPUT,#DS_REG_CONTROL
        call ByteOut
        mov BYTE_OUTPUT,#%00000000
        call ByteOut
        clrb DS_RST
        
        nop

        ;set seconds

        setb DS_RST
        mov BYTE_OUTPUT,#DS_REG_DATE
        call ByteOut
        mov BYTE_OUTPUT,#%00001100
        call ByteOut
        clrb DS_RST

        nop

        ;read seconds

        mov !rc,#%0000010   ; input redirection
        
        setb DS_RST         ; set device select
        mov BYTE_OUTPUT,#DS_REG_DATE + 1
        call ByteOut
        call ByteIn
        clrb DS_RST
        
;;;; SUB: ByteIn    
;;;; Clocks in a byte by generating clock on PIN_CLOCK and reading clocked pin on PIN_IO and
;;;; placing it in BYTE_INPUT. Data is valid on falling clock edge.
;;;; Setup: 
;;;; PIN_IO     Valid port pin representing serial device IO (must be set input on tristates)
;;;; PIN_CLOCK     Valid port pin representing serial device clock
;;;; BYTE_INPUT  Input byte storage

ByteIn         mov temp1,#9            ; setup counter for 9 (8 bits/byte jmp if not zero
:Nextbit    djnz temp1,:Clockbit           ; have we clocked in a full bit?
        mov temp1,#9                ; if we have, reset the counter for the next byte read
        ret                              ; if there is one, and return                
:Clockbit   setb PIN_CLOCK            ; set the clock high: 5V:70ns / 2.0V:280ns clk-data-hld
        clrb PIN_CLOCK                  ; put the clock low
        movb BYTE_INPUT.0,PIN_IO     ; put the bit in the byte
        rl BYTE_INPUT                   ; rotate the byte to the left
        jmp :Nextbit                     ; jump to the next bit in the byte
        
;;;; SUB: ByteOut    
;;;; Puts the register byte BYTE_OUTPUT onto the pin PIN_IO bit by bit, producing a rising edge
;;;; valid clock on PIN_CLOCK for each bit. Must be ran via a call statement.
;;;; Setup: 
;;;; PIN_IO     Valid port pin representing serial device IO (must be set to output on tristates)
;;;; PIN_CLOCK     Valid port pin representing serial device clock
;;;; BYTE_OUTPUT Byte to be clocked out
        
ByteOut       mov temp1,#9                          ; setup counter with 9 (8 bits/byte jmp if not zero)                        
        mov temp2,BYTE_OUTPUT        ; save the byte output in case it was needed by caller
:Nextbit    djnz temp1,:Clockbit             ; do we have more bits to clock out?
        mov temp1,#9                     ; if we don't reset the counter for the next byte
        mov BYTE_OUTPUT,temp2         ; Put the byte back in case the caller needs it 
        ret                                   ; if there is one, and return
:Clockbit   movb PIN_IO,BYTE_OUTPUT.0       ; put the LSB of the output byte to the output pin
        setb PIN_CLOCK                     ; put the clock high
        clrb PIN_CLOCK                      ; put the clock low    
        rr BYTE_OUTPUT                     ; rotate the byte to the right to get the next bit
        jmp :Nextbit                          ; jump to the next bit in the byte (if there is one)

Comments

  • JonathanLJonathanL Posts: 3
    edited 2005-01-18 01:44
    Anyone have any ideas? I'm really going out of my mind on what should have been a simple part of this project. Worse yet, the DS1302 times out after 50ms after the last clock transisition, so I really can't debug it step by step.

    It's just a simple clockin/clockout routine, anyone spots any obvious errors?

    Thanks,

    Jon
  • PJMontyPJMonty Posts: 983
    edited 2005-01-18 07:30
    Jon,

    I confess I skimmed your code (so this may be dumb), but I have a question. Are you using the pull up resistors on the SX as the sole means of providing pull up to the device you're interfacing to, or does the device have active outputs that actually drive the SX inputs?
      Thanks, PeterM
  • JonathanLJonathanL Posts: 3
    edited 2005-01-18 09:55
    The device directly drives the SX inputs as far as I know so no pull ups are required. Anyway I found the error in my code that was preventing me from receiving data from the device (sending bytes was always okay); I failed to specify the port direction as input on the one I/O pin during a read cycle -- the one statement·was before the command byte·to send (which may have never even be sent at all), moving it down after the command byte was sent·fixed the problem.

    There were additional errors I fixed once I was actually communicating with the device regarding handling of the bits in the read byte routine. The RR instruction likes to move the carry flag around once you get to the last bit, so I had to add an extra jump if equal to stop the rotate on the last bit and manually specify move the value of the IO pin into the last bit of the byte.

    Everything is working okay now, I can read all values and set them, and read to/from the extra RAM on the device, so no pull ups are required I assume (?). I have found the clock works up to about 4 MHz SX·speed at 5V·without having to insert delay loops. At 3V it works up to 1 MHz.

    I will be posting up the completed code once I finish it for communicating with the clock (get/set time,·read/write ram)·in case anyone needs it. It may not be pretty or "best·pratice", but I only received the SX in the mail last week and have never before done any other assembly programming. Fun stuff!

    Post Edited (JonathanL) : 1/18/2005 10:03:46 AM GMT
  • PJMontyPJMonty Posts: 983
    edited 2005-01-18 20:45
    Jonathon,

    Glad to hear you worked the problem out.
      Thanks, PeterM
Sign In or Register to comment.