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

    Sure! Let me know if you need anything else

    Master 16f877 - External 4Mhz Crystal:
    Code:
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    ' Master
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    
    DEFINE OSC 4
    
    'OPTION_REG.7 = 0
    
    ADCON1 = 7
    
    '------------------------------------------------------------------------------
    
    DEFINE I2C_SLOW 1
    
    TRISB.5 = 1
    TRISB.7 = 1
    
    '------------------------------------------------------------------------------
    
    scl VAR PORTB.5		' i2c clock input
    sda VAR PORTB.7     ' i2c data input
    
    '------------------------------------------------------------------------------
    
    I2Caddress VAR BYTE
    
    valor VAR BYTE
    
    '------------------------------------------------------------------------------
    
    ' Set LCD Data port
    DEFINE LCD_DREG PORTD
    ' Set starting Data BIT (0 OR 4) IF 4-BIT bus
    DEFINE LCD_DBIT 4
    ' Set LCD Register Select port
    DEFINE LCD_RSREG PORTC
    ' Set LCD Register Select BIT
    DEFINE LCD_RSBIT 6
    ' Set LCD Enable port
    DEFINE LCD_EREG PORTC
    ' Set LCD Enable BIT
    DEFINE LCD_EBIT 7
    ' Set LCD bus size (4 OR 8 bits)
    DEFINE LCD_BITS 4
    ' Set number of lines ON LCD
    DEFINE LCD_LINES 2
    ' Set command delay time in us
    DEFINE LCD_COMMANDUS 2000
    ' Set Data delay time in us
    DEFINE LCD_DATAUS 50
    
    '------------------------------------------------------------------------------
    
    Pause 500       ' Wait for LCD to startup
    LCDOut $fe, 1
    LCDOut $fe, "Daniel"
    Pause 500       ' Wait for LCD to startup
    
    valor = 0
    
    '------------------------------------------------------------------------------
    
    main:
          I2Caddress = $3
    
          LCDOut $fe, 1
          LCDOut "Writting 1 - LED ON..."
          Pause 500
    
          I2CWrite SDA, SCL, I2Caddress, [6], bogus ' Write offset to slave
          Pause 500
    
          LCDOut $fe, 1
          LCDOut "Writting 1 - LED OFF..."
          Pause 500
    
          I2CWrite SDA, SCL, I2Caddress, [8], bogus ' Write to slave
          Pause 500
    
          LCDOut $fe, 1
          LCDOut "Reading 1..."
          Pause 500
    
          I2CRead SDA, SCL, I2Caddress, [valor], bogus ' Read from slave
          LCDOut $fe, 1
          LCDOut "Value: ", DEC valor
          Pause 500
    
          '--------
    
          I2Caddress = $5
    
          LCDOut $fe, 1
          LCDOut "Writting 2 - LED ON..."
          Pause 500
    
          I2CWrite SDA, SCL, I2Caddress, [4], bogus ' Write to slave
          Pause 500
    
          LCDOut $fe, 1
          LCDOut "Writting 2 - LED OFF..."
          Pause 500
    
          I2CWrite SDA, SCL, I2Caddress, [10], bogus ' Write to slave
          Pause 500
    
          LCDOut $fe, 1
          LCDOut "Reading 2..."
          Pause 500
    
          I2CRead SDA, SCL, I2Caddress, [valor], bogus ' Read from slave
          LCDOut $fe, 1
          LCDOut "Value: ", DEC valor
          Pause 500
    
          '--------
    
          GoTo main       ' Do it forever
    
    '-------------------------------------------------------------------------------
    
    bogus:
    		LCDOut $fe,1, "Time out"	' I2C command timed out
    		Pause 500
    
    		GoTo main
    
    '-------------------------------------------------------------------------------
    
    End
    
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    Last edited by DanPBP; - 19th February 2009 at 19:34.

  2. #2


    Did you find this post helpful? Yes | No

    Default

    1' Slave - 16F88 - Internal 8Mhz
    Code:
    '------------------------------------------------------------------------------
    '------------------------------------------------------------------------------
    ' Slave
    '------------------------------------------------------------------------------
    '------------------------------------------------------------------------------
    
    @ device pic16f88, intrc_osc_noclkout	' system clock options
    @ device pic16f88, wdt_on			' watchdog timer
    @ device pic16f88, pwrt_on			' power-on timer
    @ device pic16f88, mclr_off			' master clear options (internal)
    @ device pic16f88, protect_off		' code protect off
    
    '--- set device ---------------------------------------------------------------
    
    DEFINE OSC 8
    OSCCON = %01110001 '8mhz
    
    '------------------------------------------------------------------------------
    
    CMCON = 7
    ADCON1 = 0 ' Disable A/D converter
    ADCON0 = 0
    ANSEL = 0 ' all analog pins to digital
    
    '--- tris port config here (don't use SCL & SDA pins other than I2C) ----------
    
    DEFINE I2C_HOLD 1
    
    TRISB.1 = 1
    TRISB.4 = 1
    
    '--- Alias pins ---------------------------------------------------------------
    
    SDADIR VAR TRISB.1
    SCLDIR VAR TRISB.4
    
    '--- Define here your variables and alias -------------------------------------
    
    LEDT VAR PORTA.2
    LEDL VAR PORTB.7
    LEDM VAR PORTB.6
    LEDR VAR PORTB.5
    readcnt VAR BYTE
    datain VAR BYTE
    WrData VAR BYTE
    
    '--- Define used register flags ------------------------------------------------
    
    SSPIF               VAR PIR1.3    ' SSP (I2C) interrupt flag
    SSPIE               VAR PIE1.3 
    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 SSPCON.4  ' SSP (I2C) SCK Release Control
    SSPEN               VAR SSPCON.5  ' SSP (I2C) Enable
    SSPOV               VAR SSPCON.6  ' SSP (I2C) Receive Overflow Indicator
    WCOL                VAR SSPCON.7  ' SSP (I2C) Write Collision Detect
    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 defintion ------------------------------------------------------
    
    RxBufferLEN         CON 1       
    RxBuffer            VAR BYTE[Rxbufferlen]
    RxBufferIndex       VAR BYTE
    
    '--- Tx Buffer defintion ------------------------------------------------------
    
    TxBufferLEN         CON 1
    TxBuffer            VAR BYTE[txbufferlen]
    TxBufferIndex       VAR BYTE
    
    '--- Define constants ---------------------------------------------------------
    
    I2Caddress          CON $3 ' Make address = 3
    
    '--- Initialize I2C slave mode ------------------------------------------------
    
    SCLDIR = 1          ' SCL must be an input before enabling interrupts
    SDADIR = 1   
    SSPADD = I2Caddress ' Set our address
    SSPCON = $36        ' Set to I2C slave with 7-bit address
    SSPSTAT = 0
    SSPIE = 1 
    SSPIF = 0 
    RxBufferIndex = 0
    TxBufferIndex = 0
    
    '--- Initialization Done! -----------------------------------------------------
    
    GoTo main
    
    '--- I2C subroutine  ----------------------------------------------------------
    
    i2cslave:                                      ' I2C slave subroutine
              SSPIF = 0                            ' Clear interrupt flag
              IF R_W = 1 Then i2crd                ' Read data from us
              IF BF = 0 Then i2cexit               ' Nothing in buffer so exit
              IF D_A = 1 Then i2cwr                ' Data for us (not address)
              IF SSPBUF != I2Caddress Then i2cexit ' Clear the address from the buffer
              readcnt = 0                          ' Mark as first read
              GoTo i2cexit
    
    i2cwr:                                ' 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 i2cexit
    
    i2crd:                                      ' I2C read data from us
           IF D_A = 0 Then
              TxBufferIndex = 0
           EndIF
    
           While STAT_BF : Wend                        ' loop 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
                 
    i2cexit:
             Return
    
    '--- End I2C subroutine  ------------------------------------------------------
    
    Main:
          txbuffer = 12
    
          IF SSPIF = 1 Then
             GoSub i2cslave
          EndIF
    
          SSPOV = 0
          WCOL = 0
    
          Select Case RxBuffer[0]
                 Case 6
                         High LEDT
                 Case 8
                         Low LEDT
          End Select
    
          WrData=0  
          GoTo Main
    
    
    '------------------------------------------------------------------------------
    
    End
    
    '------------------------------------------------------------------------------
    '------------------------------------------------------------------------------

  3. #3


    Did you find this post helpful? Yes | No

    Default

    2' Slave - 16F88 - Internal 8Mhz
    Code:
    '------------------------------------------------------------------------------
    '------------------------------------------------------------------------------
    ' Slave
    '------------------------------------------------------------------------------
    '------------------------------------------------------------------------------
    
    @ device pic16f88, intrc_osc_noclkout	' system clock options
    @ device pic16f88, wdt_on			' watchdog timer
    @ device pic16f88, pwrt_on			' power-on timer
    @ device pic16f88, mclr_off			' master clear options (internal)
    @ device pic16f88, protect_off		' code protect off
    
    '--- set device ---------------------------------------------------------------
    
    DEFINE OSC 8
    OSCCON = %01110001 '8mhz
    
    '------------------------------------------------------------------------------
    
    CMCON = 7
    ADCON1 = 0 ' Disable A/D converter
    ADCON0 = 0
    ANSEL = 0 ' all analog pins to digital
    
    '--- tris port config here (don't use SCL & SDA pins other than I2C) ----------
    
    DEFINE I2C_HOLD 1
    
    TRISB.1 = 1
    TRISB.4 = 1
    
    '--- Alias pins ---------------------------------------------------------------
    
    SDADIR VAR TRISB.1
    SCLDIR VAR TRISB.4
    
    '--- Define here your variables and alias -------------------------------------
    
    LEDT VAR PORTA.2
    LEDL VAR PORTB.7
    LEDM VAR PORTB.6
    LEDR VAR PORTB.5
    readcnt VAR BYTE
    datain VAR BYTE
    WrData VAR BYTE
    
    '--- Define used register flags ------------------------------------------------
    
    SSPIF               VAR PIR1.3    ' SSP (I2C) interrupt flag
    SSPIE               VAR PIE1.3 
    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 SSPCON.4  ' SSP (I2C) SCK Release Control
    SSPEN               VAR SSPCON.5  ' SSP (I2C) Enable
    SSPOV               VAR SSPCON.6  ' SSP (I2C) Receive Overflow Indicator
    WCOL                VAR SSPCON.7  ' SSP (I2C) Write Collision Detect
    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 defintion ------------------------------------------------------
    
    RxBufferLEN         CON 1       
    RxBuffer            VAR BYTE[Rxbufferlen]
    RxBufferIndex       VAR BYTE
    
    '--- Tx Buffer defintion ------------------------------------------------------
    
    TxBufferLEN         CON 1
    TxBuffer            VAR BYTE[txbufferlen]
    TxBufferIndex       VAR BYTE
    
    '--- Define constants ---------------------------------------------------------
    
    I2Caddress          CON $5 ' Make address = 5
    
    '--- Initialize I2C slave mode ------------------------------------------------
    
    SCLDIR = 1          ' SCL must be an input before enabling interrupts
    SDADIR = 1   
    SSPADD = I2Caddress ' Set our address
    SSPCON = $36        ' Set to I2C slave with 7-bit address
    SSPSTAT = 0
    SSPIE = 1 
    SSPIF = 0 
    RxBufferIndex = 0
    TxBufferIndex = 0
    
    '--- Initialization Done! -----------------------------------------------------
    
    GoTo main
    
    '--- I2C subroutine  ----------------------------------------------------------
    
    i2cslave:                                      ' I2C slave subroutine
              SSPIF = 0                            ' Clear interrupt flag
              IF R_W = 1 Then i2crd                ' Read data from us
              IF BF = 0 Then i2cexit               ' Nothing in buffer so exit
              IF D_A = 1 Then i2cwr                ' Data for us (not address)
              IF SSPBUF != I2Caddress Then i2cexit ' Clear the address from the buffer
              readcnt = 0                          ' Mark as first read
              GoTo i2cexit
    
    i2cwr:                                ' 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 i2cexit
    
    i2crd:                                      ' I2C read data from us
           IF D_A = 0 Then
              TxBufferIndex = 0
           EndIF
    
           While STAT_BF : Wend                        ' loop 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
                 
    i2cexit:
             Return
    
    '--- End I2C subroutine  ------------------------------------------------------
    
    Main:
          txbuffer = 24
    
          IF SSPIF = 1 Then
             GoSub i2cslave
          EndIF
    
          SSPOV = 0
          WCOL = 0
    
          Select Case RxBuffer[0]
                 Case 4
                         High LEDT
                 Case 10
                         Low LEDT
          End Select
    
          WrData=0  
          GoTo Main
    
    
    '------------------------------------------------------------------------------
    
    End
    
    '------------------------------------------------------------------------------
    '------------------------------------------------------------------------------

  4. #4


    Did you find this post helpful? Yes | No

    Default Thank You!

    Daniel: Thanks to you and others in this great forum for sharing....It is so much easier to understand when you can see code that is working and is well commented.

    Thanks again to all the generous people on this forum!

    RC

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


    Did you find this post helpful? Yes | No

    Default

    I think, this part could be written better:

    Code:
           wcol = 0                                    ' clear collision flag
           SSPBUF = TxBuffer[TxBufferIndex]
    
           While wcol 
                 wcol = 0
                 SSPBUF = TxBuffer[TxBufferIndex]
           Wend
    this is much shorter:

    Code:
           Repeat
                 wcol = 0
                 SSPBUF = TxBuffer[TxBufferIndex]
           Until !wcol
    and works, too.
    PBP 2.50C, MCS+ 3.0.0.5, MPLAB 8, MPASM 5.14, ASIX Presto, PoScope, mE mikroBasic V7.2, PICKIT2

  6. #6


    Did you find this post helpful? Yes | No

    Default

    Thanks for the update! This should be a hot topic now!

    Btw, how many times I have seen this topic on the forum without any answers because: "my code that works is proprietary and I cannot share it" or worst: "RTFM!". If the only thing you have to say is that, keep it to yourself! Or, the other one I hate: "did you try the example from melabs site?" The one that everyones says it doesn't work? Yes!!!

    Thanks a lot to Al, the I2C slave routine is working great and he was kind enough to share it with all of us. You're great Sr.!

  7. #7
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by danielhr77 View Post
    Thanks for the update! This should be a hot topic now!

    Btw, how many times I have seen this topic on the forum without any answers because: "my code that works is proprietary and I cannot share it"
    Translation: My code does not work, but I won't admit it. At least 50% of the time <br> Anyway thanks Daniel and AL, Ralf , mister_e, Big Wumpus Something new to play with.
    Last edited by Archangel; - 7th March 2009 at 06:38.
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

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, 03:58
  2. PIC as I2C Slave
    By Mainul in forum General
    Replies: 4
    Last Post: - 5th January 2013, 14:23
  3. I2C Slave, config Vref - + in pic with ADC
    By sebapostigo in forum PBP Wish List
    Replies: 4
    Last Post: - 5th March 2007, 04:21
  4. Pic as an i2c slave
    By Robert Soubie in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 25th January 2007, 22:11
  5. Use pic as slave in I2C
    By robert0 in forum General
    Replies: 2
    Last Post: - 3rd February 2006, 20: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