Software I2C Master With Pullups

2007-03-23
2013-05-30
  • Nobody/Anonymous

    Here is an I2C header file that worked for a 16f88 and a 24LC256 eeprom.
    This a rejuggled Steve Bell library, only with pullups on the SDA and SCL lines.  Also included are the required setup definitions and an example code.  Please substitute whatever LCD methods you are using instead of my 'ascii' serial LCD.

    Kent

    Setup:
    #include <I2CMstrSoftPullup.h> 'Or whatever you want to call it
    #define SDA PortB.1            '16f88
    #define SCL PortB.4            '16f88
    #define waittime 1 ms
    #define chipwrite b'10100000'  '24lc256 address 1010+A2A1A0+R/W
    #define chipread b'10100001'
    Dim address as Word

    Code:

    Main:
    LCD_Rst
    address = 0
    For logtemp = 0 to 255
    address = address + 1
    addrl = address
    addrh = address_h
    eeprom_send(addrh, addrl, logtemp)
    wait 1 10ms   'Need some delay here for proper operation
    Next

    Do
    address = 0
    For count = 0 to 255
    LCD_Rst
    address = address + 1
    addrl = address
    addrh = address_h
    ascii (eeprom_receive(addrh,addrl))
    wait 1 s
    Next
    Loop
    goto Main

    Header file:

    '==========================================================
    'This is a Software Master I2C that uses pullups
    'on the SDA and SCL lines.  By Kent Schafer.
    'This is a rejuggled Header file built by Steve Bell
    'without pullups.

    sub ICC_initialize  'Bus not Busy (A)Both SDA & SCL high
    DIR SDA OUT
    DIR SCL OUT
    Dir SDA In  'SET SDA ON
    Dir SCL In  'SET SCL ON
    wait waittime
    end sub

    sub ICC_START      'Start Data Transfer (B) SDA high to low sequence while SCL high
    Dir SDA In         'SET SDA ON
    wait waittime
    Dir SCL In         'SET SCL ON
    wait waittime      'delay 
    DIR SDA OUT        'set SDA as output
    SET SDA OFF        'take SDA low while clock high for start bit
    wait waittime      'delay
    Dir SCL Out
    SET SCL OFF        'take SCL low
    end sub

    sub ICC_stop        'Stop Data Transfer (C) A SDA low to high transition while SCL high
    Dir SCL Out
    SET SCL OFF
    wait waittime
    DIR SDA OUT         'set SDA as output
    SET SDA OFF         'take SDA low
    Dir SCL In          'SET SCL ON
    wait waittime
    Dir SDA In          'SET SDA ON 
    wait waittime 
    end sub

    sub ICC_send(XMIT)  'Data valid (D) data must be changed during SCL low cyle
    Dir SCL Out
    SET SCL OFF
    wait waittime
    for counter = 1 to 8
    DIR SDA OUT          'set SDA as output
    SET SDA OFF          'clear SDA
    ROTATE XMIT LEFT     'if bit of XMIT is 1, set SDA
    IF STATUS.C ON THEN Dir SDA In  'SET SDA ON
    Dir SCL In            'SET SCL ON 'take SCL high
    wait waittime
    Dir SCL Out
    SET SCL OFF           'take SCL low
    wait waittime
    NEXT                  'proceed with rest of bits in XMIT
    'NOW each receiving device must acknowledge after each byte sent
    DIR SDA IN            'set SDA as input
    Dir SCL In            'SET SCL ON'take SCL high
    wait waittime
    Dir SCL Out
    SET SCL OFF           'take SCL low
    wait waittime
    DIR SDA OUT          'set SDA as output
    end sub

    function ICC_read
    DIR SDA IN
    RX = 0
    for counter = 1 to 8
    Dir SCL In                 'SET SCL ON
    wait waittime
    SET STATUS.C OFF
    if SDA ON Then SET STATUS.C ON
    Rotate RX Left
    Dir SCL Out 
    SET SCL OFF                'take SCL low
    wait waittime             
    NEXT                       'do this for all 8 bits
    ICC_read = RX
    End function

    sub ICC_send_no_ack  'SDA must be left Hi-Z after an EEPROM read
    Dir SDA In
    wait waittime
    Dir SCL In                 'SET SCL ON
    wait waittime
    Dir SCL Out
    SET SCL OFF                'take SCL low
    wait waittime
    end sub

    sub eeprom_send(addr1,addr0,info)#NR
    DIR SDA OUT                'set SCL and SDA as outputs
    DIR SCL OUT
    ICC_initialize             'call init and start subroutine
    ICC_START
    ICC_send(chipwrite)        'send prom_addr
    ICC_send(addr1)            'send high memory addr
    ICC_send(addr0)            'send low memory addr
    ICC_send(info)             'send data
    ICC_STOP                   'call stop subroutine
    end sub

    Function eeprom_receive(addr1,addr0)
    DIR SDA OUT                'set SCL and SDA as outputs
    DIR SCL OUT
    ICC_initialize             'call init and start subroutine
    ICC_START
    ICC_send(chipwrite)        'send prom_addr
    ICC_send(addr1)            'send high memory addr
    ICC_send(addr0)            'send low memory addr
    ICC_STOP
    ICC_START
    ICC_send(chipread)         'send prom_addr for read
    eeprom_receive = ICC_read  'call subroutine read
    ICC_send_no_ack            'call subroutine no_ack
    DIR SDA OUT
    ICC_STOP
    end function

     
  • kent_twt4

    kent_twt4 - 2010-10-18

    PS:  Make Main an open loop at end of example code, otherwise, it will eventually wear out the eeprom  by continuously writing to it.

    LCD_Rst
    address = 0
    For logtemp = 0 to 255
    address = address + 1
    addrl = address
    addrh = address_h
    eeprom_send(addrh, addrl, logtemp)
    wait 1 10ms 'Need some delay here for proper operation
    Next
    ...
    ...
    ...
    Main:
    ...
    ...
    goto Main
    
     

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks