I2C Slave with a PIC


Closed Thread
Results 1 to 40 of 130

Hybrid View

  1. #1
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default

    I will be interested in your port to the 18F series, and it sounds like you will be willing to post your code. I have an upcoming project that will need it. I tried to get Soubie's code working about a year ago with no luck.
    Charles Linquist

  2. #2
    Join Date
    Nov 2008
    Posts
    48


    Did you find this post helpful? Yes | No

    Default

    Charles,
    same problem, i also never got his code working.
    I come back next week, hope with a working code.
    Regards,
    Ralf

  3. #3
    Join Date
    Oct 2008
    Location
    Southern California
    Posts
    17


    Did you find this post helpful? Yes | No

    Unhappy Still not working here

    Guys,

    I've been working this problem for nearly a year now. I've tried Soubie's code with no luck, and the code from this thread isn't working either. I'm using the 18F4620 as the master talking to an 18F2620, the little brother of the 4620 as the slave. I've RTFM to the point I can recite it, and the Errata sheets, and I've tried countless logical, and even illogical options to trying to get it working.

    The best I can get so far is the master sends the address byte and the slave accepts it when it matches its own address and ignores addresses not matching its own. When the address matches, the slave sets the Buffer Full and the Interrupt Flags, but for some reason won't send an ACK back to the master (at least that's what this thread's code [and my own polls of the master's ACK flag] are saying). I've made sure to clear all flags as the datasheet clearly directs, and still no luck. If the slave would ACK, the master would send the next byte and so on.

    I'm operating both chips on their internal crystal (8 MHz) and using the 4x PLL (= 32MHz). Before you go there, I'm already successfully talking to an I2C real-time clock chip with no problems and I'm saving data to an external I2C EEPROM regularly with no problems. The I2C network is working with the PICs at 32 MHz. I'm on the right pins; I'm using the pull external pull-up resistors...

    I've had this exact hardware working in the past when using MikroElektronika Basic, but I'm much happier in PBP. This one problem is holding up the entire project. Trying to get two 18F's to ping-pong data back and forth is a killer.

    If someone has even a bit more success than what I've had, please post it and maybe together we can chip away at this challenge.

  4. #4


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by rswain View Post
    and the code from this thread isn't working either.
    Well, the code provided by Al (aratti) and the one I posted works great both ways!

    I don't know what to tell you without looking at your code, but I modified the one provided by Al just a little and worked right away!

    Can you post your code? Maybe we can see something that you're not seeing.

  5. #5
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default

    I'll be able to devote some time to a group project in about two weeks. I will also have another issue - I'm forced to work with 10-bit addresses.
    Charles Linquist

  6. #6
    Join Date
    Oct 2008
    Location
    Southern California
    Posts
    17


    Did you find this post helpful? Yes | No

    Default Code for 18F2620 that doesn't ACK for some reason

    Here's my slave code that's not sending back the ACK. I appologize for the "dead code" and commented out parts in advance. Maybe you'll see something I'm missing...

    Robert
    ----------------
    Code:
    'Oscillator Initialization
        DEFINE OSC 32               ' Osc. in MHz
        OSCCON = %01110000          
        OSCTUNE.6 = 1               
        ADCON0.0 = 0                ' Turns off A-to-D module
        ADCON1 = $0F                ' Makes 100% port A digital 
        TRISA = %00000000
        CMCON = 7 ' Comparators Off
    
    DEFINE I2C_HOLD 1
    'DEFINE I2C_SLOW 1
    
    ' Define used register flags
    SSPIF    VAR PIR1.3 ' SSP (I2C) interrupt flag
    SSPIE    VAR PIE1.3 ' SSP Int Enable
    BF       VAR SSPSTAT.0 ' SSP (I2C) Buffer Full
    R_W      VAR SSPSTAT.2 ' SSP (I2C) Read/Write
    D_A      VAR SSPSTAT.5 ' SSP (I2C) Data/Address
    CKP      VAR SSPCON1.4 ' SSP (I2C) SCK Release Control
    SSPEN    VAR SSPCON1.5 ' SSP (I2C) Enable
    SSPOV    VAR SSPCON1.6 ' SSP (I2C) Receive Overflow Indicator
    WCOL     VAR SSPCON1.7 ' SSP (I2C) Write Collision Detect
    'STRETCH  VAR SSPCON2.0 ' SSP (I2C) Clock stretch
    
    A        var byte      ' my counter variable for testing
    '---------------- Alias pins -----------------------------------
    
    TRISC.3 = 1         ' input
    TRISC.4 = 1         ' input
    
    '--------------- Define used register flags -------------------
    
    'STAT_BF             VAR SSPSTAT.0           ' SSP (I2C) Buffer Full
    'STAT_RW             VAR SSPSTAT.2           ' SSP (I2C) Read/Write
    'STAT_DA             VAR SSPSTAT.5           ' SSP (I2C) Data/Address
    CKE                 VAR SSPSTAT.6           ' SSP (I2C) Data/Address
    
    '------------------- Rx Buffer definition --------------------
    RxBufferLEN         con 3           
    RxBuffer            var byte[Rxbufferlen]
    RxBufferIndex       var byte
    
    '------------------ Tx Buffer definition ----------------------
    TxBufferLEN         con 3
    TxBuffer            var byte[txbufferlen]
    TxBufferIndex       var byte
    
    '------------------ Define constants ------------------------
    'I2Caddress          CON $2                  ' Make address = 2
    I2Caddress          CON $06                  ' Make address = 2
    
    ' Define constants
    U8       var byte
    U17      var byte
    InByte   var byte
    OutByte  var byte
    readcnt  VAR BYTE 
    'U8 = $06
    U17 = $08
    
    'STRETCH = 1
    WRData var byte
    ' Initialize I2C slave mode
    'SSPCON2 = 0 ' General call address disabled
    
    'SSPADD = My_I2C_address                     ' Set our address
    SSPADD = I2Caddress                         ' Set our address
    SSPCON2.7 = 0                               ' General call address disabled
    SSPCON1 = $36                               ' Set to I2C slave with 7-bit address
    SSPSTAT = 0
    SSPIE = 1 
    SSPIF = 0 
    RxBufferIndex = 0
    TxBufferIndex = 0
    bf = 0
    SSPOV = 0
    
        'Port C harware UART settings 
        DEFINE HSER_RCSTA 90h              
        DEFINE HSER_TXSTA 20h              
        DEFINE HSER_BAUD 9600              
        DEFINE HSER_CLROERR 1       
    '----------------- Initialization Done! -----------------------------
    rxbuffer[0] = 0
    rxbuffer[1] = 0
    rxbuffer[2] = 0
    
    GoTo main
      
    
    I2C_Slave:                                  ' I2C slave subroutine
      hserout ["SSPIF = ",#SSPIF,"  BF = ",#bf,13,10]
      hserout ["R_W = ",#R_w,"  D_A = ",#D_A,13,10]
      hserout ["SSPBUF = ",#SSPBUF,13,10]
      SSPIF = 0                                 ' Clear interrupt flag
      SSPov = 0                                 ' Clear interrupt flag
      bf = 0                                      ' clear buffer full
      IF R_W = 1 Then 
        hserout ["R_W = 1, Read data from U8",13,10]
        goto I2C_Read                  ' Read data from us
      endif
      IF SSPBUF = I2Caddress Then 
        hserout ["It's to me! ",#SSPBUF," = ",#I2Caddress,13,10]
      endif
      IF D_A = 1 Then 
        hserout ["Data (not address)",13,10]
        goto I2C_Write                 ' Data for us (not address)
      endif
      GoTo I2C_Exit
      
    I2C_Write:                                      ' I2C write data to us
      InByte = SSPBUF                             ' Put buffer data into array
      Rxbuffer[Rxbufferindex] = InByte
      rxbufferindex = rxbufferindex + 1
    
      hserout ["SSPBUF Write = ",#SSPBUF,13,10]
      GoTo i2c_exit
    
    I2C_Read:                                 ' I2C read data from us
      hserout ["SSPBUF Read = ",#SSPBUF,13,10]
      IF D_A = 0 Then
        TxBufferIndex = 0
      EndIF
    
    while BF : wend                        ' loop while buffer is full
    wcol = 0                                    ' clear collision flag
    SSPBUF = TxBuffer[TxBufferIndex]
    while wcol 
    wcol = 0
    SSPBUF = TxBuffer[TxBufferIndex]
    wend
      hserout ["SSPBUF Outbyte = ",#SSPBUF," should be outbyte 16 or 31",13,10]
    CKP = 1                                     ' release clock, allowing read by master
    TxBufferIndex = TxBufferIndex + 1           ' increment index
    if TxBufferIndex = TxBufferlen then         ' all bytes have been tx
    TxBufferIndex = 0                           ' reset index            
    endif
                 
    I2C_Exit:
    Return
    
    main:
      pause 300
      hserout [13,10,"Start of program U8",13,10]
      hserout ["RxBuffer = "]
      for a = 0 to 2
        hserout [dec rxbuffer[a],"  "]
      next a
      hserout [13,10]
    loop:
    '  IF SSPIF = 1 Then
      IF BF = 1 Then
        hserout [13,10,"Went into I2C_Slave routine",13,10]
        GoSub i2c_slave
        hserout ["RxBuffer = "]
        for a = 0 to 2
          hserout [dec rxbuffer[a],"  "]
        next a
        hserout [13,10]
        hserout ["SSPCON1 = ",hex sspcon1,"  ",bin sspcon1,13,10]
        hserout ["SSPCON2 = ",hex sspcon2,"  ",bin sspcon2,13,10]
        hserout ["SSPSTAT = ",hex sspstat,"  ",bin sspstat,13,10]
        hserout ["SSPBUF = ",#sspbuf,13,10]
        
        if rxbufferindex = RxBufferLEN then           ' end of buffer transfer 
          WrData = 1
          rxbufferindex = 0
          rxbuffer[0] = 0
          rxbuffer[1] = 0
          rxbuffer[2] = 0
          hserout ["RxBuffer Cleared = "]
          for a = 0 to 2
            hserout [dec rxbuffer[a],"  "]
          next a
          hserout [13,10]
        endif
      endif
    
      SSPOV = 0
      WCOL = 0
      IF RxBuffer[0] = 15 Then
        hserout ["Got a 15",13,10]
        hserout ["  Readcount is: ",#readcnt,13,10]
        hserout ["Have a 16 to send if asked",13,10]
        TxBuffer[0] = 16
      EndIF
      
      IF RxBuffer[0] = 30 Then
        hserout ["Got a 30",13,10]
        hserout ["  Readcount is: ",#readcnt,13,10]
        hserout ["Have a 31 to send if asked",13,10]
        TxBuffer[0] = 31
      EndIF
    WrData=0  
    pause 50
    GoTo loop
    
    End
    Last edited by ScaleRobotics; - 22nd October 2010 at 13:24. Reason: added code tags

  7. #7


    Did you find this post helpful? Yes | No

    Default

    One thing I learn these days is that you cannot mess with the I2C timing.
    Looking at your code, I guess those hserouts are killing the protocol.
    I'll take a closer look at everything else tomorrow.

  8. #8


    Did you find this post helpful? Yes | No

    Default

    Try this code, I cleaned it up a lot. Slave address is 2.

    1) From the master, try to read 12 from the slave

    2) Try to send one byte (zero) to the slave and do something.

    I don't have MPASM so, it could be some small errors, check them.

    Code:
    'Oscillator Initialization
    DEFINE OSC 32 ' Osc. in MHz
    OSCCON = %01110000 
    OSCTUNE.6 = 1 
    ADCON0.0 = 0 ' Turns off A-to-D module
    ADCON1 = $0F ' Makes 100% port A digital 
    TRISA = %00000000
    CMCON = 7 ' Comparators Off
    
    DEFINE I2C_HOLD 1
    
    ' Define used register flags
    SSPIF VAR PIR1.3 ' SSP (I2C) interrupt flag
    SSPIE VAR PIE1.3 ' SSP Int Enable
    BF VAR SSPSTAT.0 ' SSP (I2C) Buffer Full
    R_W VAR SSPSTAT.2 ' SSP (I2C) Read/Write
    D_A VAR SSPSTAT.5 ' SSP (I2C) Data/Address
    CKP VAR SSPCON1.4 ' SSP (I2C) SCK Release Control
    SSPEN VAR SSPCON1.5 ' SSP (I2C) Enable
    SSPOV VAR SSPCON1.6 ' SSP (I2C) Receive Overflow Indicator
    WCOL VAR SSPCON1.7 ' SSP (I2C) Write Collision Detect
    'STRETCH VAR SSPCON2.0 ' SSP (I2C) Clock stretch
    
    '---------------- Alias pins -----------------------------------
    
    TRISC.3 = 1 ' input
    TRISC.4 = 1 ' input
    
    '--------------- Define used register flags -------------------
    
    STAT_BF VAR SSPSTAT.0 ' SSP (I2C) Buffer Full
    STAT_RW VAR SSPSTAT.2 ' SSP (I2C) Read/Write
    STAT_DA VAR SSPSTAT.5 ' SSP (I2C) Data/Address
    CKE VAR SSPSTAT.6 ' SSP (I2C) Data/Address
    
    '------------------- Rx Buffer definition --------------------
    RxBufferLEN CON 1
    RxBuffer VAR BYTE[Rxbufferlen]
    RxBufferIndex VAR BYTE
    
    '------------------ Tx Buffer definition ----------------------
    TxBufferLEN CON 1
    TxBuffer VAR BYTE[txbufferlen]
    TxBufferIndex VAR BYTE
    
    '------------------ Define constants ------------------------
    
    I2Caddress CON $2 ' Make address = 2
    
    ' Define constants
    
    
    datain VAR BYTE
    readcnt VAR BYTE 
    WRData VAR BYTE
    
    
    'SSPADD = My_I2C_address ' Set our address
    SSPADD = I2Caddress ' Set our address
    SSPCON2.7 = 0 ' General call address disabled
    SSPCON1 = $36 ' Set to I2C slave with 7-bit address
    SSPSTAT = 0
    SSPIE = 1 
    SSPIF = 0 
    RxBufferIndex = 0
    TxBufferIndex = 0
    bf = 0
    SSPOV = 0
    
    'Port C harware UART settings 
    DEFINE HSER_RCSTA 90h 
    DEFINE HSER_TXSTA 20h 
    DEFINE HSER_BAUD 9600 
    DEFINE HSER_CLROERR 1 
    
    '----------------- Initialization Done! -----------------------------
    GoTo main
    
    '-------------------------------------------------------------------------------
    
    I2C_Slave: ' I2C slave subroutine
              sspif = 0                            ' clear interrupt flag
              IF r_w = 1 Then I2C_Read                ' read data from us
              IF bf = 0 Then I2C_Exit               ' nothing in buffer so exit
              IF d_a = 1 Then I2C_Write                ' data for us (not address)
              IF sspbuf != i2caddress Then I2C_Exit ' clear the address from the buffer
              readcnt = 0                          ' mark as first read
    
              GoTo I2C_Exit
    
    '-------------------------------------------------------------------------------
    
    I2C_Write: ' I2C write data to us
           datain = sspbuf                   ' put buffer data into array
           rxbuffer[rxbufferindex] = datain
           rxbufferindex=rxbufferindex + 1
    
           IF rxbufferindex = rxbufferlen Then ' end of buffer transfer 
              wrdata = 1
              rxbufferindex = 0
           EndIF
    
    GoTo i2c_exit
    
    '-------------------------------------------------------------------------------
    I2C_Read: ' I2C read data from us
    
           IF d_a = 0 Then
              txbufferindex = 0
           EndIF
    
           While stat_bf : Wend                        ' koop while buffer is full
    
           wcol = 0                                    ' clear collision flag
           sspbuf = txbuffer[txbufferindex]
    
           While wcol 
                 wcol = 0
                 sspbuf = txbuffer[txbufferindex]
           Wend
    
           ckp = 1                                     ' release clock, allowing read by master
           txbufferindex = txbufferindex + 1           ' increment index
    
           IF txbufferindex = txbufferlen Then         ' all bytes have been tx
              txbufferindex = 0                        ' reset index            
           EndIF
    
    GoTo i2c_exit
    
    
    '-------------------------------------------------------------------------------
    
    I2C_Exit:
             sspov = 0
             wcol = 0
             wrdata = 0
    Return
    
    '-------------------------------------------------------------------------------
    
    '-------------------------------------------------------------------------------
    main:
          txbuffer[0] = 12 ' test value
    
          rxbuffer[0] = 0
    
          IF sspif = 1 Then
             GoSub i2c_slave
          EndIF
    
          Select Case rxbuffer[0]
                 Case 0
                       ' do something here, turn on LED for example.
          End Select
    
          GoTo main
    
    End

Similar Threads

  1. Problem with PICto PIC I2C MASTER-SLAVE
    By juanen19 in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 11th June 2013, 02:58
  2. PIC as I2C Slave
    By Mainul in forum General
    Replies: 4
    Last Post: - 5th January 2013, 13:23
  3. I2C Slave, config Vref - + in pic with ADC
    By sebapostigo in forum PBP Wish List
    Replies: 4
    Last Post: - 5th March 2007, 03:21
  4. Pic as an i2c slave
    By Robert Soubie in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 25th January 2007, 21:11
  5. Use pic as slave in I2C
    By robert0 in forum General
    Replies: 2
    Last Post: - 3rd February 2006, 19:26

Members who have read this thread : 2

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts