Menu

I2C

Help
2006-12-14
2013-05-30
  • Nobody/Anonymous

    Could someone please provide an example interfacing a PIC with a serial eeprom using I2C?  I received some 24AA65's and I can't figure out how to begin using them with a PIC16.

     
    • Hugh Considine

      Hugh Considine - 2006-12-16

      This link may be of some assistance:
      http://ww1.microchip.com/downloads/en/DeviceDoc/i2c.pdf

      I hope to implement built-in support for hardware I2C in GCBASIC at some stage in the near future, probably within the next couple of weeks. I'll post a link to the updated ssp.h as soon as I can.

       
    • Nobody/Anonymous

      Any luck with this?  I've looked over the pdf file, but I cant get past page 62.  It seems that my pic has a different SSPCON register and I can't set it to hardware master mode?

       
    • Nobody/Anonymous

      Will this example work? Here is a snippet:

      'Software I2C mode constants
      #define I2CPORT PORTB
      #define SDA_PORT 4
      #define SCL_PORT 6
      #define SDA I2CPORT.SDA_PORT
      #define SCL I2CPORT.SCL_PORT

      sub I2C_read(RX)
      'subroutine to read a byte, store it in RX
      'set SDA as input
      DIR SDA IN
      FOR counter = 7 to 0
          STEP -1
      'take SCL high
          SET SCL ON
      'if SDA clear, set bit as 1
          RX.counter = 0
          IF (SDA = OFF) THEN RX.counter = 1
      'delay 5microseconds
          wait 5 us
      'take SCL low
          SET SCL OFF
      'delay 5microseconds
          wait 5 us
      NEXT
      'do this for all 8 bits
      end sub

       
    • Hugh Considine

      Hugh Considine - 2007-01-11

      There are a couple of problems with the syntax of your program:
      - It is not possible to set a different bit of a variable based on another variable
      - So far, none of the released versions of GCBASIC allow a bit to be set or checked using the equals sign. This is fixed in the newest release of GCBASIC, which you can get at http://gcbasic.sourceforge.net/newfiles/update.zip

      It also seems that for I2C, a start and stop "condition" are required. The I2C specification at http://www.nxp.com/acrobat_download/literature/9398/39340011.pdf has explanations of these, and some timing diagrams which may be of assistance. The datasheets for PIC chips with "MSSP" modules may also be of some help - I used the 18F4550 datasheet, and found that it helped quite a bit.

      Here is the code that I have at the moment. It has not been tested, and may need to be altered:

      Code to put in main program:

      #include "i2c.h"
      #define I2C_Data PORTB.4
      #define I2C_Clock PORTB.6

      'Time for 100 us
      #define I2C_HalfBitTime 5 us

      Code to put in to "i2c.h":

      #startup I2CInit

      'Initialise code
      sub I2CInit
      dir I2C_Clock In
      dir I2C_Data In
      end sub

      sub I2CReceive(Address, Data)

      'Take control of bus
      Set I2C_Data On
      set I2C_Clock On
      dir I2C_Data Out
      dir I2C_Clock out

      'Start Condition
      set I2C_Data off

      'Send Address (7 bits)
      For Temp = 1 to 7
        Set I2C_Data Off
        if Address.6 On Then Set I2C_Data On
        Set I2C_Clock On
        Wait I2C_HalfBitTime
        Set I2C_Clock Off
        Wait I2C_HalfBitTime
        Rotate Address Left
      next

      'Send direction bit (read)
      Set I2C_Data On
      Set I2C_Clock On
      Wait I2C_HalfBitTime
      Set I2C_Clock Off
      Wait I2C_HalfBitTime
      Dir I2C_Data In

      'Get Ack
      Set I2C_Clock On
      Wait I2C_HalfBitTime
      Set I2C_Clock Off
      Wait I2C_HalfBitTime

      'Get Data (8 bits)
      For Temp = 1 to 8
        Set I2C_Clock On
        Wait I2C_HalfBitTime
        Set STATUS.C Off
        if I2C_Data On Then Set STATUS.C On
        Rotate Data Right
        Set I2C_Clock Off
        Wait I2C_HalfBitTime
      Next

      'Send Ack
      Dir I2C_Data out
      Set I2C_Data On
      Set I2C_Clock On
      Wait I2C_HalfBitTime
      Set I2C_Clock Off
      Wait I2C_HalfBitTime

      'Stop condition
      set I2C_Clock On
      Wait I2C_HalfBitTime
      Set I2C_Data on
      Wait I2C_HalfBitTime

      'Release control
      Dir I2C_Data in
      Dir I2C_Clock In

      end sub

       
    • Nobody/Anonymous

      Hugh --

      I see the new routines added in the ssp.h file to support i2c mode.

      Could I get a simple example of using a PIC that doesn't suppport master i2c mode to interface with something else? 

      Would these functions work?

      I2CMode(Slave)
      I2CSend(data) ' this one looks like it's empty in ssp.h ?
      I2CReceive(data)

      I really appreciate you providing this.  I notice there are no functions to send start and stop bits?  Should these be emulated in software, or will the SSPCON handle it?

      Steve

       
    • Nobody/Anonymous

      Here is the code I was working with to try to implement software i2c.

      Steve

      'Subs
      ' eeprom_send(prom_addr,addrh,addrl,info)            Writes info to eeprom prom_addr and address addr
      ' sub eeprom_receive(prom_addr,addrh,addrl,info)    Receives into info eeprom prom_addr and address addr

      'Software I2C mode constants
      #define I2CPORT PORTB
      #define SDA_PORT 4
      #define SCL_PORT 6
      #define SDA I2CPORT.SDA_PORT
      #define SCL I2CPORT.SCL_PORT
      #define waittime 5

      sub ICC_initialize
      ADOff 'make port digital
      DIR I2CPORT b'00000000' 'make SCL and SDA outputs
      DIR SDA OUT
      DIR SCL OUT
      SET SDA ON 'bring both SCL and SDA high
      SET SCL ON
      end sub

      sub ICC_START
      'subroutine to send start bit
      DIR SDA OUT 'set SDA as output
      SET SDA ON 'take SDA high
      SET SCL ON 'take SCL high
      wait waittime us 'delay
      SET SDA OFF 'take SDA low while clock high for start bit
      wait waittime us 'delay
      SET SCL OFF 'take SCL low
      end sub

      sub ICC_stop
      'subroutine to send a stop bit
      SET SDA OFF 'take SDA low
      SET SCL ON 'take SCL high
      wait waittime us 'delay 1 micro second
      SET SDA ON 'take SDA high while SCL high for stop bit
      wait waittime us 'delay 5 micro second
      end sub

      sub ICC_send(XMIT)
      'subroutine to send 8 bits
      DIR SDA OUT 'set SDA as output
      SET SCL OFF
      for counter = 1 to 8
          wait waittime us
          SET SDA OFF 'clear SDA
          ROTATE XMIT LEFT 'if bit of XMIT is 1, set SDA
          IF STATUS.C ON THEN SET SDA ON
          IF STATUS.C ON THEN number = 1
          SET SCL ON 'take SCL high
          wait waittime us 'delay 5micro second
          SET SCL OFF 'take SCL low
          wait waittime us
      NEXT 'proceed with rest of bits in XMIT
      'NOW acknowledge send
      DIR SDA IN 'set SDA as input
      SET SCL ON 'take SCL high
      wait waittime us 'delay 5microseconds
      SET SCL OFF 'take SCL low
      wait waittime us
      DIR SDA OUT 'set SDA as output
      end sub

      function ICC_read
      'subroutine to read a byte
      'set SDA as input
      DIR SDA IN
      RX = 0
      for counter = 1 to 8
          SET SCL ON 'take SCL high
          wait waittime us
          Set STATUS.C ON
          if SDA ON Then Set STATUS.C OFF
          Rotate RX Left
          wait waittime us 'delay 5microseconds
          SET SCL OFF 'take SCL low
          wait waittime us 'delay 5microseconds
      NEXT 'do this for all 8 bits
      ICC_read = RX
      end function

      sub ICC_send_ack
      'subroutine to send the acknowledge bit
      DIR SDA OUT 'set SDA as output
      SET SDA OFF 'take SDA low
      wait waittime us 'delay 5microsends
      SET SCL ON 'take SCL high
      wait waittime us 'delay 5microsends
      SET SCL OFF 'take SCL low
      wait waittime us 'delay 5microsends
      end sub

      sub ICC_send_no_ack
      'subroutine to send neg ack
      DIR SDA OUT 'set SDA as output
      SET SDA ON 'take SDA high
      wait waittime us 'delay 5microseconds
      SET SCL ON 'take SCL high
      wait waittime us 'delay 5microseconds
      SET SCL OFF 'take SCL low
      wait waittime us 'delay 5microseconds
      end sub

      sub eeprom_send(prom_addr,addr1,addr0,info)
      DIR SDA OUT 'set SCL and SDA as outputs
      DIR SCL OUT
      ICC_initialize 'call init and start subroutine
      ICC_START
      ICC_send(prom_addr) '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(prom_addr,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(prom_addr) 'send prom_addr
      ICC_send(addr1) 'send high memory addr
      ICC_send(addr0) 'send low memory addr
      ICC_START
      ICC_send(prom_addr) 'send prom_addr for read
      eeprom_receive = ICC_read 'call subroutine read
      ICC_send_no_ack 'call subroutine no_ack
      DIR SDA OUT
      DIR SCL OUT
      ICC_STOP
      end function

       
    • Hugh Considine

      Hugh Considine - 2007-01-14

      The I2C routines in ssp.h aren't complete - I haven't touched them since I started adding 18F support to GCBASIC. I'll finish them once I have GCBASIC 0.9.3.0 debugged and uploaded.

      Thanks for posting your I2C routines. Could I redistribute them with GCBASIC 0.9.4.0?

       
    • Steve

      Steve - 2007-01-14

      Sure, that would be fine.

      I would feel better about it if I could actually get them working!

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.