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):
There are 2 sets of routines, block read/write, and byte read/write.Code:' 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
Here is an example using block read to fetch the time/date registers:
And here is a way to update those same registers with the block write routine:Code:'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 are some handy low level byte write routines:Code:'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 is a routine that will do a block read and then update your system variables directly from the time/date registers:Code: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
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.Code:'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




Bookmarks