PDA

View Full Version : ds1307 from f877 to f452 not work



microkam
- 6th July 2005, 10:44
this code is run ok on 16f877,when i download this code on 18f452 there is one problem that the ds1307 not work, in the same time the 24lc256 on the same bus is working good...whats the problem!!!!


define osc 4
DEFINE LOADER_USED 1

DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 3
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 2
DEFINE LCD_BITS 4
DEFINE LCD_COMMANDUS 2000
DEFINE LCD_DATAUS 50
DEFINE LCD_LINES 2


DPIN var PORTC.4 'I2C DATA PIN 24LC256 and ds1307,with 4K7 pull up
CPIN var PORTC.5 'I2C CLOCK PIN with pulled up resister 4K7


add var word
d1 var byte
d2 var byte
B0 var byte
sec var byte
sec0 var byte
sec1 var byte
rtcco var byte
rtcad var byte

pause 500
rtcco=$D0
rtcad=0
B0=0
I2CWRITE DPIN,CPIN,rtcco,rtcad,[B0,B0,B0,B0,B0] ' intilization of ds1307
lcdout $FE,1," start"
main:
pause 1000
add=0
d1=9
I2cWRITE DPIN,CPIN,$A0,add,[d1] 'eeprom write
pause 30
I2CREAD DPIN,CPIN,$A1,add,[d2] 'eeprom read
gosub readtime
lcdout $FE,1,#d2," ",#sec
goto main

readtime:
rtcco=$D0
rtcad=0
I2CREAD DPIN,CPIN,rtcco,rtcad,[B0] 'ds1307 read
sec0=B0&%00001111
sec1=B0&%01110000 : sec1=sec1>>4
sec=sec0+sec1*10
return

Dave
- 6th July 2005, 11:37
microkam, I notice you make no mention of a 4.7 k pullup on the data line?

Dave Purola,
N8NTA

microkam
- 6th July 2005, 11:49
the data line and clock line is pulled up with 4K7 ohm ,and this code is runing very good on 16f877 ,but idont know whats the problem on 18f452

Ingvar
- 6th July 2005, 11:50
Perhaps .....

DEFINE I2C_SLOW 1

..... will solve the problem?

microkam
- 6th July 2005, 11:53
i did this..
i defined this
DEFINE I2C_SLOW 1
buts no result

NavMicroSystems
- 6th July 2005, 12:59
microkam,

I can't see anything wrong with your code.

And since you are saying the EEPROM works fine
I would assume the DS1307 is faulty
(or has a bad connection)

Melanie
- 6th July 2005, 13:02
Can you try it with a variable instead of a constant in the I2C Address... eg...

RTC var Byte

RTC=$D0
I2CWRITE DPIN,CPIN,RTC,0,[0,0,0,0,0] ' intilization of ds1307

and likewise in reading...

I2CREAD DPIN,CPIN,RTC,0,[B0] 'ds1307 read

there is no need to change between $D0 and $D1 when reading or writing, because PBP manipulates bit zero for you automatically. You only need to concern yourself with the upper seven bits of the address.

Nobody reads FAQ's... makes me wonder why I spent the time doing them in the first place...http://www.picbasic.co.uk/forum/showthread.php?t=587

microkam
- 6th July 2005, 13:30
there is no faulty in ds1307 because before moment i replace the 18f452 with 16f877 on the same program and it run ok ......
i dont know whats i doing

microkam
- 6th July 2005, 13:34
i edited my programe on the new defined and the ds1307 still not working
,i download the new programe on the 16f877 and all thing is ok
whats the problem!!!
mel, can you see the new programe and tell me whats the wrong

Melanie
- 6th July 2005, 13:47
I interchange 18F252, 18F242, 18F2420, 18F2520 and 18F2620 with 16F876's all the time, on the same boards with a DS1307 installed (although I use different pins to you). From memory, other than CONFIG FUSES and the Weak Pull-Up's having a different Register, there's not too many other changes to look out for. Can you try another 18F PIC? what versions of PBP and MPLAB/MPASM are you using?

NavMicroSystems
- 6th July 2005, 13:52
Melanie,

you are absolutely right in:

there is no need to change between $D0 and $D1 when reading or writing, because PBP manipulates bit zero for you automatically. You only need to concern yourself with the upper seven bits of the address.

However,
all variants listed should work:
(I would always prefer the first one)



RTC CON $D0
I2CWRITE DPIN,CPIN,RTC,0,[0,0,0,0,0]




RTC var Byte
RTC=$D0
I2CWRITE DPIN,CPIN,RTC,0,[0,0,0,0,0]




I2CWRITE DPIN,CPIN,$D0,0,[0,0,0,0,0]


and even this one
(Bit0 set with I2CWRITE)
works since PBP takes care of Bit0:


I2CWRITE DPIN,CPIN,$D1,0,[0,0,0,0,0]

microkam
- 6th July 2005, 13:55
i used picbasic pro 2.4
microcode studio 2.0.5.2
mpasm v02.80
whats the state of fuses you use
i used HS are this correct

NavMicroSystems
- 6th July 2005, 13:56
Since microkam has connected the I2" lines to C.4 and C.5
and there is nothing special with PortC on the 877 or 452
it should actually be "Plug&Play"

Melanie
- 6th July 2005, 13:58
Ralph:

I have had instances (back in PBP ver 2.42) where a constant in the Device Address (eg $D0) didn't work. I've had a constant work on a 16F628, yet fail on an 16F872. Since switching to using variables, I've not experienced any problems. I've not botherd doing any in-depth studies on versions beyond 2.42 since if I don't get problems then I don't go out of my way looking for them.

Microkam:

XT for 4MHz or less, HS for greater than 4MHz.
Which sub-version of 2.4... there's big differences between say 2.40 and 2.46.

NavMicroSystems
- 6th July 2005, 14:03
i used picbasic pro 2.4
microcode studio 2.0.5.2
mpasm v02.80
whats the state of fuses you use
i used HS are this correct

There are newer Versions of all the packages available.
(MicroCode Studio and MPASM are available for download)

With regards to the Fuses and Config Bits:
The Loader.HEX usually has all this preset, so you don't have to worry.
(As long as your programmer doesn't alter them)

microkam
- 6th July 2005, 14:10
i want to change the HS to XT and i well reply to you

microkam
- 6th July 2005, 14:16
ok NavMicroSystems , whats the soluation i tested all thing and no result

Bruce
- 6th July 2005, 16:32
PBP version 2.42 introduced some timing changes to I2CREAD/I2CWRITE for
the 18F series. That may be why you're having problems if you're using
version 2.40.

I've compiled your code as-is with PBP v2.46. See if this works for you.

microkam
- 6th July 2005, 21:33
hi Bruce...
i downloaded your hex file and it's runing ok.
how can i solve this problem on my compiler picbasic pro 2.4 because i dont have a newer version than 2.4..

Bruce
- 6th July 2005, 21:50
Version 2.40 is pretty old. If for some reason you can't upgrade to the latest
version, then you might try contacting MeLabs directly to see what changes
they made to the 18F I2C library routines.

Look here http://www.microengineeringlabs.com/support/upgrade.htm#pbp

They've had a LOT of updates since v2.40 for the 18F series. Well worth the
few bucks for an upgrade if you're using 18F parts.

NavMicroSystems
- 6th July 2005, 21:56
microcam,

this is probably not what you wanted to hear,
but best would be to upgrade to PBP 2.46

microkam
- 6th July 2005, 22:23
is this update free ,can i update to 2.46 free

Bruce
- 6th July 2005, 22:52
Contact the distributor you originally purchased PBP from. They should be
able to get you going.

mytekcontrols
- 7th July 2005, 00:02
If you don't want to upgrade PBP, and you don't mind adding some additional code, here is a customizable I2C routine that will work with the DS1307 (it could also be set-up to work with multiple I2C devices):


' SDA = I2C serial data line
' SCL = I2C serial clock lines
'
DS1307 Con $D0 ' I2C Slave Device "Write" Address (DS1307)
I2Cdelay con 15 ' usec delay used in SDA and SCL timing
' routines.
blocksize con 8 ' maximum # of bytes to send or receive

i2cBytes var byte ' # of bytes in data array
i2cData var byte[blocksize] ' data array
i2cWork var byte ' work byte for TX routine
i2cDevAddr var byte ' Device Slave Address
i2cAddr var word ' Memory Address
i2cloop var byte
i2cindex var byte

' ----------------------------------------------------
' Subroutines
' ----------------------------------------------------

'DS1307 RTC Time/Date Register Block Write Routine
'(i2cData = data array, i2cbytes = # of bytes to send)
DS1307blkwrite:
i2cDevAddr = DS1307 ' set slave device WRITE address
Gosub I2C_AddrSend ' Send Address Info!

For i2cindex = 0 To (i2cbytes-1) ' loop for number of bytes in array
i2cWork = i2cData[i2cindex] ' xfer from array to temp
Gosub I2C_TX_Byte ' Send Data!
Next i2cindex

Gosub I2C_Stop ' Finished!
Return

'DS1307 RTC Time/Date Register Byte Write Routine
'(i2cData = byte to send, i2caddr = address of byte to write)
DS1307bytewrite:
i2cDevAddr = DS1307 ' set slave device WRITE address
Gosub I2C_AddrSend ' Send Address Info!

i2cWork = i2cData ' Transfer data!
Gosub I2C_TX_Byte ' Send Data!

Gosub I2C_Stop ' Finished!
Return

'DS1307 RTC Time/Date Register Block Read Routine
'(i2cData = data array, i2cbytes = # of bytes to read)
DS1307blkread:
i2cDevAddr = DS1307 ' set slave device WRITE address
Gosub I2C_AddrSend ' Send Address Info!

Gosub I2C_Stop ' break between events and
Gosub I2C_Start ' re-start for device read

i2cWork = (DS1307+1) ' set slave device READ address
Gosub I2C_TX_Byte

For i2cindex = 0 To (i2cbytes-1) ' loop for number of bytes in array
Gosub I2C_RX_Byte ' Receive Data!
i2cData[i2cindex] = i2cWork ' Transfer Data!
If i2cindex != 6 Then Gosub I2C_ACK
Next i2cindex

Gosub I2C_Stop ' Finished!
Return

'DS1307 RTC Time/Date Register Byte Read Routine
'(i2cData = byte to receive, i2caddr = address of byte to read)
DS1307byteread:
i2cDevAddr = DS1307 ' set slave device WRITE address
Gosub I2C_AddrSend ' Send Address Info!

Gosub I2C_Stop ' break between events and
Gosub I2C_Start ' re-start for device read

i2cWork = (DS1307+1) ' set slave device READ address
Gosub I2C_TX_Byte

Gosub I2C_RX_Byte ' Receive Data!
i2cData = i2cWork ' Transfer Data!

Gosub I2C_Stop ' Finished!
Return

'I2C Device Read/Write and Memory Address Routine
'(i2cDevAddr = Device Address, i2caddr = Memory Address)
I2C_AddrSend:
Gosub I2C_Stop ' Normalize Bus/Recover from errors

Gosub I2C_Start ' send Start

i2cWork = i2cDevAddr ' send slave WRITE address
Gosub I2C_TX_Byte

i2cWork = i2caddr // 256 ' send LSB ADDRESS
Gosub I2C_TX_Byte
If i2cDevAddr = DS1307 Then Return ' 1 byte memory address

i2cWork = i2caddr / 256 ' send MSB ADDRESS
Goto I2C_TX_Byte

' ----------------------------------------------------
' Low Level I2C Subroutines
' ----------------------------------------------------

' --- Start ---
I2C_Start: ' I2C start bit sequence
Gosub SCLlo
Gosub SDAhi
Gosub SCLhi
Gosub SDAlo ' SDA -> low while SCL high
Goto SCLlo

' --- Stop ---
I2C_Stop: ' I2C stop bit sequence
Gosub SCLlo
Gosub SDAlo
Gosub SCLhi
Gosub SDAhi ' SDA --> high while SCL high
Goto SCLlo

' --- Transmit ---
I2C_TX_Byte:
For i2cloop = 0 to 7
If i2cWork.7 = 0 Then
Gosub SDAlo
Else
Gosub SDAhi
Endif
Gosub SCLhi
Gosub SCLlo
i2cWork = i2cWork << 1
Next i2cloop
Goto I2C_NACK

' --- Receive ---
I2C_RX_Byte:
For i2cloop = 0 to 7
Gosub SCLhi
i2cWork = (i2cWork*2)+ SDA ' shift left and insert bit
Gosub SCLlo
Next i2cloop
Return

'Get Acknowledge Bit
I2C_NACK:
Gosub SDAhi
Gosub SCLhi
Goto SCLlo

'Send Acknowledge Bit
I2C_ACK:
Gosub SDAlo
Gosub SCLhi
Gosub SCLlo
Goto SDAhi

SDAhi:
Input SDA
Pauseus I2Cdelay
Return

SDAlo:
Low SDA
Pauseus I2Cdelay
Return

SCLhi:
High SCL
Pauseus I2Cdelay
Return

SCLlo:
Low SCL
Pauseus I2Cdelay
Return


There are 2 sets of routines, block read/write, and byte read/write.
Here is an example using block read to fetch the time/date registers:


'Retrieve RTC values
getclk:
i2caddr = 0
i2cbytes = 7
Gosub DS1307blkread
For indx = 0 to 6
Select Case indx
Case 0 'seconds
secs = i2cData[indx]
Case 1 'minutes
mins = i2cData[indx]
Case 2 'hours
hours = i2cData[indx]
Case 3 'day of the week
dweek = i2cData[indx]
Case 4 'day
day = i2cData[indx]
Case 5 'month
month = i2cData[indx]
Case 6 'year
year = i2cData[indx]
End Select
Next indx
Return


And here is a way to update those same registers with the block write routine:


'Update RTC registers from system variables
UpdateRTC:
Gosub RTCoff

For indx = 0 to 6
Select Case indx
Case 0 'seconds
If newsecs = $FF Then newsecs = 59
If newsecs > 59 Then newsecs = 0
tTemp = newsecs
Gosub dec2BCD
Case 1 'minutes
If newmins = $FF Then newmins = 59
If newmins > 59 Then newmins = 0
tTemp = newmins
Gosub dec2BCD
Case 2 'hours
If newhours = $FF Then newhours = 23
If newhours > 23 Then newhours = 0
tTemp = newhours
Gosub dec2BCD
Case 3 'day of the week
If newdweek = $FF Or newdweek = 0 Then newdweek = 7
If newdweek > 7 Then newdweek = 1
tTemp = newdweek
Gosub dec2BCD
Case 4 'day
tTemp = month
Gosub BCD2dec
If tTemp // 2 = 0 Then
daytop = 30
Else
daytop = 31
Endif
If tTemp = 2 Then
tTemp = year
Gosub BCD2dec
If tTemp // 4 = 0 Then
daytop = 29
Else
daytop = 28
Endif
Endif
If newday = $FF Or newday = 0 Then newday = daytop
If newday > daytop Then newday = 1
tTemp = newday
Gosub dec2BCD
Case 5 'month
If newmonth = $FF Or newmonth = 0 Then newmonth = 12
If newmonth > 12 Then newmonth = 1
tTemp = newmonth
Gosub dec2BCD
Case 6 'year
If newyear = $FF Then newyear = 99
If newyear > 99 Then newyear = 0
tTemp = newyear
Gosub dec2BCD
End Select
Next indx

i2caddr = 0
i2cbytes = 7
Gosub DS1307blkwrite
Goto RTCon

dec2BCD:
tTemp = ((tTemp DIG 1) << 4) | (tTemp DIG 0)
i2cData[indx] = tTemp
Return

BCD2dec:
tTemp = ((tTemp >> 4)*10) + (tTemp & %1111)
Return


And here are some handy low level byte write routines:


RTCon:
i2caddr = 0
Gosub DS1307byteread
If i2cData.7 = 0 Then Return
i2cData = i2cData & %01111111
i2caddr = 0
Goto DS1307bytewrite

RTCoff:
i2caddr = 0
Gosub DS1307byteread
If i2cData.7 = 1 Then Return
i2cData = i2cData | %10000000
i2caddr = 0
Goto DS1307bytewrite

RTChour24:
i2caddr = 2
Gosub DS1307byteread
If i2cData.6 = 0 Then Return
i2cData = 0
i2caddr = 2
Goto DS1307bytewrite


And here is a routine that will do a block read and then update your system variables directly from the time/date registers:



'Refresh system variables from RTC registers
RTCrefresh:
Gosub getclk

tTemp = secs
Gosub BCD2dec
newsecs = tTemp
tTemp = mins
Gosub BCD2dec
newmins = tTemp
tTemp = hours
Gosub BCD2dec
newhours = tTemp
tTemp = dweek
Gosub BCD2dec
newdweek = tTemp
tTemp = day
Gosub BCD2dec
newday = tTemp
tTemp = month
Gosub BCD2dec
newmonth = tTemp
tTemp = year
Gosub BCD2dec
newyear = tTemp
Return


I don't know if any of this will be of use to you, but I had it laying around and I figured I should at least offer it up.