Menu

MasterI2C Example (Hardware-Synchronous)

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

    Here is an example on how to use the Master Synchronous Serial Port (MSSP).  Have not tested on other devices or generalized the InitI2C sub to handle other devices if so required?  Comments welcome.

    Sorry for no indents, maybe code tags will come along in the future.

    The header file is in another post to keep it short.

    Kent

    '-------------------------------------------------------
    'Master I2C Mode (Hardware-Synchronous)
    'By Kent Schafer June 20, 2007
    'This is a port of Microchip Tutorial "I2C Master Mode"
    'and AN976
    '-------------------------------------------------------

    'Chip model
    #chip 16f877A,20
    #config     _CP_OFF & CPD_OFF  &_WDT_OFF & _BODEN_OFF & _PWRTE_ON  & _HS_OSC  & _LVP_OFF

    'Setup 4 bit LCD
    #define LCD_IO 4
    #define LCD_DB4 PORTD.4
    #define LCD_DB5 PORTD.5
    #define LCD_DB6 PORTD.6
    #define LCD_DB7 PORTD.7
    #define LCD_RS PORTC.7
    #define LCD_RW PORTC.6
    #define LCD_Enable PORTC.5

    'setup I2C
    #include <MasterI2C.h>
    #define eeprom_write b'10100000'  '24lc256 address write
    #define eeprom_read  b'10100001'  '24lc256 address read
    'SSPADD (ClockValue) equals (FOSC / (4 * Baud)) - 1 
    'For example for 20mhz clock and 100,000bps baud = 49
    'At this time be sure to define ClockValue in binary form
    #define ClockValue b'00110001'
    Dir PortC.3 In  'SCL Port Pin
    Dir PortC.4 In  'SDA Port Pin

    Dim addr as Word
    Dim RxWord as Word
    Dim test as Word

    cls
    test = 7777

    'Initialize MSSP to enable I2c and master mode
    InitI2C

    'Send out data to eeprom address
    addr = 1
    WriteID = eeprom_write
    ReadID = eeprom_read

    For count = 1 to 10
      testl = test
      testh = test_H

      For I2CWord = 1 to 2
        If I2CWord = 1 Then  'First loop thru
          addr = addr + 1
          LowAddr = addr
          HighAddr = addr_h
          I2CWrite(WriteID,HighAddr, LowAddr, testh)
          wait 5 ms   'Need some delay here for proper operation
        End if
        If I2CWord = 2 Then
          addr = addr + 1
          LowAddr = addr
          HighAddr = addr_h
          I2CWrite(WriteID,HighAddr, LowAddr, testl)
          wait 5 ms   'Need some delay here for proper operation  
        End if
      Next

      test = test + 1000
    Next

    Main:

    'Read the test data at eeprom address
    addr = 1

    For count = 1 to 10 
      For I2CWord = 1 to 2
        If I2CWord = 1 Then  'Read in High byte first
          addr = addr + 1
          LowAddr = addr
          HighAddr = addr_h
          RxHigh = I2CRead(WriteID,HighAddr,LowAddr,ReadID)
          wait 5 ms   'Need some delay here for proper operation
        End if

        If I2CWord = 2 Then  'Read in Low byte next
          addr = addr + 1
          LowAddr = addr
          HighAddr = addr_h
          RxLow = I2CRead(WriteID,HighAddr,LowAddr,ReadID)
          wait 5  ms   'Need some delay here for proper operation  
        End if
      Next

      RxWord = RxLow
      RxWord_H = RxHigh
      cls
      LCDWord (RxWord)
      wait 5 sec
    Next

    Goto Main

     
    • Nobody/Anonymous

      Hey man,
      I tried ur code n found an error where it said the I2CWrite(WriteID,HighAddr, LowAddr, testl) has syntax error
      And I just cannot figured out what is the syntax error. Anyone can help?

       
    • kent_twt4

      kent_twt4 - 2008-03-11

      Not able to re-run the code from my location to tell if something is broke. But the first inclination is if you have the the MasterI2C.h file saved in the GCBasic include folder?  The procedure for doing that has been covered in a previous forum post.

       
    • Nobody/Anonymous

      Yeah I have it
      Here is the code I copied from the one of the post. I think there are maybe error within it?
      I'm really stuck with the I2C kent... :(
      Can u see any error within the MasterI2c.h?
      This is abit out of the box but after I tried the MasterI2C.h not successfully I wrote this one to test but also not working:
      ----------------------------------------My test code------------------------------------------------
      #chip 18F452, 4
      ADoff
      #include <MasterI2C.h>
      #define I2CPORT PORTC
      #define SDA_PORT 4
      #define SCL_PORT 3 
      #define SDA I2CPORT.SDA_PORT
      #define SCL I2CPORT.SCL_PORT

      Dim Address, I2C_Data as byte

      #define ClockValue b'00110001' ;ClockValue or SSPADD = (FOSC / (4 * Baud)) - 1 

      Main:
      Address = b'00001111'
      I2C_Data = b'00000010'
      ICC_initialize
      ICC_START
      ICC_send(b'10110000')
      wait 5 us
      ICC_send(Address)
      wait 5 us
      ICC_send(I2C_Data)
      wait 5 us
      ICC_send(b'10110000')
      wait 5 us
      ICC_send(b'00000000')
      wait 5 us
      ICC_send(b'00110010')
      ICC_STOP
      wait 5 s
      goto Main

      'Restart
      'Address = b'00000000'
      'I2C_Data = b'00110010'
      'I2CWrite(0xB0, Address, I2C_Data)
      'wait 2 s
      'goto Main
      end

      Sub ICC_START
        Set SDA ON             // i2c start bit sequence
        wait 5 us
        Set SCL ON
        wait 5 us
        Set SDA OFF
        wait 5 us
        Set SCL OFF
        wait 5 us
      End Sub

      Sub ICC_STOP
        SET SDA OFF             // i2c stop bit sequence
        wait 5 us
        Set SCL ON
        wait 5 us
        Set SDA ON
        wait 5 us
      End Sub

      sub ICC_send(XMIT)
      'subroutine to send 8 bits
      DIR SDA OUT 'set SDA as output
      SET SCL OFF
      wait 5 us
      for counter = 1 to 8
      SET SDA OFF 'clear SDA
      ROTATE XMIT LEFT 'if bit of XMIT is 1, set SDA
      IF STATUS.C ON THEN SET SDA ON
      SET SCL ON 'take SCL high
      wait 5 us 'delay 5micro second
      SET SCL OFF 'take SCL low
      wait 5 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 5 us 'delay 5microseconds
      SET SCL OFF 'take SCL low
      wait 5 us
      DIR SDA OUT 'set SDA as output
      end sub

      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
      wait 5 us
      SET SCL ON
      wait 5 us
      'SSPADD = 249
      'SSPCON1 = b'00001000'
      end sub

      ------------------------------------------------MasterI2C.h-----------------------------------------------------------
      '--------------------------------------------------------
      'Header file name MasterI2c.h
      'Master I2C Mode (Hardware-Synchronous)
      'By Kent Schafer June 21, 2007
      'This is a port of Microchip Tutorial "I2C Master Mode"
      'and AN976
      '
      'This header is currently set up for word size addressing
      'like in the larger size eeproms.
      'No polling is taking place after writes or reads
      'A suitable delay is required (5 ms or ??)
      '--------------------------------------------------------

      sub InitI2C 'Disable slew rate control (SMP)
      SSPSTAT = b'1000000' 'ClockValue or SSPADD = (FOSC / (4 * Baud)) - 1 
      SSPADD = ClockValue 'Clear the register, only cleared on POR
      SSPCON2 = 0 'Set SSPEN and SSPMx bits for SSP Enable and Master I2C mode
      SSPCON = b'00101000'
      SET PIR1.SSPIF OFF
      SET PIR2.BCLIF OFF 
      end sub

      sub Start
      Set PIR1.SSPIF Off 'Clear SSP interrupt flag
      Set SSPCON2.SEN On 'set start condition
      waitstart:
      If PIR1.SSPIF Off Then 'Check if operation complete
      goto waitstart
      end if
      end sub

      sub Restart
      Set PIR1.SSPIF Off 'Clear SSP interrupt flag
      Set SSPCON2.RSEN On 'set stop condition
      waitRestart:
      If PIR1.SSPIF Off Then 'Check if operation complete
      goto waitRestart
      end if
      end sub

      sub TxI2C(SendByte)
      Set PIR1.SSPIF Off 
      SSPBUF = SendByte
      'Wait for acknowledge
      waitTx:
      If PIR1.SSPIF Off Then 'Check if operation complete
      goto waitTx
      end if
      waitAck:
      If SSPCON2.ACKSTAT On Then
      goto waitAck
      end if
      end sub

      sub RxI2C
      Set PIR1.SSPIF Off
      Set RCEN On 'Initiate reception
      waitRx1:
      If PIR1.SSPIF Off Then 'Check if operation complete
      goto waitRx1
      end if
      ReadByte = SSPBUF 'Read byte in buffer
      'Wait for Not acknowledge
      Set PIR1.SSPIF Off
      Set SSPCON2.ACKEN On 'Select to send NO ACK
      waitNoAck:
      If PIR1.SSPIF Off Then 'Check if operation complete
      goto waitNoAck
      end if
      end sub

      sub Stop
      Set PIR1.SSPIF Off 
      Set SSPCON2.PEN On 'Set Stop condition
      waitStop:
      If PIR1.SSPIF Off Then 'Check if operation complete
      goto waitStop
      end if
      end sub

      'sub Poll
      ' For pollcount = 1 to 40
      ' Restart
      ' TxI2C(eeprom_write)
      'end sub

      Function I2CWrite(WriteID, HighAddr, LowAddr, I2Cdata)  
      Start 
      TxI2C(WriteID) 'Device ID write byte 
      TxI2C(HighAddr) 'Send word address high byte 
      TxI2C(LowAddr) 'Send word address low byte 
      TxI2C(I2Cdata) 'Send out data byte to slave 
      Stop 
      'Poll 
      end Function

      Function I2CRead(WriteID,HighAddr,LowAddr,ReadID)
      Start
      TxI2C(WriteID) 'Device ID read byte
      TxI2C(HighAddr) 'Send word address high byte
      TxI2C(LowAddr) 'Send word address low byte
      Restart
      TxI2C(ReadID) 'Device ID read byte
      Set SSPCON2.ACKDT On 'Send no acknowledge
      RxI2C 'Receive data byte from slave
      I2CRead = ReadByte 
      Stop
      end function

      sub I2CWriteTemp(WriteID,command) 
      Start
      TxI2C(WriteID) 'Device ID write byte
      TxI2C(command) 'Send byte size data
      Stop
      end sub

       
    • kent_twt4

      kent_twt4 - 2008-03-19

      Sorry about the late response, but will not be back to my stuff for several weeks yet.  When using the 18f4620, the MasterI2C.h didn't work either.  So here was the header file work around.  An if statement, or script checking for 16 bit device would be more elegant.

      Hope this works for you.

      sub InitI2C 'Disable slew rate control (SMP)
      SSPSTAT = b'1000000' 'ClockValue or SSPADD = (FOSC / (4 * Baud)) - 1 
      SSPADD = ClockValue 'Clear the register, only cleared on POR
      SSPCON2 = 0 'Set SSPEN and SSPMx bits for SSP Enable and Master I2C mode
      ;SSPCON = b'00101000'
      SSPCON1 = b'00101000' '18f needs SSPCON1
      SET SSPIF OFF 'SET PIR1.SSPIF OFF
      SET BCLIF OFF 'SET PIR2.BCLIF OFF 
      end sub

       

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.