Help with serial interface DS1302
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:
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
It's just a simple clockin/clockout routine, anyone spots any obvious errors?
Thanks,
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
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
Glad to hear you worked the problem out.
Thanks, PeterM