I2C Slave with a PIC - Page 2


Closed Thread
Page 2 of 4 FirstFirst 1234 LastLast
Results 41 to 80 of 130
  1. #41
    Join Date
    Mar 2008
    Location
    Gerogetown, Texas
    Posts
    94


    Did you find this post helpful? Yes | No

    Default Pic18F2620 Slave working

    Here is the code that is working for me. I am sending three bytes to the slave. In this example 10, 20 and 30. The slave adds 1 and sends back 11, 21 and 31.

    Here is a snipit of the master portion.
    Code:
     I2Caddress = $0A
     I2CWrite i2cdat,i2cclk,I2Caddress,[10,20,30],NoGo
     pauseus 5
     i2cread i2cdat,i2cclk,i2caddress,[tp_x, tp_y, tp_dp],NoGo2      
     pauseus 5
        
           USBBuffer[0] = tp_x
           USBBuffer[1] = tp_y
           USBBuffer[2] = tp_dp
           USBBuffer[3] = 0
           gosub dousbout        ' I am using USB as a debugger
    pause 100
    goto mainmenu
    NoGo:
           USBBuffer[0] = 1
           USBBuffer[1] = 2
           USBBuffer[2] = 3
           USBBuffer[3] = 0
           gosub dousbout
    goto mainmenu
    
    NoGo2:
           USBBuffer[0] = 4
           USBBuffer[1] = 5
           USBBuffer[2] = 6
           USBBuffer[3] = 0
           gosub dousbout
    goto mainmenu
    Here is the full slave. Pic18F2620 @ 20Mhz

    Code:
    asm
            __CONFIG    _CONFIG1H, _OSC_HS_1H     
            __CONFIG    _CONFIG2H, _WDT_OFF_2H & _WDTPS_512_2H
            __CONFIG    _CONFIG3H, _PBADEN_OFF_3H
            __CONFIG    _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
    endasm
    DEFINE OSC 20
    'DEFINE ADC_BITS 10
    'DEFINE ADC_CLOCK 3
    'DEFINE ADC_SAMPLEUS 50
    
    Define I2C_SLOW 1
    DEFINE I2C_HOLD 1
    
    'OSCCON = %01110001 '8mhz
    'OSCTUNE.6 = 1  ' PLL selected 32mhz clock
    
    ' PicBasic Pro I2C slave program 
    ' Alias pins
    scl     VAR     PORTC.3         ' I2C clock input
    sda     VAR     PORTC.4         ' I2C data input
    
    'ADCON2.7=1
    ADCON1 = $F     '$B       'an1-an3 analog remainder digital
    CMCON = 7         'PortA Digital
    '
    '---------------- Alias pins -----------------------------------
    
    'SCLDIR              var TRISC.3 
    'SDADIR              var TRISC.4
    
    '--------------- 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 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
    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
    WrData              var byte
    j                   var byte
    '------------------- Rx Buffer defintion --------------------
    RxBufferLEN         con 3           
    RxBuffer            var byte[Rxbufferlen]
    RxBufferIndex       var byte
    RxCnt               var byte
    rxcnt = 0
    '------------------ Tx Buffer defintion ----------------------
    TxBufferLEN         con 3
    TxBuffer            var byte[txbufferlen]
    TxBufferIndex       var byte
    TxCnt               var byte
    txcnt = 0
    '------------------ Define constants ------------------------
    rxinptr             var byte
    rxoutptr            var byte
    txinptr             var byte
    txoutptr            var byte
    rxinptr = 0
    rxoutptr = 0
    txinptr = 0
    txoutptr = 0
    
    I2Caddress          CON $0A                  ' Make address = 2
    
    ' Allocate RAM
    result	VAR		BYTE			' ADC result
    DataIn 	VAR     BYTE[8]			' Data in 
    DataOut	VAR     BYTE[8]			' Data out array
    readcnt	VAR     BYTE            ' I2C read count
    
    readcnt = 0				' Zero counter
    
    
    '****************************************************************
    '       Variables used in the program. 
    '       
    '****************************************************************
    
    transdata              var byte
    transbit7              var transdata.7
    Tdata                  var word
    txdata                 var word
    tydata                 var word
    txcomp                 var word
    tycomp                 var word
    tx                     var word
    ty                     var word
    tvalue                 var word
    txcomp=0 
    tycomp=0 
    tx=0
    ty=0
    tvalue=0
    PD      var            bit 'pen down flag
    address var            byte
    
    ' -------------- Initialize I2C slave mode ------------------------
    
    'SCLDIR = 1          ' SCL must be an input before enabling interrupts
    'SDADIR = 1   
    SSPADD = I2Caddress ' Set our address
    SSPCON1 = $36        ' Set to I2C slave with 7-bit address
    SSPCON2.0 = 1
    SSPSTAT = 0
    SSPIE = 1 
    SSPIF = 0 
    RxBufferIndex = 0
    TxBufferIndex = 0
    
    
    'LED1  var PORTC.1
    
        '   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
    portc.1 = 1'high led1
    goto Main
    '*****************************************************************************
    
    
    '------------------------- I2C subroutine  -------------------------------- 
    I2C_Int:
    
    If R_W = 0 then     'Write from master
        if D_A = 0 then  ' It's address from master
           address = SSPBUF ' do nothing
           rxcnt = 1
           rxinptr = 0
           rxoutptr = 0
           txinptr = 0
           txoutptr = 0
        else
            WCOL = 0
            sspov = 0
            if bf = 1 then   'There is data in buffer
               if rxcnt < rxbufferlen  then
                  rxbuffer[rxinptr] = SSPBUF
                  rxinptr = rxinptr + 1
                  if rxinptr = rxbufferlen then rxinptr = 0
               endif   
               rxcnt = rxcnt + 1
               
            EndIF 
        endif
    else   ' Read by master
           
            dataout = SSPBUF     'dummy read
    if bf = 0 then   ' if buffer is empty
            if txcnt > 0 then  ' Is there a byte to transfer
               SSPBUF = txbuffer[txoutptr]   'get the byte abd send it
               txoutptr = txoutptr + 1       
                      if txoutptr = txbufferlen then txoutptr = 0
               txcnt = txcnt - 1
            else
            'no byte to send
            endif       
    endif
    endif
    
    sspif = 0
    CKP = 1 
    @ INT_RETURN
    
    
    
    ' -------------------------end I2C subroutine  -------------------------------- 
    
    '--------------------[ main program loop]---------------------------------------
    Main:
    'SSPOV = 0
    'WCOL = 0
         'INTCON.7 = 0   'trrn off interrupt
         if txcnt < txbufferlen  then
              
                TxBuffer[txinptr] = rxbuffer[txinptr] | %00000001     ' add "1" to the data in
                txinptr = txinptr + 1
                if txinptr = txbufferlen  then txinptr = 0
    
                txcnt = txcnt + 1
                'INTCON.7 = 1   'turn on interrupt
        endif
        if rxcnt != 0 then
           datain = rxbuffer[rxoutptr]
           rxoutptr = rxoutptr + 1
           if rxoutptr = rxbufferlen  then
              rxoutptr = 0
           endif
           rxcnt = rxcnt - 1
    
    
        endif
    
    
    WrData=0 
    
    
    
    goto main 
    end
    Disregard all the extra stuff, I am using this slave a Touch Screen controller.

    Thanks

    Dave

  2. #42
    Join Date
    Oct 2008
    Location
    Southern California
    Posts
    17


    Did you find this post helpful? Yes | No

    Thumbs up Making some headway now

    Group,

    I'm back using the 18F4685, one in Master and one in Slave. I'm now able to read from the Slave, 3 digits (and their even the right ones!). I set up a fast loop to read the digits on the Master side and do nothing but send the data in a fast loop on the Slave side. (Will post both sides soon).

    The problem is still the same on sending data from the Master to the Slave. The address gets there, matches, sets the SSPIF and BF, but also I get the SSPOV (overflow) bit set. Even on the first attempt to read the buffer, the OV is already set. There must be some "slow it down" handshaking not happening just right. Has anyone had luck sending multiple bytes to the Slave?

    rswain

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


    Did you find this post helpful? Yes | No

    Default

    The attachments are the latest code (starting to work on the 18F4685). Still not able to send Master to Slave - Slave gets OVERFLOW flag.
    Rswain
    Last edited by rswain; - 15th March 2009 at 05:57.

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


    Did you find this post helpful? Yes | No

    Thumbs down

    You don't empty the SSPBUF after receiving the adress and the first data-byte gives you an buffer-overrun.....
    PBP 2.50C, MCS+ 3.0.0.5, MPLAB 8, MPASM 5.14, ASIX Presto, PoScope, mE mikroBasic V7.2, PICKIT2

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


    Did you find this post helpful? Yes | No

    Cool More Progress

    BigWumpus,

    You're right. I wasn't getting the bytes out of the Buffer fast enough. I tried a few things to empty the buffer faster and that helped. Now I don't have an Overflow problem, but I've managed to screw up the result that goes back to the Master when it asks for data from the Slave. I've got to go back double check the emptying and filling of the buffer.

    I'm going to go back a step and make sure I've got the Master pulling data from the Slave perfectly. I'll take it up to 20 bytes or so to make sure. Once that's done, then I'll work again on sending data from the Master to the Slave. When I quit yesterday, I had it receiving two bytes (three if you count the address byte).

    We're getting very close. I'll post working code as I accomplish these tasks.

    Rswain

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


    Did you find this post helpful? Yes | No

    Post

    -------------------------deleted-------------------------
    Last edited by BigWumpus; - 16th March 2009 at 17:10. Reason: CODE-code is messy
    PBP 2.50C, MCS+ 3.0.0.5, MPLAB 8, MPASM 5.14, ASIX Presto, PoScope, mE mikroBasic V7.2, PICKIT2

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


    Did you find this post helpful? Yes | No

    Cool

    Try this:

    I2C_Slave: ' I2C slave subroutine
    IF R_W Then

    I2C_Read: ' I2C read data from us ' THIS SECTION IS WORKING!
    IF !d_a Then txbufferindex = 0
    Repeat
    Repeat
    Until !bf
    wcol = 0:sspbuf = txbuffer[txbufferindex]
    Until !wcol
    txbufferindex = txbufferindex + 1 ' increment index
    IF txbufferindex = txbufferlen Then txbufferindex = 0 ' all bytes have been tx reset index

    Else

    IF !D_A Then
    InByte=SSPBUF 'here is your error ! You don't empty the buffer!!!!!!!!!!!!!!!!!!!!!!
    else

    I2C_Write: ' I2C write data to us ' THIS SECTION NOT WORKING
    If BF Then
    InByte = SSPBUF ' Put buffer data into array
    if rxbufferindex<rxbufferlen then Rxbuffer[Rxbufferindex] = InByte:rxbufferindex = rxbufferindex + 1
    ENDIF
    SSPov = 0 ' Clear overflow flag

    endif
    endif

    ckp = 1 ' release clock, allowing read by master (makes no difference (yet))
    SSPIF=0



    The CODE-code is messy
    PBP 2.50C, MCS+ 3.0.0.5, MPLAB 8, MPASM 5.14, ASIX Presto, PoScope, mE mikroBasic V7.2, PICKIT2

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


    Did you find this post helpful? Yes | No

    Default

    Here is a working 18F2455 I2C slave. It will receive or send any amount of bytes you choose. The slave will not work if USB is enable on the chip.

    In this example the Master is sending 0 to 127 on byte(0), and fixed data on Bytes 1 and 2.

    The Slave sends three bytes back, tests the received byte(0) and lights a couple of leds. When the master sends (Byte(0) = 4), the slave ends three different bytes back. I also have eight leds connected to the slave, four on PortB 4-7 and four on PortA 0-3. These leds display the value of the received Byte(0).



    Slave code

    Code:
    '*  Date    : 3/17/2009                                         *
    '*  Version : 1.0                                               *
    '*  Notes   :                                                   *
    '*          :  18F2550 Slave I2c                                *
    '****************************************************************
    asm     __CONFIG    _CONFIG1L, _PLLDIV_5_1L & _FCMEN_OFF_1H
            __CONFIG    _CONFIG1H, _FOSC_HS_1H    
            __CONFIG    _CONFIG2L, _VREGEN_OFF_2L
            __CONFIG    _CONFIG2H, _WDT_OFF_2H & _WDTPS_512_2H
            __CONFIG    _CONFIG3H, _PBADEN_OFF_3H
            __CONFIG    _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
    endasm
    DEFINE OSC 20          
    Define I2C_SLOW 1     'At this clock speed this needed to be added to make it work.
    DEFINE I2C_HOLD 1
    
    ADCON1 = $F       'All digital
    CMCON = 7         'PortA Digital
    
    
    '--------------- 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 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
    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
    WrData              var byte
    j                   var byte
    '------------------- Rx Buffer defintion --------------------
    RxBufferLEN         con 16           
    RxBuffer            var byte[Rxbufferlen]
    RxBufferIndex       var byte
    RxCnt               var byte
    rxcnt = 0
    '------------------ Tx Buffer defintion ----------------------
    TxBufferLEN         con 3
    TxBuffer            var byte[txbufferlen]
    TxBufferIndex       var byte
    TxCnt               var byte
    txcnt = 0
    '------------------ Define vars ------------------------
    rxinptr             var byte
    rxoutptr            var byte
    txinptr             var byte
    txoutptr            var byte
    rxinptr = 0
    rxoutptr = 0
    txinptr = 0
    txoutptr = 0
    I2Caddress          CON $02                  ' Make address = 2
    
    result	            VAR		BYTE			' ADC result
    DummyRead           var     byte
    DataIn 	            VAR     BYTE[8]			' Data in 
    DataOut	            VAR     BYTE[8]			' Data out array
    readcnt	            VAR     BYTE            ' I2C read count
    address             var     byte
    StatMask            var     byte
    StatMask = %00101101
    readcnt = 0				' Zero counter
    ' PicBasic Pro I2C slave program 
    ' Alias pins
    Led1    var PORTC.0
    LED2    Var PORTC.1
    
    
    
    
    scl     VAR     PORTB.1         ' I2C clock input
    sda     VAR     PORTB.0         ' I2C data input
    TRISB = %00000011
    TRISC = %00000000
    TRISA = %00000000
    LATB = $F0
    'PortA= $0F
    PORTA = $0F      'leds off  on A port
    PORTB = $F0       ' Leds off on B port
    
    
    high LED1
    high led2
    
    ' -------------- Initialize I2C slave mode ------------------------
    SSPADD = I2Caddress ' Set our address
    SSPCON1 = $36        ' Set to I2C slave with 7-bit address
    SSPCON2 = %00000000   ' clear sspcon2
    SSPCON2 = %00000001   'enable clock stretching
    SSPSTAT = %00000000    ' clear sspstat
    SSPIE = 1               'Enable MSSP interrupt enable bit
    SSPIF = 0               'Clear MSSP interrupt flag
    RxBufferIndex = 0
    TxBufferIndex = 0
    Temp            var  byte
    RxIndex         var  byte
    TxIndex         var  byte
    Stat            var  byte
    
    dataout[0] = 41     ' just some data to start with
    dataout[1] = 122
    dataout[2] = 103
    dataout[3] = 4
    
    
    '    '   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
    
    
    @ INT_ENABLE  SSP_INT     ; Master Synchronous Serial Port Interrupt Flag bit. The transmission/reception is complete
    
    '----------------------[ Skip over subs ]--------------------------------------
    goto Programstart
    
    I2C_Int:
    
    If R_W = 0 then                            'Write from master
        if D_A = 0 then                        ' It's address from master
           address = SSPBUF                    ' do nothing
           rxinptr = 0                          ' Clear counters
           rxoutptr = 0
        else
            WCOL = 0
            sspov = 0
            if bf = 1 then                     'There is data in buffer
               if rxcnt < rxbufferlen  then
                  rxbuffer[rxinptr] = SSPBUF
                  rxinptr = rxinptr + 1
                  if rxinptr = rxbufferlen then rxinptr = 0
               endif   
               rxcnt = rxcnt + 1
               
            EndIF 
        endif
    else                                   ' Read by master
        if SSPSTAT = %00001101 then        'last byte was an address byte.
               txinptr = 0                 'read BF
               txoutptr = 0
        endif
            dummyread = SSPBUF             'dummy read  empty buffer
            if bf = 0 then                 ' if buffer is empty
                if txcnt > 0 then          ' Is there a byte to transfer
                   SSPBUF = txbuffer[txoutptr]   'get the byte and send it
                   txoutptr = txoutptr + 1       
                   if txoutptr = txbufferlen then txoutptr = 0
                   txcnt = txcnt - 1
                else
                'no byte to send
                endif       
            endif
    endif
    
    sspif = 0
    CKP = 1 
    
    @ INT_RETURN
    '-------------------[ end of interrupt ]--------------------------------------
    
    
    ' ************************************************************
    ' * main program loop -                                      *
    ' *                                                          *
    ' * ..                                                       *
    ' ************************************************************
    
    ProgramStart: 
    
         if txcnt < txbufferlen  then
              
                TxBuffer[txinptr] = dataout[txinptr] 
                txinptr = txinptr + 1
                if txinptr = txbufferlen  then txinptr = 0
    
                txcnt = txcnt + 1
        endif
        if rxcnt != 0 then
           datain[rxoutptr] = rxbuffer[rxoutptr]
           rxoutptr = rxoutptr + 1
           if rxoutptr = rxbufferlen  then
              rxoutptr = 0
           endif
           rxcnt = rxcnt - 1
    
    
        endif
    Select case datain[0]             'Test data from master byte 0
           case 0
              low led1                'turn on LED1
           case 1
              high led1               'turn off led1
              low led2                'turn on led2
           case 2
             low led1: low led2       'turn on both
           case 3
              high led1: high led2    'turn off both
           case 4                     'Change the data out to master
              dataout[0] = 44
              dataout[1] = 45
              dataout[2] = 46
           
    end select
                                        'Eight leds for testing, 4 on Port b and four on Port a
    portb = ~datain(0) <<4              'Lower nibble to RB4 to RB7
    porta = ~(datain(0) & $F0)>>4       'upper nibble RA0 to RA3
    goto ProgramStart 
     end
    It seems the 18F chips are very sensitive to the correct timing. Also it is a good idea to read AN734B to understand the difference between I2C slave with 16F chips and 18F chips.

    Hope this helps someone out

    Dave

  9. #49
    Join Date
    Oct 2008
    Location
    Southern California
    Posts
    17


    Did you find this post helpful? Yes | No

    Talking It works!

    Guys,

    This weekend I put together software nuggets from both DaveC3 and BigWumpus. In doing so, I could see the influence of most of you that have been working on this thread over the last few weeks. I went through and trimmed out the dead code, and moved a few things around to work for my uses. I'll post both the master and slave(s) in the next day or two so others can learn from our efforts! Thanks to everyone for taking on this tough problem.

    Thanks,
    rswain

  10. #50
    Pedro Pinto's Avatar
    Pedro Pinto Guest


    Did you find this post helpful? Yes | No

    Default

    Hello Danielhr77

    I look in this moment for a slave I2C solution for my project

    If i understand right if i need to receive or tramsmit more than one byte, it need to increase this value, like:
    '--- Rx Buffer defintion ----------------------------------------------------
    RxBufferLEN CON 4 'for receive up to 4 bytes
    RxBuffer VAR BYTE[Rxbufferlen]
    RxBufferIndex VAR BYTE
    '
    '--- Tx Buffer defintion ---------------------------------------------------
    TxBufferLEN CON 4 'for send up to 4 bytes
    TxBuffer VAR BYTE[txbufferlen]
    TxBufferIndex VAR BYTE


    'Master send 4 bytes
    I2CWrite SDA, SCL, I2Caddress, [4,10,56,21], bogus ' Write offset to slave
    Pause 500


    On the Slave side, how can i read and show the received 4 bytes?
    Is this correct? Sorry for asking but i have not very experience.
    I want sent back the received 4 bytes

    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
    Case 56
    do anything
    Case 21
    do anything
    End Select
    '
    WrData=0
    GoTo Main
    End

    Thank You
    Best regards
    Pedro

  11. #51
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default

    Pedro , to read back the bytes sent just tranfer the content from RxBuffer int TxBuffer in the slave.

    Code:
    Select Case RxBuffer[0]
    TxBuffer[0]=RxBuffer[0]
    TxBuffer[1]=RxBuffer[1]
    TxBuffer[2]=RxBuffer[2]
    TxBuffer[3]=RxBuffer[3]
    Case 4
    High LEDT
    Case 10
    Low LEDT
    Case 56
    do anything
    Case 21
    do anything
    End Select
    From master just use this code:

    Code:
    I2CRead SDA,SCL,I2Caddress,[str YourBuffer\4], bogus
    You will find the four bytes into the array YourBuffer

    Al.
    All progress began with an idea

  12. #52
    Pedro Pinto's Avatar
    Pedro Pinto Guest


    Did you find this post helpful? Yes | No

    Default

    Hello Al

    Thank you

    Best regards
    Pedro

  13. #53
    Pedro Pinto's Avatar
    Pedro Pinto Guest


    Did you find this post helpful? Yes | No

    Default

    Hi Al

    If the master send 4 bytes to the slave and the slave send the received bytes back to the master, must in that moment the master not change to slave mode to receive this 4 bytes?
    If yes, i can't see that in yours and danielhr77 code

    Regards
    Pedro

  14. #54
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default

    Pedro, I am not sure to understand your question correctly, but I try to answer

    Master remain master. Slave will not return your 4 bytes without a proper request. When you want the 4 bytes back to the master then you make the request with:
    Code:
    I2CRead SDA,SCL,I2Caddress,[str YourBuffer\4], bogus
    and you will find the four bytes into the array YourBuffer that you have properly declared in your MASTER.

    Al.
    All progress began with an idea

  15. #55
    Pedro Pinto's Avatar
    Pedro Pinto Guest


    Did you find this post helpful? Yes | No

    Default

    Good morning Al

    Thank You, now i understand it

    Best regards
    Pedro

  16. #56


    Did you find this post helpful? Yes | No

    Default

    I've been wondering... And it's just out of curiosity...

    We are sending and receiving bytes, right?

    Is it possible to send and receive words?

    Thanks!

    Daniel.

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


    Did you find this post helpful? Yes | No

    Cool

    I've been wondering the same thing - I need to move words and was just willing to break them up into two bytes, but maybe it's worth tracking it down to get a final answer.

  18. #58


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by rswain View Post
    Guys,

    This weekend I put together software nuggets from both DaveC3 and BigWumpus. In doing so, I could see the influence of most of you that have been working on this thread over the last few weeks. I went through and trimmed out the dead code, and moved a few things around to work for my uses. I'll post both the master and slave(s) in the next day or two so others can learn from our efforts! Thanks to everyone for taking on this tough problem.
    Hey rswain!

    Any news about this?

    Thanks!

    Daniel.

  19. #59
    Join Date
    Nov 2008
    Posts
    48


    Did you find this post helpful? Yes | No

    Default I2C SLave in a 18F6722

    Hi all,
    wanted to come back earlier with my experiences, but had too much work.
    But :
    I use Al's i2cslave in an 18F6722 I in an interrupthandler, in Al's code i made a little correction:

    while STAT_BF = 1
    i = SSP1BUF ' Dummy Read inserted => clears BF Flag
    wend ' loop while buffer is full

    This seems to be neccessary for this PIC's, the original code from Al results in
    staying in this loop for ever.

    I read back eight variables and write two variables with no problems.
    The master and the slave have both the " DEFINE I2C_HOLD 1" at start up.

    Regards,
    Ralf

  20. #60
    Join Date
    Nov 2008
    Posts
    48


    Did you find this post helpful? Yes | No

    Default i2c slave with 18F14K22

    Hi again,
    did somebody test Al's code with a 18F14K22?
    Regards,
    Ralf

  21. #61
    Join Date
    Nov 2008
    Posts
    48


    Did you find this post helpful? Yes | No

    Default

    There is an other problem with the i2cslave:

    1. When the i2caddress is specifiead as constant (i2caddress CON $0F) it works perfect.

    2. When bulding the address via a variable, it doesnt work:
    ...
    i2caddress VAR byte
    ...
    i2caddress = $0F

    I need this because i build it from the status of four bits of Port A

    Any idea?

    Regards,
    Ralf

  22. #62
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default

    I need this because i build it from the status of four bits of Port A

    Any idea?

    Ralf, you can try this:

    Code:
    
    
    Select Case PortA
    
    Case 1
    i2caddress CON $01
    Case 2
    i2caddress CON $02
    case 3
    i2caddress CON $03
    .
    .
    .
    .
    Case x
    i2caddress CON $x
    End Select
    It should work.

    Edited:

    No! it doesn't work sorry.

    Al.
    Last edited by aratti; - 25th March 2010 at 13:19.
    All progress began with an idea

  23. #63
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166


    Did you find this post helpful? Yes | No

    Default

    ralfmayr, Here is what I have been using for years. It uses the base address for the first of 3 PCF8574's. I then calculate the address depending on the one I need to gather or send data to.

    UNIT0 CON %01000000 'U5's CONTROL BYTE (PCF8574) I/O EXPANDER

    '**************** I2C I/O ROUTINE (PCF8574A) I/O EXPANDER ************
    READ_WRITE VAR BIT 'READ DATA or WRITE DATA FLAG
    EXPAND_UNIT VAR BYTE 'CONTROL BYTE FOR I2C
    DEVICE VAR BYTE 'SELECTED I/O EXPANDER DEVICE
    OUTPUTS VAR BYTE[3] 'RELAY OUTPUT BYTES
    SWITCHES VAR BYTE[3] 'SWITCH INPUTS BYTES

    '************************************************* *******************
    R_WI2CS:'READ DIGITAL INPUTS FROM or WRITE DIGITAL OUTPUTS TO PCF8574'S
    '************************************************* *******************
    EXPAND_UNIT = UNIT0 'COPY BASE ADDRESS OF PCF8574'S
    EXPAND_UNIT = (EXPAND_UNIT | (DEVICE << 1)) 'SELECT WHICH DEVICE
    IF READ_WRITE = 0 THEN 'READ INPUT STATUS FROM PCF8574'S
    I2CREAD SDA,SCL,EXPAND_UNIT,[SWITCHES(DEVICE)]
    ELSE 'SET OUTPUT STATES TO PCF8574'S
    I2CWRITE SDA,SCL,EXPAND_UNIT,[OUTPUTS(DEVICE)]
    ENDIF
    RETURN


    Then to use it first set the device index.
    Next set the read_write flag.
    Then finally call the routine.....

    Dave Purola,
    N8NTA

  24. #64
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default

    Ralf, you can try the case select using the proper addresses (not my example). You must correct your code as per the line in black bold and comment out the line in red bold. The code compile so it should work. Longing to hear from you on the final test.

    Al.


    Code:
    ' Initialize I2C slave mode
    
    Select case PortA
    
    Case 1
    SSPADD = 2
    case 2 
    SSPADD = 3
    case 3
    SSPADD = 4
    
    end select
    
    SCLDIR = 1  ' SCL must be made an input before enabling interrupts
    SDADIR = 1   
    'SSPADD = I2Caddress ' Set our address
    SSPCON2.7 = 0 ' General call address disabled
    SSPCON = $36 ' Set to I2C slave with 7-bit address
    SSPSTAT = 0
    SSPIE = 1 
    SSPIF = 0 
    RxBufferIndex = 0
    TxBufferIndex = 0
    
    'Initialization Done!
    
     
    GoTo main
    
    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 != SSPADD Then i2cexit ' Clear the address from the buffer
    readcnt = 0 ' Mark as first read
    GoTo i2cexit
    All progress began with an idea

  25. #65
    Join Date
    Nov 2008
    Posts
    48


    Did you find this post helpful? Yes | No

    Default

    Hi Al,
    my mistake, it works now.
    I made a mistake in calculating the address from four bits of a port :-(

    This works:

    main_loop:
    ...
    i2caddress = (addr0 * 16) + (addr1 * 8) + (addr2 * 4) + (addr3 * 2)
    SSP1ADD = I2Caddress
    ...
    goto main_loop

    ...in the moment i try to implement the slave routine into a 18LF14K22...
    It does not work in the moment, it is the same like on a18F6722, there it
    works great.

    Regards,
    Ralf

  26. #66
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default

    Code:
    i2caddress = (addr0 * 16) + (addr1 * 8) + (addr2 * 4) + (addr3 * 2)
    SSP1ADD = I2Caddress
    Very good Ralf !

    Al.
    All progress began with an idea

  27. #67
    Join Date
    Nov 2008
    Posts
    48


    Did you find this post helpful? Yes | No

    Default

    Hi Al,
    success!
    The slave routine runs in a 18LF14K22.
    I read back via i2c 20 values (a/d values and digital i/o) and i can set
    several parameters with two bytes, 1st is array index, 2nd is value.
    The handler runs via interrupt, in the moment i am cleaning a little bit,
    but i am very happy with it.
    Regards,
    Ralf

  28. #68
    Join Date
    Nov 2008
    Posts
    48


    Did you find this post helpful? Yes | No

    Default

    Some Remarks:

    1. It is necessary to set the "DEFINE I2C_HOLD 1" in the master to get a
    better behaviour of the timing. I checkrd it with the logic analyzer and it is
    exactly like in the original "Phillips-Spec"

    2. In the section
    ...
    while STAT_BF = 1
    i = SSPBUF ' Dummy Read inserted => clears BF Flag
    wend
    ...
    it is necessary to inlude the dummy read to get it work on
    a 18F6722 and a 18LF14K22 (refer to MCHIP App Note 734, page 17)

    3. Address range ist tested from 00h to FFh, all work well.

    4. New address setting works (in the main loop) by only setting SSPADD
    register with new value without reseting the complete handler.

    Regards,
    Ralf

  29. #69
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default

    ralfmayr wrote on 17th Feb. 2009
    Hi Daniel,
    no, i stopped working on it, it is not possible to get it work... :-(

    I solved my problem using serin/serout.
    But it would be great when we exchange our know-how, so we can solve this together!

    -,Ralf
    I quoted your last year post, just to congratulate with you for the remarkable knowledge you have gained in a year. This will teach new comer that persevering on a subject always pay.

    Thank you for those additional I2C remarks that could be useful.

    Al.
    All progress began with an idea

  30. #70
    Join Date
    Nov 2008
    Posts
    48


    Did you find this post helpful? Yes | No

    Default

    Yep,
    last year i made my first experiments with i2cslave,
    but had no time to work on it for 8 months now as
    i was very busy with other things.
    Hope it will help others to come faster to their target.
    -,Ralf

  31. #71
    Join Date
    Nov 2008
    Posts
    48


    Did you find this post helpful? Yes | No

    Default

    Hello Al,
    another question:
    What are the three definitions:
    1. DEFINE I2C_SLOW 1
    2. DEFINE I2C_HOLD 1
    3. DEFINE I2C_SCLOUT 1
    do?
    1. => Used with LO > 8MHz and 100kHz devices
    2. => Time Delay during acknowledge?
    3. => Open Collector / Bipolar Clock on SCL? Dont Understand this!

    So: I use PCF8575C and MAX3611 (both 400kHz devices) but both only work
    correct when DEFINE I2C_HOLD 1 and DEFINE I2C_SCLOUT 1 is done.

    Can you help?

    Regards,
    Ralf

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


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by ralfmayr View Post
    Hello Al,
    another question:
    What are the three definitions:
    1. DEFINE I2C_SLOW 1
    2. DEFINE I2C_HOLD 1
    3. DEFINE I2C_SCLOUT 1
    do?
    1. => Used with LO > 8MHz and 100kHz devices
    2. => Time Delay during acknowledge?
    3. => Open Collector / Bipolar Clock on SCL? Dont Understand this!

    So: I use PCF8575C and MAX3611 (both 400kHz devices) but both only work
    correct when DEFINE I2C_HOLD 1 and DEFINE I2C_SCLOUT 1 is done.

    Can you help?

    Regards,
    Ralf
    Hi Ralf,
    I can answer part of #3:
    Open collector means the PIC has 2 states LOW where it takes the pin to ground and an open state where the pin is high impedance, so to get a high state it must have a pull up resistor to supply the power. I do not know what bipolar clock means, have not read up on this yet.
    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.

  33. #73
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default

    1. => Used with LO > 8MHz and 100kHz devices
    Yes.

    2. => Time Delay during acknowledge?
    Not Exactly, data transfer can be paused by the receiving device by holding the clock line low, so the receiving device can control the data flow. To enable this function you need the DEFINE I2C_HOLD 1 declared.

    3. => Open Collector / Bipolar Clock on SCL? Dont Understand this!
    Joe already answer to this point with a clear explanation. Let me add that bipolar is a device capable to pullup the lines by itself without the need of external pullup resistors

    So: I use PCF8575C and MAX3611 (both 400kHz devices) but both only work
    correct when DEFINE I2C_HOLD 1 and DEFINE I2C_SCLOUT 1 is done.
    It is usefull to use DEFINE I2C_HOLD 1 as default since it will keep synchronized different devices connected on the I2C bus all with different internal clock.

    I don't know much about PCF8575C and MAX3611 but very likely they are bipolar devices.

    Al.
    All progress began with an idea

  34. #74
    Join Date
    Nov 2008
    Posts
    48


    Did you find this post helpful? Yes | No

    Default

    Thank you both for the answers.
    Now i understand.
    So it seems always to be best to work with declaration 2 & 3 with
    400 khz devices. This is what i found out yesterday.
    Have nice eastern!
    Regards,
    Ralf

  35. #75
    Join Date
    Nov 2005
    Location
    Perth, Australia
    Posts
    429


    Did you find this post helpful? Yes | No

    Default

    Hi all. I need to synchronise an array from one PIC to another (one way only), so I have been working to make a simplified version of the code seen in this thread with just the bare essentials to send the array from slave to master.

    It mostly works, but there is one little bug. I am sending the array over and over again - the test array is 6 bytes and I have assigned test values of 1 2 3 4 5 and 6.

    On the 1st i2cread the master receives 123456. On the 2nd i2cread it gets 234561, and the third 345612. It seems that every time I do an i2cread, the following byte goes missing. The first time I get 123456, the next 1 goes into oblivion and therefore the next packet is 234561.

    I know I can get around this by sending a dummy byte after the array, knowing that it will be lost, but I'd like to know why this is happening if anyone has any ideas?

    Master PIC (18F2620, 40Mhz HSPLL):
    Code:
    DEFINE OSC 40
    
    DEFINE I2C_HOLD 1
    
    DEFINE LCD_DREG         PORTB          
    DEFINE LCD_DBIT         0              
    DEFINE LCD_RSREG        PORTB         
    DEFINE LCD_RSBIT        4             
    DEFINE LCD_EREG         PORTB          
    DEFINE LCD_EBIT         5             
    DEFINE LCD_BITS         4           
    DEFINE LCD_LINES        2              
    DEFINE LCD_COMMANDUS    2000         
    DEFINE LCD_DATAUS       50           
    PAUSE 100
    LCDOUT $FE,1,$FE,2
    
    ADCON1=%00001111
    CMCON=%00000111
    
    scl             VAR PORTC.3
    sda             VAR PORTC.4                    
    
    i2c_address     VAR BYTE
    
    i2c_data        VAR BYTE[6]
    
    i2c_address=$0A
    
    
    main:
    I2CREAD sda,scl,i2c_address,[STR i2c_data\6]
    LCDOUT $FE,$80,DEC i2c_data[0]
    LCDOUT " ",    DEC i2c_data[1]
    LCDOUT " ",    DEC i2c_data[2]
    LCDOUT " ",    DEC i2c_data[3]
    LCDOUT " ",    DEC i2c_data[4]
    LCDOUT " ",    DEC i2c_data[5]
    PAUSE 1000
    GOTO main
    Slave PIC (18F2620, 40Mhz HSPLL):
    Code:
    DEFINE OSC 40
    
    INCLUDE "DT_INTS-18.bas"  
    INCLUDE "ReEnterPBP-18.bas"
    
    ADCON1=%00001111                            
    CMCON=%00000111         		     
    
    i2c_buffer_full     VAR SSPSTAT.0 
    i2c_read            VAR SSPSTAT.2
    i2c_release_scl     VAR SSPCON1.4 
    
    i2c_data            VAR BYTE[6]
    i2c_data_index      VAR BYTE
    
    dummy               VAR BYTE
    
    SSPADD=$0A          ' I2C Address: $0A
    SSPCON1=$36
    SSPCON2.0=1
    
    i2c_data[0]=1
    i2c_data[1]=2
    i2c_data[2]=3
    i2c_data[3]=4
    i2c_data[4]=5
    i2c_data[5]=6
    
    i2c_data_index=0
    
    ASM
    INT_LIST  macro  
            INT_Handler SSP_INT, _i2c_int_handler, PBP, yes
        endm
        INT_CREATE          
        INT_ENABLE SSP_INT
    endasm
    
    
    main:
    ' main program goes here
    goto main 
    
    
    i2c_int_handler:
    IF i2c_read then
        dummy=SSPBUF
        IF i2c_buffer_full=0 THEN
            SSPBUF=i2c_data[i2c_data_index]
            i2c_data_index=i2c_data_index+1
            IF i2c_data_index=6 THEN i2c_data_index=0
        ENDIF
    ENDIF
    i2c_release_scl=1 
    @ INT_RETURN
    Last edited by Kamikaze47; - 15th August 2010 at 23:04. Reason: spelling
    "I think fish is nice, but then I think that rain is wet, so who am I to judge?" - Douglas Adams

  36. #76
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Hey Kamikaze,

    I didn't see a problem from just looking at the code, so I ran it in the simulator.
    And I don't see a problem there either.

    On the master I get " 1 2 3 4 5 6".
    It does not change.

    I only added a toggle in the Master's main loop to verify it was looping.
    And a toggle in the Slave's handler, to verify the transfers.

    Is there something you stripped out before posting that could have caused it?

    Name:  SIM1.JPG
Views: 3653
Size:  108.4 KB
    DT

  37. #77
    Join Date
    Nov 2005
    Location
    Perth, Australia
    Posts
    429


    Did you find this post helpful? Yes | No

    Default

    Thanks for looking DT. I'm currently running the above code "as is" on 2 breadboards side by side.

    Still losing a byte every time I do an i2cread.

    I tried reading one byte at a time instead of six, and I get: 1, 3, 5, 1, 3, 5. So no matter how many bytes I receive at once, it always skips the byte immediately proceeding those bytes.

    *edit* My circuit is identical to yours there DT except for 10mhz crystals + caps, and I only have an LCD on the master PIC.

    In case its relevant, these are my configs:

    Code:
            __CONFIG    _CONFIG1H, _OSC_HSPLL_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
            __CONFIG    _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
            __CONFIG    _CONFIG3H, _CCP2MX_PORTC_3H & _PBADEN_OFF_3H & _LPT1OSC_OFF_3H & _MCLRE_ON_3H
            __CONFIG    _CONFIG4L, _STVREN_ON_4L & _LVP_OFF_4L & _XINST_OFF_4L

    Quote Originally Posted by Darrel Taylor View Post
    Hey Kamikaze,

    I didn't see a problem from just looking at the code, so I ran it in the simulator.
    And I don't see a problem there either.

    On the master I get " 1 2 3 4 5 6".
    It does not change.

    I only added a toggle in the Master's main loop to verify it was looping.
    And a toggle in the Slave's handler, to verify the transfers.

    Is there something you stripped out before posting that could have caused it?

    Attachment 4704
    Last edited by Kamikaze47; - 16th August 2010 at 13:52. Reason: added more information
    "I think fish is nice, but then I think that rain is wet, so who am I to judge?" - Douglas Adams

  38. #78
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Have you looked at the errata sheet for the silicon rev you have? This series has a lot of issues with the MSSP module & I2C.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  39. #79
    Join Date
    Nov 2005
    Location
    Perth, Australia
    Posts
    429


    Did you find this post helpful? Yes | No

    Default

    I'll have a look at that errata sheet as you suggest.

    Incidentally, DT: What program do you use for PIC simulation? It looks like a handy tool to have.
    "I think fish is nice, but then I think that rain is wet, so who am I to judge?" - Douglas Adams

  40. #80
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Kamikaze47 View Post
    Incidentally, DT: What program do you use for PIC simulation? It looks like a handy tool to have.
    It's Proteus VSM, and it's extremely handy.

    My breadboards are all covered in a layer of dust.
    They don't get used much anymore.
    DT

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 : 5

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