PDA

View Full Version : DS1302 16F628 Woes



idtat
- 11th January 2009, 00:58
Hi All, Hope I posted the code correctly in the box

I have been working on this for about 8 hours now and have GOOGLED it to death, I am usualy very good at finding my solution on my own.

When I set the time I get some strange outputs on the LCD, like I am thinking HEX and it is thinking DEC and visa versa.

I have writen some test code to play with the modifiers (DEC, HEX, BIN) to see if I could figure it out but..................

The trees seem to be so thick I can't see the problem on this one.

Any pointers would be great.

Thanks
Aaron





'----------------------- Chip Setup ----------------------------------------

Define osc 4
CMCON = 7 ' PortA = digital I/O
VRCON = 0 ' A/D Voltage reference disabled
TRISA = %11110000 ' Set PortA I/O
TRISB = %11110001 ' Set PortB I/O
PORTA = 0 ' Clear PortA
PORTB = 0 ' Clear PortB

'-------------------------- I/O Variables ----------------------------------

rst var portb.2 ' DS1302 Reset PIC Pin 8 Blue
clk var portb.1 ' DS1302 Clock PIC Pin 7 Orange
dq var portb.0 ' DS1302 Data PIC Pin 6 White
LCD var PortA.2 ' PIC pin 1

'----------------------- Write Commands For DS1302 --------------------------

writectrl con $8E ' Control byte
writeram con $80 ' Write to RAM
writeprotect con $00 ' Write-protect DS1302
writesec con $80 ' Write seconds
writemin con $82 ' Write minutes
writehour con $84 ' Write hour
writedate con $86 ' Write date
writemonth con $88 ' Write month
writeyear con $8C ' Write year

'------------------------- Read Commands For DS1302 -------------------------

readsec con $81 ' Read seconds from DS1302
readmin con $83 ' Read minutes from DS1302
readhour con $85 ' Read hours from DS1302
readdate con $87 ' Read date from DS1302
readyear con $8D ' Read year from DS1302
readmonth con $89 ' Read month from DS1302

'------------------------- Commands For LCD ---------------------------------

Baud con 16780 'Baud rate 2400 8N1

'------------------------------ Time Variables ------------------------------

mem var byte ' Temporary data holder
outbyte var byte ' Second byte to ds1302
reg_adr var byte ' First byte to DS1302
date var byte ' Date variable
ss var byte ' Seconds variable
ss2 var byte 'seconds comparison byte
mm var byte ' Minutes varibale
hh var byte ' Hours variable
mo var byte ' Month variable
yr var byte ' Year variable

'------------------------ Initial Settings For Ports ------------------------

low rst ' Set reset pin low
low clk ' Set clock pin low

'----------------------- Set Initial Time ----------------------------------

reg_adr = writectrl ' Set to control byte
outbyte = writeprotect ' Set turn off protection
gosub w_out ' Send both bytes

reg_adr = writesec ' Set to write seconds register
outbyte = $00 ' Set to write 00 to seconds register
gosub w_out

reg_adr = writemin
outbyte = $2D
gosub w_out

reg_adr = writehour
outbyte = $04
gosub w_out

reg_adr = writedate
outbyte = $A
gosub w_out

reg_adr = writemonth
outbyte = $01
gosub w_out

reg_adr = writeyear
outbyte = $09
gosub w_out

reg_adr = writectrl
outbyte = writeprotect
gosub w_out

'----------------------- Main Program -----------------------------------

Main_Program:
gosub Get_time
gosub Display
goto Main_Program
end

'----------------------- Get Time Subroutine ---------------------------

Get_time:
reg_adr = readsec ' Read seconds
gosub w_in
ss = mem

reg_adr = readmin ' Read minutes
gosub w_in
mm = mem

reg_adr = readhour ' Read Hours
gosub w_in
hh = mem

reg_adr = readyear ' Read Year
gosub w_in
yr = mem

reg_adr = readdate ' Read Date
gosub w_in
date = mem

reg_adr = readmonth ' Read Month
gosub w_in
mo = mem
return

'----------------------- Display Subroutine ---------------------------

Display:
pause 250
serout2 LCD,Baud,[12,14, "TIME ", hex2 hh,":", hex2 mm,":", hex2 ss]
return

'----------------------- Time Commands Subroutines --------------------------

w_in:
mem = reg_adr ' Set mem variable to reg_adr contents
high rst ' Activate the DS1302
shiftout dq,clk,0, [mem] ' Send control byte
shiftin dq,clk,1, [mem] ' Retrieve data in from the DS1302
low rst ' Deactivate DS1302
return

w_out:
mem = reg_adr ' Set mem variable to reg_adr contents
high rst ' Activate the DS1302
shiftout dq,clk,0, [mem] ' Send control byte
mem = outbyte ' Set mem variable to outbyte contents
shiftout dq,clk,0, [mem] ' Send data stored in mem variable to DS1302
low rst ' Deactivate DS1302
return

idtat
- 11th January 2009, 01:01
Forgot to say thanks to Cokecolakid for the origional code

Charles Linquis
- 11th January 2009, 03:34
This is what I use. I cut-and-pasted from some other code, so everything might not be here, but this should give you a good idea.







RTC = %11010000 ' RTC device address (byte addressing); should not be a constant
ScReg CON $00 ' seconds address (00 - 59) MSBit of SecReg must be set to a 0 to enable RTC
MnReg CON $01 ' minutes address (00 - 59)
HrReg CON $02 ' hours address (01 - 12) or (00 - 23)
DaReg CON $03 ' day address (1 - 7)
DtReg CON $04 ' date address (01 - 28/29, 30, 31)
MoReg CON $05 ' month address (01 - 12)
YrReg CON $06 ' year address (00 - 99)
ContReg CON $07 ' control register
RAMstart CON $08
RTCflag CON 0 ' RTC flag (location 0 of internal EEPROM)
ClockControlByte CON %00010000 ' sets the SQW/OUT to 1Hz pulse, logic level low


' Clock Variables


Sc VAR BYTE
Mn VAR BYTE
Hr VAR BYTE
Da VAR BYTE
Dt VAR BYTE
Mo vAR BYTE
YR var BYTE


;------------------------------------------------------------


DoClock:
HSEROUT [13,10,"To SET clock, enter 'S', to READ clock, enter 'R'",13,10]
HSERIN [Dummy]


IF Dummy = "S" OR Dummy = "s" THEN

HSEROUT ["Enter Time - all inputs require two digits, no editing is possible",13,10]

HSEROUT [13,10,"Hours "]
HSERIN [Dummy]
HSEROUT [Dummy]
TimBuff[1] = Dummy
HSERIN [Dummy]
HSEROUT [Dummy]
TimBuff[2] = Dummy

HSEROUT [13,10,"Minutes "]
HSERIN [Dummy]
HSEROUT [Dummy]
TimBuff[3] = Dummy
HSERIN [Dummy]
HSEROUT [Dummy]
TimBuff[4] = Dummy

HSEROUT [13,10,"Date "]
HSERIN [Dummy]
HSEROUT [Dummy]
TimBuff[9] = Dummy
HSERIN [Dummy]
HSEROUT [Dummy]
TimBuff[10] = Dummy

HSEROUT [13,10,"Month "]
HSERIN [Dummy]
HSEROUT [Dummy]
TimBuff[7] = Dummy
HSERIN [Dummy]
HSEROUT [Dummy]
TimBuff[8] = Dummy

HSEROUT [13,10,"Year "]
HSERIN [Dummy]
HSEROUT [Dummy]
TimBuff[11] = Dummy
HSERIN [Dummy]
HSEROUT [Dummy]
TimBuff[12] = Dummy
GOSUB SETTime
ENDIF

IF Dummy = "R" or Dummy = "r" THEN
GOSUB ShowTime

HSEROUT [TimBuff[1],TimBuff[2],":",TimBuff[3],TimBuff[4],":00,",TimBuff[7],TimBuff[8],"/",TimBuff[9],TimBuff[10],"/",TimBuff[11],TimBuff[12],13,10]

PAUSE 10000

ENDIF

RETURN



HexASCII2BCD:
BCD = (Number1 - 48)<<4 + (Number2 - 48)
RETURN

BCD2HexASCII:
Number1 = (BCD >> 4) + 48
Number2 = (BCD & %00001111) + 48
RETURN




SetTime:

Number1 = TimBuff[5]
Number2 = TimBuff[6]

Gosub HexAscii2BCD

Sc = BCD

Number1 = TimBuff[3]
Number2 = TimBuff[4]


Gosub HexAscii2BCD

Mn = BCD

Number1 = TimBuff[1]
Number2 = TimBuff[2]

Gosub HexAscii2BCD

Hr = BCD

Number1 = TimBuff[7]
Number2 = TimBuff[8]

Gosub HexAscii2BCD

Mo = BCD

Number1 = TimBuff[9]
Number2 = TimBuff[10]

Gosub HexAscii2BCD

Da = 0 ' We don't care what day of the week it is
Dt = BCD

Number1 = TimBuff[11]
Number2 = TimBuff[12]

Gosub HexAscii2BCD

YR = BCD

Cntrl = 0 ' Must be zero to make clk run - NOT same as control reg!
Gosub ClockWrite
GOSUB ClockControl
Spare1 = 55 ' Doesn't have to be BCD
GOSUB ClockRamWrite
RETURN


ShowTime:

Gosub ClockRead
BCD = sc
GOSUB BCD2HexAscii

TimBuff[5] = Number1
TimBuff[6] = Number2

BCD = mn
GOSUB BCD2HexAscii
TimBuff[3] = Number1
TimBuff[4] = Number2

BCD = hr
GOSUB BCD2HexAscii
TimBuff[1] = Number1
TimBuff[2] = Number2

BCD = mo
GOSUB BCD2HexAscii
TimBuff[7] = Number1
TimBuff[8] = Number2

BCD = dt
GOSUB BCD2HexAscii
TimBuff[9] = Number1
TimBuff[10] = Number2

BCD = yr
GOSUB BCD2HexAscii
TimBuff[11] = Number1
TimBuff[12] = Number2

RETURN


ClockWrite:
I2CWrite SDA1,SCL1,RTC,ScReg,[sc,mn,hr,da,dt,mo,yr,Cntrl]
Return

ClockControl:
I2CWRITE SDA1,SCL1,RTC,ContReg,[ClockControlByte]
RETURN

ClockRAMRead:
I2CRead SDA1,SCL1,RTC,RAMstart,[Spare1,Spare2,Spare3,Spare4,Spare5,Spare6]
RETURN

ClockRAMWrite:
I2CWRITE SDA1,SCL1,RTC,RAMstart,[Spare1,Spare2,Spare3,Spare4,Spare5,Spare6]
RETURN

ClockRead:
I2CRead SDA1,SCL1,RTC,ScReg,[sc,mn,hr,da,dt,mo,yr]
RETURN

elec_mech
- 15th January 2009, 03:27
idtat,

I'm attempting to use the DS1302 myself with luck as well. Now, I haven't read through your code to any great extend, but one thing jumped out at me:



w_in:
mem = reg_adr ' Set mem variable to reg_adr contents
high rst ' Activate the DS1302
shiftout dq,clk,0, [mem] ' Send control byte
shiftin dq,clk,1, [mem] ' Retrieve data in from the DS1302
low rst ' Deactivate DS1302
return


I'm assuming you're using burst mode? Regardless, in either burst mode or the non-burst mode, you have to use LSB. I see you did that for your shiftouts, but not for your shiftin above. In other words, try changing this:



shiftin dq,clk,1, [mem] ' Retrieve data in from the DS1302


to this:



shiftin dq,clk,0, [mem] ' Retrieve data in from the DS1302


Let me know if you have luck. I'm trying to read seconds and I'm getting junk.

elec_mech
- 15th January 2009, 14:15
Okay, I'm an idiot. I didn't realize a '1' in shiftin is for LSB, whereas a '1' in shiftout is MSB. I came across some other code (haven't tried it yet) on the forum that may help:

http://www.picbasic.co.uk/forum/showthread.php?t=3499&highlight=ds1302


Good luck.