Coding and general discussion relating to the compiler
Moderators: David Barker, Jerry Messina
-
bitfogav
- Registered User
- Posts: 169
- Joined: Sat Oct 09, 2010 1:39 pm
- Location: United Kingdom
Post
by bitfogav » Mon Jun 15, 2020 12:01 pm
Hey guys,
I have been trying to make a simple sub to read all the connected addresses on a I2C bus, the following routine works, but sometimes I get strange results on a serial monitor (as in the bus thinks there's 127 addresses on it?, when there's not), now I don't know if the sub is fully correct with how the I2C works or whether its a device on the bus that spaz-out the bus and gives me the wrong output data to a serial monitor.. If there's any suggestions or recommendations then it would be much appreciated..
Code: Select all
dim addrs, error, nDevices as byte
sub ScanForDevices()
for addrs = 1 to 127
i2c.start()
i2c.writebyte(addrs)
i2c.writebyte($20) '<--- the sub doesn't work unless I add this, the value isn't important.
i2c.stop()
If (I2C.NotAcknowledged = true) Then
error = 1 ' no device
Else
error = 0 ' device detected
EndIf
If error = 0 Then ' no error we have found a device.
USART.Write("$", HexToStr(addrs), 13, 10)
Inc(nDevices) ' found a device so add number of device.
End If
Next
If nDevices = 0 Then
USART.Write("No I2C devices found ", DecToStr(nDevices), 13, 10)
Else
USART.Write("Complete found ", DecToStr(nDevices), 13, 10)
End If
nDevices = 0 ' reset
End Sub
-
Jerry Messina
- Swordfish Developer
- Posts: 1473
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
Post
by Jerry Messina » Mon Jun 15, 2020 2:19 pm
Here's how I do it:
Bit 0 of the address is the RD_WRN bit, so I only use the even numbered "addresses".
(I can't recall ever seeing a "read-only" device).
If the slave is present, it will ACK its address byte, so no other data needs to be sent. Besides, you never know what you might be doing there.
I also add a little delay between addr probes in case the slave is really slow and can't process fast transactions.
Here I used 100us but you can usually get away with much less.
Code: Select all
dim nDevices as byte
sub ScanForDevices()
dim addrs, error as byte
nDevices = 0 ' reset
for addrs = 0 to 126 step 2
i2c.start()
i2c.writebyte(addrs)
i2c.stop()
If (I2C.NotAcknowledged = true) Then
error = 1 ' no device
Else
error = 0 ' device detected
EndIf
If error = 0 Then ' no error we have found a device.
USART.Write("$", HexToStr(addrs), 13, 10)
Inc(nDevices) ' found a device so add number of device.
End If
' add a little delay betweens transactions for some slow slave devices
delayus(100)
Next
USART.Write(DecToStr(nDevices), " I2C device(s) found", 13, 10)
End Sub
-
bitfogav
- Registered User
- Posts: 169
- Joined: Sat Oct 09, 2010 1:39 pm
- Location: United Kingdom
Post
by bitfogav » Mon Jun 15, 2020 3:19 pm
Bit 0 of the address is the RD_WRN bit, so I only use the even numbered "addresses".
(I can't recall ever seeing a "read-only" device).
If the slave is present, it will ACK its address byte, so no other data needs to be sent. Besides, you never know what you might be doing there.
I also add a little delay between addr probes in case the slave is really slow and can't process fast transactions.
Here I used 100us but you can usually get away with much less.
Yes I was sure that I didn't need to send the second byte of data because I only wanted to probe the bus for the connected devices.
So a small delay in the loop basically all it really needed for slow devices
Thank you so much for always helping Jerry.
I have attached the code of my program that might also be useful for anyone else that might need to find the address of a device..
Full Code Below
Code: Select all
Device = 18F2550
Clock = 20
// import libraries...
Include "usart.bas"
Include "convert.bas"
Include "I2C.bas"
dim nDevices as byte
sub ScanForDevices()
dim addrs, error as byte
nDevices = 0 ' reset
for addrs = 0 to 126 step 2
i2c.start()
i2c.writebyte(addrs)
i2c.stop()
If (I2C.NotAcknowledged = true) Then
error = 1 ' no device
Else
error = 0 ' device detected
EndIf
If error = 0 Then ' no error we have found a device.
USART.Write("$", HexToStr(addrs), 13, 10)
Inc(nDevices) ' found a device so add number of device.
End If
' add a little delay betweens transactions for some slow slave devices
delayus(100)
Next
USART.Write(DecToStr(nDevices), " I2C device(s) found", 13, 10)
End Sub
// init I2C...
I2C.Initialize(I2C_100_KHZ)
// start serial...
USART.SetBaudrate(br19200)
USART.Write("I2C Scanner", 13, 10)
USART.Write("By Gavin Wiggett (Bitfogav)", 13, 10)
// main prog loop...
While true
USART.Write("Scanning for Devices..", 13, 10)
ScanForDevices()
DelayMS(5000) ' 5sec delay between bus reads.
Wend
- serialouti2c.png (21.94 KiB) Viewed 3362 times