Decided to share one of the module's I've hand-coded for interfacing with hardware.
It might work for you right out-of-the-box, but more likely you'll need to tweak it just a bit for your own needs.
That being said, here's my module for interfacing with Maxim's DS1305 (which I've been using on pretty much ALL my PIC projects for a few years now.)
Code: Select all
{
****************************************************************
* Name : EM_Clock.bas *
* Author : Senacharim *
* Date : 02/08/2011 *
* Version : 1.2 *
* Notes : Written for interfacing a PIC18 w/ Maxim DS1305 *
* : *
****************************************************************
}
' - - - - - - - - - - - - - SOF - - - - - - - - - - - - -
Module DS1305
#ifndef _program 'Put a #define _program into your main program...
#error _program, "Hey, thou shalt not compile modules."
#endif
#define DS1305
#option SHIFT_CLOCK = 1
#option SHIFT_MAX = 8
Include "shift.bas"
Include "convert.bas"
Dim
Alarm0Buff(4),
Alarm1Buff(4),
ClockBuff(7),
ControlRegister,
Err_Condition,
oldSeconds,
oldMinutes,
TimeFlags As Byte,
Clock_Error As Boolean,
TMR0ON As T0Con.Booleans(7),
T08BIT As T0Con.Booleans(6),
T0CS As T0Con.5,
ToSE As T0Con.4,
PSA As T0Con.3,
T0PS2 As T0Con.2,
T0PS1 As T0Con.1,
T0PS0 As T0Con.0,
TMR_OverFlow As INTCON.Booleans(2),
Timer0 As TMR0L.AsWord,
FlagSeconds As TimeFlags.Booleans(0),
FlagMinutes As TimeFlags.Booleans(1),
ConReg_EOSC As ControlRegister.7,
ConReg_WP As ControlRegister.6,
ConReg_INTCN As ControlRegister.2,
ConReg_AIE1 As ControlRegister.1,
ConReg_AIE0 As ControlRegister.0
Public Dim
Yesterday_Year,
Yesterday_Month,
Yesterday_Date,
Willbe_Year,
Willbe_Month,
Willbe_Date As Byte
Const
Alarm0ReadAddressStart = $07,
Alarm1ReadAddressStart = $0B
Public Const
Clock_Err_NotRunning = -1,
Clock_Err_AllGood = 0
Const FOSC = _clock * 1000000
Const One_Second_Load = 65536 - ((1 * (FOSC / 4)) / 256)
#if One_Second_Load > 65535
#warning "Invalid Timer1 pre-load value!"
#endif
Dim Clk_CS As PORTC.5
'----------------------------------=-=-----------------------------------------
Public Function Control_Register() As Byte
'----------------------------------=-=-----------------------------------------
Result = ControlRegister
End Function
'----------------------------------=-=-----------------------------------------
Public Function Alarm0_Enabled() As Boolean
'----------------------------------=-=-----------------------------------------
Result = Boolean(ConReg_AIE0)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Alarm1_Enabled() As Boolean
'----------------------------------=-=-----------------------------------------
Result = Boolean(ConReg_AIE1)
End Function
'----------------------------------=-=-----------------------------------------
Public Function DayofMonth() As Byte
'----------------------------------=-=-----------------------------------------
Result = ClockBuff(4)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Seconds() As Byte
'----------------------------------=-=-----------------------------------------
Result = ClockBuff(0)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Minutes() As Byte
'----------------------------------=-=-----------------------------------------
Result = ClockBuff(1)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Hours() As Byte
'----------------------------------=-=-----------------------------------------
Result = ClockBuff(2)
End Function
'----------------------------------=-=-----------------------------------------
Public Function DayofWeek() As Byte
'----------------------------------=-=-----------------------------------------
Result = ClockBuff(3)
End Function
'----------------------------------=-=-----------------------------------------
Public Function DayofWeekString() As String
'----------------------------------=-=-----------------------------------------
Select DayofWeek
Case 1
Result = "Sunday"
Case 2
Result = "Monday"
Case 3
Result = "Tuesday"
Case 4
Result = "Wednesday"
Case 5
Result = "Thursday"
Case 6
Result = "Friday"
Case 7
Result = "Saturday"
End Select
End Function
'----------------------------------=-=-----------------------------------------
Public Function Month() As Byte
'----------------------------------=-=-----------------------------------------
Result = ClockBuff(5)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Year2() As Byte
'----------------------------------=-=-----------------------------------------
Result = ClockBuff(6)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Year() As Word
'----------------------------------=-=-----------------------------------------
Result = 2000 + ClockBuff(6)
End Function
'----------------------------------=-=-----------------------------------------
Function toByte(pValue As Byte) As Byte 'from faux hex!
'----------------------------------=-=-----------------------------------------
Dim
Mini,
Maxm As Byte
'---------------=-=---------------
Mini = 0
Maxm = 0
Mini.0 = pValue.0
Mini.1 = pValue.1
Mini.2 = pValue.2
Mini.3 = pValue.3
Maxm.0 = pValue.4
Maxm.1 = pValue.5
Maxm.2 = pValue.6
Maxm.3 = pValue.7
Result = (Maxm * 10) + Mini
End Function
'----------------------------------=-=-----------------------------------------
Function Clock_IN() As Byte
'----------------------------------=-=-----------------------------------------
(* public const //Shift.In Modes
MSB_PRE = $00, // MSB first, sample before clock
MSB_POST = $02, // MSB first, sample after clock
LSB_PRE = $01, // LSB first, sample before clock
LSB_POST = $03 // LSB first, sample after clock *)
'---------------=-=---------------
Result = Shift.In(LSB_PRE, 8)
End Function
'----------------------------------=-=-----------------------------------------
Function toHex(pValue As Byte) As Byte 'teh faux hexer!
'----------------------------------=-=-----------------------------------------
Dim
Mini,
Maxm As Byte,
Number As String
'---------------=-=---------------
Number = DecToStr(pValue,2)
Maxm = Byte(Number(0)) - 48
Mini = Byte(Number(1)) - 48
Result = (Maxm << 4) + Mini
End Function
'----------------------------------=-=-----------------------------------------
Sub Clock_OUT(pValue As Byte)
'----------------------------------=-=-----------------------------------------
(* public const // shiftout modes...
LSB_FIRST = $00, // LSB first
MSB_FIRST = $01 // MSB first *)
'---------------=-=---------------
Shift.Out(LSB_FIRST,pValue ,8)
End Sub
'----------------------------------=-=-----------------------------------------
Function Clock_IO(pAddress As Byte, pValue As Byte = 0) As Byte
'----------------------------------=-=-----------------------------------------
Dim
pRes As Byte
'---------------=-=---------------
High(Clk_CS)
DelayUS(1)
Clock_OUT(pAddress)
If pAddress > 127 Then
pRes = pValue
Clock_OUT(pRes)
Result = 0
Else
pRes = Clock_IN
Result = pRes
EndIf
Low(Clk_CS)
DelayUS(1)
End Function
'----------------------------------=-=-----------------------------------------
Sub Reset_Timer()
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
Timer0 = One_Second_Load
TMR_OverFlow = false
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub Read_Alarm0()
'----------------------------------=-=-----------------------------------------
Dim
Index As Byte
'---------------=-=---------------
High(Clk_CS)
Clock_OUT(toHex(Alarm0ReadAddressStart))
For index = 0 To Bound(Alarm0Buff)
Alarm0Buff(index) = Clock_IN()
Next
Low(Clk_CS)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub Read_Alarm1()
'----------------------------------=-=-----------------------------------------
Dim
Index As Byte
'---------------=-=---------------
High(Clk_CS)
Clock_OUT(toHex(Alarm1ReadAddressStart))
For index = 0 To Bound(Alarm1Buff)
Alarm1Buff(index) = Clock_IN()
Next
Low(Clk_CS)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub Alarm0_Off()
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
Clock_IO(Alarm0ReadAddressStart)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub Alarm1_Off()
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
Clock_IO(Alarm1ReadAddressStart)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub Read_Clock(pBypassTimer As Boolean = false)
'----------------------------------=-=-----------------------------------------
Dim
Index,
FailCount As Byte
'---------------=-=---------------
If (TMR_OverFlow = true Or pBypassTimer = true) Then
FailCount = 0
ReadAgain:
High(Clk_CS)
Clock_OUT(0)
For index = 0 To Bound(ClockBuff)
ClockBuff(index) = toByte(Clock_IN())
Next
Low(Clk_CS)
If (FailCount < 255) Then
If Hours > 23 Or
Minutes > 59 Or
Seconds > 59 Or
Month = 0 Or
Month > 12 Or
DayofWeek > 7 Or
DayofWeek = 0 Or
Year2 > 99 Then
DelayMS(10)
Inc(FailCount)
GoTo ReadAgain
EndIf
EndIf
Reset_Timer()
EndIf
If oldSeconds <> ClockBuff(0) Then
FlagSeconds = true
oldSeconds = ClockBuff(0)
Else
FlagSeconds = false
EndIf
If oldMinutes <> ClockBuff(1) Then
FlagMinutes = true
oldMinutes = ClockBuff(1)
Else
FlagMinutes = false
EndIf
If Willbe_Date <> DayofMonth Then
Yesterday_Year = Willbe_Year
Yesterday_Month = Willbe_Month
Yesterday_Date = Willbe_Date
Willbe_Year = Year
Willbe_Month = Month
Willbe_Date = DayofMonth
EndIf
End Sub
'----------------------------------=-=-----------------------------------------
Public Function SecondsFlag() As Boolean
'----------------------------------=-=-----------------------------------------
Result = FlagSeconds
End Function
'----------------------------------=-=-----------------------------------------
Public Function MinutesFlag() As Boolean
'----------------------------------=-=-----------------------------------------
Result = FlagMinutes
End Function
Const
pTS_Month = 0,
pTS_Date = 1,
pTS_Year = 2,
pTS_Hour = 3,
pTS_Minute = 4,
pTS_Weekday = 5,
TimeWriteAddress() As Byte = ($85,$84,$86,$82,$81,$83)
'----------------------------------=-=-----------------------------------------
Public Sub SetMonth(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
pValue = toHex(pValue)
Clock_IO(TimeWriteAddress(pTS_Month), pValue)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub SetDate(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
pValue = toHex(pValue)
Clock_IO(TimeWriteAddress(pTS_Date), pValue)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub SetYear(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
pValue = toHex(pValue)
Clock_IO(TimeWriteAddress(pTS_Year), pValue)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub SetHour(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
pValue = toHex(pValue)
pValue.6 = 0 'Set to 24h time.
Clock_IO(TimeWriteAddress(pTS_Hour), pValue)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub SetMinute(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
pValue = toHex(pValue)
Clock_IO(TimeWriteAddress(pTS_Minute), pValue)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub SetWeekday(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
pValue = toHex(pValue)
Clock_IO(TimeWriteAddress(pTS_Weekday), pValue)
End Sub
'************************ |/ Alarm 0 \/ ***************************************
Const
Alarm_Second = 0,
Alarm_Minute = 1,
Alarm_Hour = 2,
Alarm_Weekday = 3,
Alarm0_WriteAddress() As Byte = ($87,$88,$89,$8A)
'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm0Seconds(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
Clock_IO(
Alarm0_WriteAddress(Alarm_Second),
pValue
)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm0Minute(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
Clock_IO(
Alarm0_WriteAddress(Alarm_Minute),
pValue
)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm0Hour(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
Clock_IO(
Alarm0_WriteAddress(Alarm_Hour),
pValue
)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm0Weekday(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
Clock_IO(
Alarm0_WriteAddress(Alarm_Weekday),
pValue
)
End Sub
'----------------------------------=-=-----------------------------------------
Public Function Alarm0Seconds() As Byte
'----------------------------------=-=-----------------------------------------
Result = Alarm0Buff(0)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Alarm0Minutes() As Byte
'----------------------------------=-=-----------------------------------------
Result = Alarm0Buff(1)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Alarm0Hours() As Byte
'----------------------------------=-=-----------------------------------------
Result = Alarm0Buff(2)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Alarm0DayofWeek() As Byte
'----------------------------------=-=-----------------------------------------
Result = Alarm0Buff(3)
End Function
'************************ |/ Alarm 1 \/ ***************************************
Const
Alarm1_WriteAddress() As Byte = ($8B,$8C,$8D,$8E)
'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm1Seconds(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
Clock_IO(
Alarm1_WriteAddress(Alarm_Second),
pValue
)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm1Minute(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
Clock_IO(
Alarm1_WriteAddress(Alarm_Minute),
pValue
)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm1Hour(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
Clock_IO(
Alarm1_WriteAddress(Alarm_Hour),
pValue
)
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub SetAlarm1Weekday(pValue As Byte)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
If pValue.7 = 0 Then pValue = toHex(pValue) EndIf
Clock_IO(
Alarm1_WriteAddress(Alarm_Weekday),
pValue
)
End Sub
'----------------------------------=-=-----------------------------------------
Public Function Alarm1Seconds() As Byte
'----------------------------------=-=-----------------------------------------
Result = Alarm1Buff(0)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Alarm1Minutes() As Byte
'----------------------------------=-=-----------------------------------------
Result = Alarm1Buff(1)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Alarm1Hours() As Byte
'----------------------------------=-=-----------------------------------------
Result = Alarm1Buff(2)
End Function
'----------------------------------=-=-----------------------------------------
Public Function Alarm1DayofWeek() As Byte
'----------------------------------=-=-----------------------------------------
Result = Alarm1Buff(3)
End Function
'******************************************************************************
'----------------------------------=-=-----------------------------------------
Function SetControlRegister(pSetValue As Byte) As Boolean
'----------------------------------=-=-----------------------------------------
Dim
ErrCountup As Byte
'---------------=-=---------------
ErrCountup = 0
Result = false
'1 Read ControlRegister value.
ControlRegister = Clock_IO($0F)
While (ErrCountup < 255)
If ControlRegister <> pSetValue Then
Clock_IO($8F, pSetValue)
DelayMS(1)
ControlRegister = Clock_IO($0F)
DelayMS(1)
Else 'they equal! We're good.
Result = true
Break
EndIf
Inc(ErrCountup)
Wend
End Function
'----------------------------------=-=-----------------------------------------
Public Sub INTCN_EN(pEnabled As Boolean)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
ControlRegister = Clock_IO($0F) 'Get clock control register value.;
If ConReg_INTCN <> Bit(pEnabled) Then
ConReg_INTCN = Bit(pEnabled)
SetControlRegister(ControlRegister)
EndIf
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub Alarm0_EN(pEnabled As Boolean)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
ControlRegister = Clock_IO($0F)
If ConReg_AIE0 <> Bit(pEnabled) Then
ConReg_AIE0 = Bit(pEnabled) ' 1
SetControlRegister(ControlRegister)
EndIf
End Sub
'----------------------------------=-=-----------------------------------------
Public Sub Alarm1_EN(pEnabled As Boolean)
'----------------------------------=-=-----------------------------------------
'---------------=-=---------------
ControlRegister = Clock_IO($0F)
If ConReg_AIE1 <> Bit(pEnabled) Then
ConReg_AIE1 = Bit(pEnabled) ' 1
SetControlRegister(ControlRegister)
EndIf
End Sub
' *****************************************************************************
'----------------------------------=-=-----------------------------------------
Public Sub Clock_Init(pEnableTimer As Boolean = true)
'the vaunted, all important clock initialization.
'a routine which must not fail if accurate timing is to be achieved.
'----------------------------------=-=-----------------------------------------
Dim
CountUp As Byte
'---------------=-=---------------
CountUp = 0
ControlRegister = Clock_IO($0F) 'Read control register.
ConReg_WP = 0
SetControlRegister(ControlRegister) 'Write Protect Off.
If ConReg_EOSC <> 0 Then
ConReg_EOSC = 0
SetControlRegister(ControlRegister)
EndIf
If pEnableTimer Then
TMR0ON = false
T08BIT = false '16 bit counter
T0CS = 0 'internal clock
PSA = 0 'prescaler assigned.
T0PS2 = 1
T0PS1 = 1
T0PS0 = 1 ' 1:256 Scaler.
Timer0 = One_Second_Load
TMR0ON = true
Else
TMR0ON = false
Timer0 = 0
EndIf
TMR_OverFlow = false
' Read_Clock(true)
While
(Hours = 0 And Minutes = 0 And Seconds = 0
And Year2 = 0 And Month = 0 And DayofMonth = 0
And CountUp < 255)
Inc(CountUp)
DelayMS(10)
Read_Clock(true)
Wend
'Assuming the system clock is correct, then at least 2.5 seconds will have
'gone by betwixt initialization and the last loop's reading.
'A 0 in the seconds place, given that situation, indicates a definite err.
If (CountUp = 255) Then
Clock_Error = true
Err_Condition = Clock_Err_NotRunning
Else
Err_Condition = Clock_Err_AllGood
EndIf
ControlRegister = Clock_IO($0F) 'Read control register. Again.
End Sub
//TimerEvent = Clock_Increment()
//Initialise Module
Err_Condition = 255
Shift.SetInput(PORTB.0)
Shift.SetOutput(PORTB.0)
Shift.SetClock(PORTC.4)
Clear(ClockBuff)
Clock_Error = false
FlagSeconds = false
oldSeconds = 255
oldMinutes = 255
Yesterday_Year = 0
Yesterday_Month = 0
Yesterday_Date = 0
Willbe_Year = 0
Willbe_Month = 0
Willbe_Date = 0
Clock_Init() 'auto-init with timer. Perhaps to change this later...
' - - - - - - - - - - - - - EOF - - - - - - - - - - - - -
End Module