I2C Slave with a PIC


Closed Thread
Results 1 to 40 of 130

Hybrid View

  1. #1
    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.

  2. #2
    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

  3. #3
    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

  4. #4
    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

  5. #5
    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

  6. #6
    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

  7. #7
    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

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