SI2C Query
Moderators: David Barker, Jerry Messina
SI2C Query
On the topic of software I2C again...! Currently, the SI2C library pulls the clock low and high, acting as a master. However, should it instead:
(i) pull the clock (SCL) low, as required, by setting the SCL pin as an output and bringing this low (as it does currently), then...
(ii) when the clock should go high, set the SCL pin as an input and allow the pull-up resistors on the bus to pull it high?
Is there a danger of setting the clock high by using a high output pin that this might be sinked directly into another device/PIC on the I2C bus that is holding the clock low, e.g. for clock stretching?
Any thoughts from anyone welcome.
Thanks,
Steve
(i) pull the clock (SCL) low, as required, by setting the SCL pin as an output and bringing this low (as it does currently), then...
(ii) when the clock should go high, set the SCL pin as an input and allow the pull-up resistors on the bus to pull it high?
Is there a danger of setting the clock high by using a high output pin that this might be sinked directly into another device/PIC on the I2C bus that is holding the clock low, e.g. for clock stretching?
Any thoughts from anyone welcome.
Thanks,
Steve
I've now made the changes to the SI2C module and it still works OK. Is this a valid alteration?
Steve
Steve
Code: Select all
(*
*****************************************************************************
* Name : SI2C Library *
* Author : David John Barker *
* Notice : Copyright (c) 2003 Mecanique *
* : All Rights Reserved *
* Date : 25/07/05 *
* Version : 1.1 *
* Notes : 1.1 Corrected 'NotAcknowledged' in WriteByte() *
* : Added WaitForWrite() routine *
* : 1.0 Initial release *
*****************************************************************************
*)
Module SI2C
Include "system.bas"
// SCL option...
#if IsOption(I2C_SCL) And Not IsValidPortPin(I2C_SCL)
#error I2C_SCL, "Invalid option. I2C clock must be a valid port pin."
#endif
#option I2C_SCL = PORTC.3
// SDA option...
#if IsOption(I2C_SDA) And Not IsValidPortPin(I2C_SDA)
#error I2C_SDA, "Invalid option. I2C data line must be a valid port pin."
#endif
#option I2C_SDA = PORTC.4
// configure SCL and SDA...
Dim
SCL As I2C_SCL.I2C_SCL@,
SDA As I2C_SDA.I2C_SDA@
// SI2C constants...
Public Const
I2C_ACKNOWLEDGE = 0, // acknowledge data bit (acknowledge)
I2C_NOT_ACKNOWLEDGE = 1 // acknowledge data bit (NOT acknowledge)
Public Dim
NotAcknowledged As Boolean
{
****************************************************************************
* Name : SDAHigh (PRIVATE) *
* Purpose : Allows SDA to pull high by I2C bus pull-up resistors *
****************************************************************************
}
Inline Sub SDAHigh()
Input(SDA)
End Sub
{
****************************************************************************
* Name : SCLHigh (PRIVATE) *
* Purpose : Allows SCL to pull high by I2C bus pull-up resistors *
****************************************************************************
}
Inline Sub SCLHigh()
Input(SCL)
End Sub
{
****************************************************************************
* Name : SDALow (PRIVATE) *
* Purpose : Sets SDA to output and force to low as SDA already set low *
****************************************************************************
}
Inline Sub SDALow()
Output(SDA)
End Sub
{
****************************************************************************
* Name : SCLLow (PRIVATE) *
* Purpose : Sets SCL to output and force to low as SCL already set low *
****************************************************************************
}
Inline Sub SCLLow()
Output(SCL)
End Sub
{
****************************************************************************
* Name : Delay (PRIVATE) *
* Purpose : Delay a fixed number of microseconds *
****************************************************************************
}
Inline Sub Delay()
DelayUS(5)
End Sub
{
****************************************************************************
* Name : ToggleClock (PRIVATE) *
* Purpose : Clock the I2C bus *
****************************************************************************
}
Inline Sub ToggleClock()
SCLHigh()
Delay
SCLLow()
Delay
End Sub
{
****************************************************************************
* Name : ShiftOut (PRIVATE) *
* Purpose : Shift out a byte value, MSB first *
****************************************************************************
}
Sub ShiftOut(pData As Byte)
Dim Index As Byte
Index = 8
Repeat
If pData.7 = 1 Then
SDAHigh()
Else
SDALow()
EndIf
ToggleClock
pData = pData << 1
Dec(Index)
Until Index = 0
ClrWDT
End Sub
{
****************************************************************************
* Name : ShiftIn (PRIVATE) *
* Purpose : Shift in a byte value, MSB first, sample whilst clock high *
****************************************************************************
}
Function ShiftIn() As Byte
Dim Index As Byte
Dim TimeOut As Byte
Index = 8
Result = 0
Input(SDA)
Repeat
SCLHigh()
TimeOut = $FF
Repeat
Dec(TimeOut)
Delay
Until (SCL = 1 Or TimeOut = 0) // wait for any clock stretching by slave
Result = Result << 1
Result.0 = SDA
SCLLow()
Delay
Dec(Index)
Until Index = 0
ClrWDT
End Function
{
****************************************************************************
* Name : Initialize *
* Purpose : Initialize I2C bus *
****************************************************************************
}
Public Sub Initialize()
SCLHigh()
SDAHigh()
Low(SCL) // Set low so that pulls low when set to output
Low(SDA) // Set low so that pulls low when set to output
End Sub
{
****************************************************************************
* Name : Start *
* Purpose : Send an I2C bus start condition. A start condition is HIGH to *
* : LOW of SDA line when the clock is HIGH *
****************************************************************************
}
Public Sub Start()
SDAHigh()
Delay
SCLHigh()
Delay
SDALow()
Delay
SCLLow()
Delay
End Sub
{
****************************************************************************
* Name : Stop *
* Purpose : Send an I2C bus stop condition. A stop condition is LOW to *
* : HIGH of SDA when line when the clock is HIGH *
****************************************************************************
}
Public Sub Stop()
SDALow()
Delay
SCLHigh()
Delay
SDAHigh()
Delay
End Sub
{
****************************************************************************
* Name : Restart *
* Purpose : Send an I2C bus restart condition *
****************************************************************************
}
Public Sub Restart()
Start
End Sub
{
****************************************************************************
* Name : Acknowledge *
* Purpose : Initiate I2C acknowledge *
* : pAck = 1, NOT acknowledge *
* : pAck = 0, acknowledge *
****************************************************************************
}
Public Sub Acknowledge(pAck As Bit = I2C_ACKNOWLEDGE)
If pAck = 1 Then
SDAHigh()
Else
SDALow()
EndIf
ToggleClock
End Sub
{
****************************************************************************
* Name : ReadByte (OVERLOAD) *
* Purpose : Read a single byte from the I2C bus *
****************************************************************************
}
Public Function ReadByte() As Byte
Result = ShiftIn
End Function
{
****************************************************************************
* Name : ReadByte (OVERLOAD) *
* Purpose : Read a single byte from the I2C bus, with Acknowledge *
****************************************************************************
}
Public Function ReadByte(pAck As Bit) As Byte
Result = ShiftIn
Acknowledge(pAck)
End Function
{
****************************************************************************
* Name : WriteByte *
* Purpose : Write a single byte to the I2C bus *
****************************************************************************
}
Public Sub WriteByte(pData As Byte)
ShiftOut(pData)
// look for ack...
Input(SDA)
SCLHigh()
Delay
NotAcknowledged = Boolean(SDA)
SCLLow()
SDALow()
End Sub
{
****************************************************************************
* Name : WaitForWrite *
* Purpose : Wait until write sequence has completed *
****************************************************************************
}
Public Sub WaitForWrite(pControl As Byte)
Dim Timeout As Byte
Timeout = $FF
Start
WriteByte(pControl)
While NotAcknowledged And (Timeout > 0)
Restart
WriteByte(pControl)
Dec(Timeout)
Wend
Stop
End Sub
-
- Registered User
- Posts: 185
- Joined: Mon Mar 10, 2008 8:20 am
- Location: Seattle, WA USA
- Contact: