PIC as I2C Master/Slaves


Closed Thread
Results 1 to 5 of 5

Hybrid View

  1. #1
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530


    Did you find this post helpful? Yes | No

    Default Re: PIC as I2C Master/Slaves

    Hi, and welcome!

    You might find this example useful: http://www.picbasic.co.uk/forum/content.php?r=224 I have not used I2C yet, so I can't give you much advice, but there are plenty of folks here that have.

    Walter

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


    Did you find this post helpful? Yes | No

    Default Re: PIC as I2C Master/Slaves

    This may help. Here is a fairly full-featured interrupt-driven I2C slave. The master part is easy.
    This slave relies on the work of many others, but I have added some bug fixes and extra features. For example, you can write
    0xAA,0X55,0x00,**your new address here**,0x00
    and you can change the address of the slave.

    Like my other stuff, it ONLY works on 18F chips.

    Code:
    ASM
        ifndef __18F2321
            error "18F2321 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,$38      ; Default I2C address if not determined in HW
                          
            DEFINE OSC 4                                                          
            Define USE_LFSR 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
       
        
        
         MasterClock VAR WORD BANKA SYSTEM  
        
     
    '------------------- Buffer defintion --------------------
        RxBufferLEN         con 10         
        RxBuffer            var BYTE[Rxbufferlen + 1]    
        TxBufferLEN         CON 10
        TXBuffer            VAR BYTE[TxBufferLEN + 1]
       
        GeneralCall         VAR BIT
        RXBufferOverFlow    VAR BIT
        TxBufferUnderFlow   VAR BIT
        HWAddress           VAR BIT
        RXBufferPointer     VAR Byte
        TXBufferPointer     VAR Byte
        address             VAR BYTE
        x                   VAR BYTE
        dummy               var byte
        I2CAddress          VAR BYTE
        WCOLCounter         VAR BYTE
        I2CDeviceAddress     VAR BYTE
        Holdoff             VAR WORD ; retry timer
    
        HWAddress = 0       ; Get address from EEPROM, not pins
        
        TestArray   VAR BYTE [200]
    
        IF !HWAddress THEN
    ;----------- Get our Address from EEPROM --------------    
             READ 0,I2CAddress  
    ;-----------------------------------------------------     
        ELSE
    ;----------------OR Get our address from PORT B0..2-----------
            I2CDeviceAddress = PORTB & %00000111
            I2CMajorAddress     CON $3     ; upper 4 bits
            I2CAddress = (I2CMajorAddress <<4) | I2CDeviceAddress <<1 ; bit 0 is R/W
    ;---------------------------------------------------------------       
        Endif
        
        SSPADD = I2Caddress ' Move our address into the proper reg
        SSPCON2.0 = 1      ; Allow clock stretching
        SSPCON2.1 = 0      ; Set to 1 to enable masking of address 1 ; 0 is R/W bit
        SSPCON2.2 = 0      ; Set to 1 to enable masking of address bit 2
        SSPCON2.3 = 0      ; Set to 1 to enable masking of address bit 3
        SSPCON2.4 = 0      ; Set to 1 to enable masking of address bit 4
        SSPCON2.5 = 0      ; Set to 1 to enable masking of address bit 5
        SSPCON2.6 = 0      ; Not used in slave
        SSPCON2.7 = 1      ; General Call enabled
        SSPSTAT = 0
        SSPEN = 1             
        SSPIE = 1 
        SSPIF = 0 
        SSPCON1 = $36 		' Set to I2C slave with 7-bit address    
           
    ;---------------------------------------------------------------
        TRISA = %11111111
        TRISB = %11111111
        TRISC = %11111111
           
    ' -------------- Turn on Ints  ------------------------
        INTCON.7 = 1  ; global ints
        INTCON.6 = 1  ; peripheral ints
        IPR1.3 = 1    ; high priority
     
    ;------------------  Clear parameters --------------
        RXBufferPointer = 0
        TxBufferPointer = 0
        GeneralCall = 0 
        RxBufferOverFlow = 0
        TXBufferUnderFlow = 0
        WCOLCounter = 0
    ;----------------Timer Setup-----------------------------------  
         T0CON = %10000011 ; /16 prescaler
    ;-------- -------------------------------------------     
         WDTCON = 1  ; Turn on the WDT
    ;--------------------------------------------------------------   
       
    
    INCLUDE "DT_INTS-18.bas"    '  Thanks Darrel!
    INCLUDE "ReEnterPBP-18.bas"     ' 
    
    ASM
    INT_LIST  macro    ; IntSource,         Label,  Type, ResetFlag?
            INT_Handler    SSP_INT,  _I2C_Int,   PBP,  yes
            INT_Handler    TMR0_INT,  MainTimer, ASM, yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    endasm
    
    ''----------------- Initialization Done! -----------------------------
    
        Goto OverInt ; jump over ISR, don't execute it.
    ;----------------------- Timer INt ------------------------------------    
    ASM
    MainTimer
            movlw   0x00         ;  10 mSec
            movwf   TMR0H
            movlw   0x63
            movwf   TMR0L
            
            infsnz  MasterClock
            incf    MasterClock + 1
            
    ;    This is a good place to pick up pin changes        
          
     INT_ENABLE TMR0_INT
     INT_RETURN
    
    ENDASM
    ;---------------------------------------------------------------------
    '------------------------- I2C subroutine  -------------------------------- 
    I2C_Int:
      ; We don't get here uless someone has matched our address register.
    
    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 Address from buffer to clear it.
           
           IF Address = 0 THEN
               GeneralCall = 1   ; Set flag if we got a general call address 
           ELSE
               GeneralCall = 0     
           ENDIF
         
              
        else            
            IF WCOL OR SSPOV THEN I2CExit
             IF RXBufferPointer < RxBufferLen - 1 THEN
                 RXBuffer [RxBufferPointer] = SSPBuf   ; 
                 RxBufferPointer = RXBufferPointer + 1
             ELSE
                 Dummy = SSPBuf  ; Grab the data but don't overwrite old
                 RXBufferOverFlow = 1
             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!
     
    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 >= 7 Then goto I2CExit     ; 7
                           RANDOM Holdoff
                           Pauseus Holdoff >> 3    ; wait 0-8 msec 
                           Goto SendI2C       ; Retry
                        ELSE
                           WColCounter = 0
                        ENDIF   
                       TXBufferPointer = TXBufferPointer + 1
                       
                 If TXBufferPointer = TXBufferLen THEN
                      TXBufferUnderflow = 1
                      TXBufferPointer = TXBufferLen - 1 ; Repeat last if req made again, but set flag now
                 ENDIF
        ENDIF
    
    I2CEXIT:
        SSPOV = 0
        BF = 0 
        sspif = 0
        CKP = 1 
    @ INT_ENABLE SSP_INT      ; probably don't need this, but I like to be certain it gets restarted
    @ INT_RETURN
    
    
    ' -------------------------end I2C subroutine  -------------------------------- 
    '--------------------[End ISRs]---------------------------------------
    OverInt:
    
    @ INT_ENABLE  SSP_INT     
    @ INT_ENABLE TMR0_INT
    '--------------------[ main program loop]---------------------------------------
    Main:
       IF RXBuffer[0] = $AA THEN
          IF RXBuffer[1] = $55 and RXBuffer[2] = 0  And RxBuffer[4] = 0 THEN
            Dummy = RXBuffer[3]
            WRITE 0,Dummy   ; Write a new address
            Pause 10
    @ RESET  ; and pick up the new address      
          ENDIF 
       ENDIF
    ;-------------------  Load the input buffer to the output buffer for test -----------   
       For X = 0 to TXBufferLen - 1  
         TxBuffer[X] = RXBuffer[X]
        next x
    ;----------------------------------------------------------------------
    goto main 
    
    end
    
    ASM
      ORG 0x0FF0  ; Keep track of pgm size in case we want to use it on a smaller chip
      NOP
    ENDASM
    Charles Linquist

Members who have read this thread : 1

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