News:

Let's find out together what makes a PIC Tick!

Main Menu

I2C address scanner

Started by Yves, Jun 30, 2023, 07:01 AM

Previous topic - Next topic

Yves

hello all,

I was wondering if anyone has developed a I2C scanning address. The routine will send a series of increasing addresses and report when it it get a positive response.
I'm asking this as I have an I2C chip where the address is completely unreadable, I suppose the routine will scan until it get an acknowledgement bit (ack). What I Know is the address is in two parts of 4 bits each the first 4 bits is the type of chip and the second is the actual address?
Regards,

Yves 
Yves


flosigud

Here is my version but Keytapper has also posted one:


'    ---------------------------------------------------------------------------
'    Name    : IICaddressScanner.BAS                                      
'    Author  : Flosi Guðmundssn                                    
'    Notice  : Copyright (c) 2015 Flosi Guðmundsson                
'            : All Rights Reserved                                 
'    Date    : 20.11.2015                                          
'    Version : 1.0                                                 
'    Notes   : The i2c scanner uses the return value of HBusOut    
'            : To see if a device did acknowledge the address.
'            : Adresses from 1 to 255 are checked
'            : Found adresses are sent to the serial port   
'   ----------------------------------------------------------------------------


'    ----------------------------------------------------------------------------

'    Include "..\33fj128GP802.inc"
    Include "..\33FJ12MC202.inc"
'    Include "..\33FJ32MC302.inc"

'    ----------------------------------------------------------------------------
'

    Dim bAddress As Byte
    Dim bAddresses As Byte
    Dim bReply

    Dim sI2CScanner[13]      As Code = " I2C Scanner ",0   
    Dim sReply[25]           As Code = " Reply at address ",0
    Dim sNumberOfReplies[11] As Code = " Replies = ",0
    DelayMS 1000

    HRSOut CStr sI2CScanner,13,13

    bAddresses = 0
    For bAddress = 1 To 255
        bReply = HBusIn bAddress
        If bReply < 255 Then
            HRSOut CStr sReply, Hex bAddress,13
            Inc bAddresses
        EndIf
    Next
    HRSOut CStr sNumberOfreplies , Dec bAddresses,13
   

    Stop

TimB

#3
Here is a more complex looking routine that uses bit of Les's software i2c routines

It sends the START sequence, then the ADDRESS, then clocks and checks for an ACK and finally a STOP Sequence

NOTE not tested in anything but Labcenter VSM but it shows it working right apart from the restarts !


Screenshot 2023-06-30 145742.png



    Symbol I2C_SDA_Pin = portC.0
    Symbol I2C_SCL_Pin = portC.1


'----------------------------------------------------------------------------------------------
' Create a very small delay to slow down the I2C interface (if required)
' Input    : None
' Output    : None
' Notes    : None
'
    $define I2C_hDelayL() Delayus 2

    $define I2C_hDelayH() Delayus 3



    Proc I2C_FindAddress(pData As Byte), Bit


        Dim I2C_bBitIndex as Byte

        PinLow I2C_SDA_Pin                          ' Make the SDA pin an output low
        I2C_hDelayL()                              ' Create a small delay
        PinLow I2C_SCL_Pin                          ' Make the SCL pin an output low
        I2C_hDelayL()                              ' Create a small delay

        For I2C_bBitIndex = 7 DownTo 0              ' Create a loop for the 8-bits to write
            If pData.7 = 1 Then                    ' Is bit-7 of pData set?
                PinInput I2C_SDA_Pin                ' Yes. So make the SDA pin an input (made high by the pull-up resistor)
            Else                                    ' Otherwise...
                PinLow I2C_SDA_Pin                  ' Make the SDA pin an output low
            EndIf                                  '
            I2C_hDelayL()                            ' Create a small delay
            PinInput I2C_SCL_Pin                    ' Make the SCL pin an input (made high by the pull-up resistor)
            I2C_hDelayH()                            ' Create a small delay
            PinLow I2C_SCL_Pin                      ' Make the SCL pin an output low
            I2C_hDelayL()                            ' Create a small delay
            Rol pData                              ' Rotate pData left by 1 bit
        Next

        i2C_hDelayL()                                ' Create a small delay
        PinInput I2C_SDA_Pin                        ' Make the SDA pin an input (made high by the pull-up resistor or low as an ACK by slave)

        PinInput I2C_SCL_Pin                          ' Make the SCL pin an input (made high by the pull-up resistor)
        I2C_hDelayH()                                ' Create a small delay

        I2C_hDelayL()                                ' Create a small delay
        Result = I2C_SDA_Pin                        ' If the line is low then address is right and you have an ACK back High and no responce

        ' Now send a stop

        I2C_hDelayL()                                ' Create a small delay
        PinLow I2C_SDA_Pin                          ' Make the SDA pin an output low
        I2C_hDelayL()                                ' Create a small delay
        PinInput I2C_SCL_Pin                        ' Make the SCL pin an input (made high by the pull-up resistor)
        I2C_hDelayH()                                ' Create a small delay
        PinInput I2C_SDA_Pin                        ' Make the SDA pin an input (made high by the pull-up resistor)
        I2C_hDelayH()
    EndProc

Here is how to call it


If  I2C_FindAddress(bIndex) = 0 then
    'We have the address
Endif