I2C Slave with a PIC


Closed Thread
Results 1 to 40 of 130

Hybrid View

  1. #1


    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

  2. #2
    Join Date
    Oct 2004
    Location
    Hangover, Germany
    Posts
    289


    Did you find this post helpful? Yes | No

    Exclamation

    You have to set the CKP-bit even after a WRITE-operation.
    Try to disable the HSEROUT-lines.
    Maybe this command will alter the TRISC-register, which will kill the I2C-engine.
    Sometime, you should clear the OV-bit...
    PBP 2.50C, MCS+ 3.0.0.5, MPLAB 8, MPASM 5.14, ASIX Presto, PoScope, mE mikroBasic V7.2, PICKIT2

  3. #3
    Join Date
    Mar 2008
    Location
    Gerogetown, Texas
    Posts
    94


    Did you find this post helpful? Yes | No

    Default

    I have been trying to get a 18F2620 to run as a slave. i ran across this in the ERRATA for this device.
    Code:
    43. Module: MSSP (I2C Slave)
    The MSSP module operating in I2C, 7-Bit Slave
    mode (SSPM3:SSPM0 = 0110) may not send a
    NACK bit (/ACK) in response to receiving the slave
    address loaded in SSPADD<7:1>. Addresses are
    in one of these ranges:
    • 0x00 to 0x07
    • 0x78 to 0x7F
    These addresses were reserved by Philips® Semiconductors
    in “The I2C Specification”, Version 2.1,
    released January 2000. Section 10.1 “Definition of
    bits in the first byte” defines the purposes of these
    addresses.
    This specification can be found at:
    http://www.semiconductors.philips.com/i2c
    Work around
    This version of the silicon does not respond to
    slave addresses in the ranges previously listed.
    Use either of these work arounds:
    • Change the 7-bit slave address in SSPADD to
    an address in the range of 0x08 to 0x77.
    • Use Revision B silicon. This version of silicon
    removes this issue’s addressing restrictions.
    I have gotten sporadic results for the master reading the slave in the following code.

    Darrell's Instant Interrupt

    Code:
        '   Interrupt definition   
        '   ====================
            '   USB interrupt used to keep USB connection alive
    INCLUDE "DT_INTS-18.bas"    ' Base Interrupt System
    INCLUDE "ReEnterPBP-18.bas"     ' Include if using PBP interrupts
    
    ASM
    INT_LIST  macro    ; IntSource,         Label,  Type, ResetFlag?
            INT_Handler    SSP_INT,  _I2C_Int,   PBP,  yes
    
        endm
        INT_CREATE               ; Creates the interrupt processor
    endasm
    
    ''----------------- Initialization Done! -----------------------------
    
    @ INT_ENABLE  SSP_INT     ; Master Synchronous Serial Port Interrupt Flag bit. The transmission/reception is complete
    'txbuffer = 0
    The Interrupt handler

    Code:
    I2C_Int:
    If R_W = 0 then
        if D_A = 0 then
           address = SSPBUF
        else
    
    Still working on master to slave write
    '        if bf = 1 then
    '           if rxcnt <= rxbufferlen then
    '              datain[rxcnt] = SSPBUF
    '              rxcnt = rxcnt + 1
    '              if rxcnt = rxbufferlen then rxcnt = 0
    '           endif   
              
              
            EndIF 
        endif
    else
        dataout = SSPBUF     'dummy read
        if txcnt > 0 then
           SSPBUF = txbuffer[txoutptr]
           txoutptr = txoutptr + 1       
                  if txoutptr = txbufferlen then txoutptr = 0
           txcnt = txcnt - 1
        else
        'no byte to send
        endif       
    endif
    CKP = 1 
    @ INT_RETURN
    and the main loop. I want to send three bytes to the master. In this case "three sevens".

    Code:
    Main:
    SSPOV = 0
    WCOL = 0
         
         if txcnt < txbufferlen - 1 then
                        
                TxBuffer[txinptr] = 7
                txinptr = txinptr + 1
                if txinptr = txbufferlen then txinptr = 0
               
                txcnt = txcnt + 1
                
        endif
    
    WrData=0 
    
    
    
    goto main 
    end
    I did the same slave program in "C" and it works well.

    The Master is reading and writing to a RTC module and a bank of 4 24lc256 EEProms and a I2C Port expander with out any problems.

    It is getting close

    Take care

    Dave

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


    Did you find this post helpful? Yes | No

    Lightbulb That makes sense...

    Although the 16F guys have been having good luck with low addresses, it makes sense that the errata sheet would point out the old Phillips rule about low addresses. I haven't tried an address above $08 before... gotta go give that a shot too. I'll report back with any results, good or bad.

    Rswain

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


    Did you find this post helpful? Yes | No

    Unhappy New attempts

    Today I tried changing the Master and Slave addresses to higher numbers. I tried $26, $A6, and $02 just for good measure. They all responded with the same results; the slave sees the address, matches to its own, sets the interrupt flag, sets the Buffer Full flag, loads the address byte into the SSPBUF and I can read it from there. Although I reported before that the Slave wasn't sending an ACK, I think I was wrong. When I poll the ACKSTAT in the Master, it comes back with a "0" which I thought was NO ACK, but in fact a 0 is reporting a good ACK.

    I've also switched to 18F4685 on both Master and Slave just eliminate the possiblilty of bad chips. Same results.

    I took Daniel's suggestion to try to read from the Slave instead of sending to it. The slave responds by loading the first digit in its SSPBUF but I'm not seeing it show up at the Master.

    I notice that the Slave's D_A (SSPSTAT.5 ' SSP Data not Address) is always showing "1" for DATA and never have I seen a "0" for ADDRESS. Is that OK? How would that bit get changed?

    Rswain
    Last edited by rswain; - 14th March 2009 at 02:55.

  6. #6


    Did you find this post helpful? Yes | No

    Default

    I'll try to buy a 18F2620 this week and run a few test Hope I can get it here, I live in Argentina, it's not always easy to find those "big brothers" ...

    EDIT: I found a 18F452 laying around on the desk, will this serve the purpose???
    Last edited by DanPBP; - 14th March 2009 at 03:47.

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


    Did you find this post helpful? Yes | No

    Default Most any 18F will do

    Daniel - I'd be happy if any 18F would work. I'm starting to think something's wrong with PBP and 18F.

    Thanks for your continued attempts to beat this problem into submission!

    I'm going to switch to 16F877A (the old standby to see if I can get them to talk - once I get that, then we'll come back here and try again!

    Robert

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