I2C Slave with a PIC


Closed Thread
Results 1 to 40 of 130

Hybrid View

  1. #1
    Join Date
    Jun 2011
    Location
    Philippines
    Posts
    223


    Did you find this post helpful? Yes | No

    Default Re: Please help me understand how the application works

    Thank you for the code, and thanks in advance DT for your valuable time...looking forward for the end result(I wish and pray that things goes well). I've been reading about I2C on net, trying to understand and the applications that might be done(particularly on Master-(multi-Slave/Multi-master)) are very interesting...

    Regards,
    tacbanon
    Last edited by tacbanon; - 29th April 2012 at 03:26.

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


    Did you find this post helpful? Yes | No

    Default Re: I2C Salve with a PIC

    Although my slave example may not be as robust as AN734, I have systems running that have 14 slaves running. All 14 slaves are polled on 2 second intervals. The master uses bit-banging (I2CWrite). I have never had trouble with the code below. I have tested it with -
    18F8723, 18F2221, 18F2321, 18F2523 and had excellent results.

    Code:
    '****************************************************************
    '*  Name    : I2C slave                                         *
    '*  Author  : Charles Linquist                                  *
    '*  Notice  : Copyright (c) 2010 [select VIEW...EDITOR OPTIONS] *
    '*          : All Rights Reserved                               *
    '*  Date    : 10/20/2010                                        *
    '*  Version : 1.0                                               *
    '*  Notes   : Transmits 100 bytes in ~14 ms (Master SEND)       *
    '*          : Recives 100 bytes in ~12 ms (Master RECEIVE)      *  
    '*          : Could possibly go faster.  Master used for  the   *
    '*          : test used bit-banging (I2CREAD/I2CWRITE           *
    '*          : settings on that end were                         *
    '*          :  DEFINE I2C_SLOW 1 ,DEFINE I2C_HOLD 1             * 
    '****************************************************************
    ASM
        ifndef __18F2221
            error "18F2221 not selected"
        endif
    ENDASM 
           
    ASM
           movlw 0x62                              ; %0110 0010  = 4 Mhz, internal osc block
           movwf OSCCON
           movlw 0x80                              ; %1000 0000  = PLL disabled
           movwf OSCTUNE
    ENDASM       
        
               
            DATA @0,0      ; programming flag
                          
            DEFINE OSC 4                                                          
            DEFINE NO_CLRWDT 1                                                      ' Don't waste cycles clearing WDT  
            Define USE_LFSR 1
            define USE_LOWPRIORITY 1
    ;---------------- Alias the bits ------------------------------------
        
        SSPIF               VAR PIR1.3    ' SSP (I2C) interrupt flag
        SSPIE               VAR PIE1.3    ' Int Enable
       
        SSPUA               VAR SSPSTAT.1
        SSPS                VAR SSPSTAT.3
        SSPP                VAR SSPSTAT.4
        SSPSMP              VAR SSPSTAT.7
        
        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
        GENCALL             VAR SSPCON2.7  ' General Call enabled
        
        MainTimer           var word bankA System
        I2CTimer            var word bankA System
        I2CTimerGate        var byte bankA System
        I2CErr              var byte bankA System
    ;-------------------------------------------------------------------------  
    ;Alias pins
        SCL     VAR     PORTC.3         ' I2C clock input
        SDA     VAR     PORTC.4         ' I2C data input
        LED     VAR     PORTB.5
        
     
    '------------------- Rx Buffer defintion --------------------
        RxBufferLEN         con 10         
        RxBuffer            var BYTE[Rxbufferlen + 1]    
        TxBufferLEN         CON 10
        TXBuffer            VAR BYTE[TxBufferLEN + 2]
        InBuff              VAR BYTE
       
        GeneralCall         VAR BIT
        RXBufferOverFlow    VAR BIT
        TxBufferUnderFlow   VAR BIT
        RXBufferPointer     VAR Byte
        TXBufferPointer     VAR Byte
        address             VAR BYTE
        x                   VAR BYTE
        dummy               var byte
        I2CAddress          VAR BYTE
        WCOLCounter         VAR BYTE
    ;-------------------------------------------------------------    
        TXBuffer[TxBufferLen + 1] = $FF  ; Char to send if requestor asks for too much.
        
        I2CDeviceAddress    VAR BYTE
        
        I2CMajorAddress     CON $3
        I2CDeviceAddress =  $8   
         
        I2CAddress = (I2CMajorAddress <<4) | I2CDeviceAddress 
    ;---------------------------------------------------------------       
        SSPADD = I2Caddress ' Set our address
        SSPCON2.0 = 1      ; Stretch the clock
        SSPSTAT = 0
        SSPEN = 1             
        SSPIE = 1 
        SSPIF = 0 
        GenCall = 1           ; Turn general call on
        SSPCON2.7 = 1         ' General call address ENABLED
        SSPCON1 = $36    ' Set to I2C slave with 7-bit address    
           
    ;---------------------------------------------------------------
        TRISA = %11111111
        TRISB = %11011111
        TRISC = %11111111
           
    ' -------------- Turn on Ints  ------------------------
        INTCON.7 = 1  ; global ints
        INTCON.6 = 1  ; peripheral ints
       
    ;------------------  Clear parameters --------------
        RXBufferPointer = 0
        TxBufferPointer = 0
        GeneralCall = 0 
        RxBufferOverFlow = 0
        TXBufferUnderFlow = 0
        WCOLCounter = 0
    ;---------------------------------------------------------------------  
       
    INCLUDE "DT_INTS-18.bas"    ' Base Interrupt System
    INCLUDE "ReEnterPBP-18.bas"     ' Use PBP interrupts
    include "ReEnterPBP-18LP.bas"
    ASM
    INT_LIST  macro    ; IntSource,         Label,  Type, ResetFlag?
            INT_Handler    TMR0_INT, TimerInt,    ASM,  yes
           
        endm
        INT_CREATE               ; Creates the interrupt processor
        
    INT_LIST_L  macro    ; IntSource,        Label,  Type, ResetFlag?
         INT_Handler    SSP_INT,  _I2C_Int,   PBP,  yes
         endm
         INT_CREATE_L               ; Creates the LP interrupt processor    
        
        
    endasm
    ''----------------- Initialization Done! -----------------------------
        Goto OverInt ; jump over ISR
    
    asm
    TimerInt
          
          infsnz MainTimer
          incf   MainTimer + 1
          btfsc  I2CTimerGate,0        ; Don't count if low bit is clr
          incf   I2CTimer
          btfss  I2CTimer,2            ; Bit 2 is set , we have at least 4 counts, we must be hung
          bra    NoProb
          bcf    PIR1,3                ; Clear Int flag
          bcf    SSPCON1,5             ; Stop the 
          bsf    SSPCON1,5
          bsf    I2CErr,0
          clrf   I2CTimer
    NoProb      
          bcf INTCON,2
                
          INT_RETURN
    endasm
    '------------------------- I2C subroutine  -------------------------------- 
    I2C_Int:
      ; We don't get here uless someone has matched our address register.
    @ bsf I2CTimerGate,0    ; start the counter
    If R_W = 0 then             'This is a WRITE by the master to us
        IF BF = 0 Then goto i2CEXIT   ; Nothing for us!
        if D_A = 0 then         'We have an address
          address = SSPBUF     'Need to READ to satisfy Microchip
           IF Address = 0 THEN
               GeneralCall = 1
           ELSE
               GeneralCall = 0      
           ENDIF
               
        else            
            IF WCOL OR SSPOV THEN I2CExit
           
              RXBuffer [RxBufferPointer] = SSPBuf   ; 
              RxBufferPointer = RXBufferPointer + 1
               
              IF RXBufferPointer > RxBufferLen  THEN
                    RXBufferOverFlow = 1
                    RXBufferPointer = 0
              ENDIF 
                  
            ENDIF
              
              
        else   ' R_W = 1 Master wants to read FROM us
              IF !D_A Then                          
                    TxBufferPointer = 0  ' Mark as first read
                    RXBufferPointer = 0
              EndIF
            
              IF CKP THEN I2CExit
                  dummy = SSPBUF  ;NECESSARY!
              
              If TXBufferPointer < TxbufferLen THEN
    SENDI2C:
                  WCOL = 0
                      SSPBUF = TXBuffer[TXBufferPointer] ' Get data from array
                       IF WCOL THEN 
                           WCOLCounter = WCOLCounter + 1            ; Don't hang the bus with infinite WRITES!
                           IF WColCounter = 0 Then goto I2CExit     ; Rolled over
                          Goto SendI2C       ; Rety
                        ELSE
                           WColCounter = 0
                        ENDIF   
                       TXBufferPointer = TXBufferPointer +1
                       TXBufferPointer  = TXBufferPointer MIN TXBufferLen + 1 ; Don't let it get larger than this
                       ; Send FFs if requestor asks for too much data  
                  ELSE
                      TXBufferPointer = 0
                      TXBufferUnderflow = 1
              ENDIF 
        ENDIF
              
    I2CEXIT:
    Asm
        bcf SSPCON1,6
        bcf SSPSTAT,0 
        bcf PIR1,3
        bsf SSPCON1,4
        
        bcf I2CTimerGate,0      ; stop the counter    
        INT_ENABLE SSP_INT      ; probably don't need this, but want to make certain it gets reenabled
        INT_RETURN
    endasm
    ' -------------------------end I2C subroutine  -------------------------------- 
    '--------------------[ main program loop]---------------------------------------
    OverInt:
    Asm
       clrf MainTimer
       clrf I2CTimer      
       bcf INTCON,2 
       bcf PIR1,3  ; Clear the I2C flag before we turn on the INT.
       movlw 0x83
       movf T0CON
       INT_ENABLE  SSP_INT     
       INT_ENABLE TMR0_INT
    endasm
    
    
    
    MAIN PROGRAM LOOP GOES HERE!
    Charles Linquist

  3. #3
    Join Date
    Jun 2011
    Location
    Philippines
    Posts
    223


    Did you find this post helpful? Yes | No

    Default Re: I2C Salve with a PIC

    Hi Charles, thanks for sharing..I will try it out..


    tacbanon

  4. #4
    Join Date
    Jun 2011
    Location
    Philippines
    Posts
    223


    Did you find this post helpful? Yes | No

    Default Re: I2C Salve with a PIC

    @Charles
    Sorry I was not able to make it work on my setup..I'm not really sure what the following code is doing, so I tried to comment it and assign a value, but no effect.
    Code:
    I2CMajorAddress     CON $3
    I2CDeviceAddress =  $8     
    'I2CAddress = (I2CMajorAddress <<4) | I2CDeviceAddress 
    I2CAddress =$14
    I hope it will be alright if you share the master side code?

    Thanks,
    tacbanon

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


    Did you find this post helpful? Yes | No

    Default Re: I2C Salve with a PIC

    At this point, I'm thinking Al (aratti) was right.

    AN734 didn't work either.
    Bytes are being put in the SSPBUF without an address match.
    So the slaves that aren't being accessed are overflowing during reads from other devices.

    The code I gave earlier works because it's resetting the overflow in the main loop, but that's just not right.

    I'm trying to get some more info from Labcenter.
    DT

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


    Did you find this post helpful? Yes | No

    Default Re: I2C Salve with a PIC

    I am using a slight variant of the code I posted, and it is working fine. The only major change is that I'm sending a packet length byte, and I'm handling the entire receive packet inside the ISR. This is safe because I have my ( higher priority) timer interrupt watching over the whole process.
    Charles Linquist

  7. #7
    Join Date
    Jun 2011
    Location
    Philippines
    Posts
    223


    Did you find this post helpful? Yes | No

    Default Re: I2C Salve with a PIC

    Hi,
    Just want to ask if anyone tried to extend say 50meters communication between master and slave using I2C bus extender P82B715PN or similar?

    Regards,
    tacbanon

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