I2C problem writing to slave


Closed Thread
Results 1 to 4 of 4

Hybrid View

  1. #1
    Join Date
    May 2011
    Posts
    8

    Default I2C problem writing to slave

    Hi everyone,
    Once more I am struggling with I2C. I had two PIC16F877A communicating nicely. I built my code based on the example of master and slave from the website. But now, I have added more code to my slave code and that makes the writing command from master to slave fail. I have a time error on the master and the slave also does not receive the single byte I am trying to write to it.
    Problem is that I need this piece of code in the slave.
    I tried to add some test to make it loop only on the receive command until I2C has finished transmission but I could not make it work.
    Is interrupt the way to go for that?
    Any other idea or code example to avoid this type of issue?

    Thanks for any help.
    regards

  2. #2
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default Re: I2C problem writing to slave

    You will need to post the modified code before anyone will be able to help trouble shoot the problem.
    Dave
    Always wear safety glasses while programming.

  3. #3
    Join Date
    May 2011
    Posts
    8


    Did you find this post helpful? Yes | No

    Post Re: I2C problem writing to slave

    Hi,

    sorry for that, here is the code.
    As you will see, the slave i2c part is unchanged, I just add some call to subroutine in the main loop.
    The funny thing is that it does not affect the read command from the other pic but only the write command which result in a time error.
    It seems to be linked to the time it takes during the main loop as I can make the write command fail by either uncomment the hserout or the call to subroutine.
    But why is there no effect on the read command? This one with all the code active always send me the right values.
    NOTE: the code is not finished and some change in subroutine (ADC and average computation) is not reflected yet in some other part of the code, so don't be surprised. I was planning to finish to trouble shoot once I could have the 2 pic communicating.

    Thanks for your help
    Code:
    ' Name        : I2CSLAVE.pbp
    ' Compiler    : PICBASIC PRO Compiler 2.6
    ' Assembler   : PM or MPASM
    ' Target PIC  : 40-pin 16F877A
    ' Hardware    : Lab-X1
    ' Oscillator  : 4MHz internal or external
    ' Keywords    : I2CREAD, I2CWRITE, LCDOUT
    ' Description : PICBASIC PRO program for I2C slave program - PIC16F877/PIC-X1.
    '
    
    DEFINE  LOADER_USED 1  ' Using boot-Loader
    Define HSER_CLROERR 1  'to automatically clear any buffer overflow of serial input
    Define HSER_BAUD 4800  'Set to NMEA baud rate standard
    
    ' Define ADCIN parameters
    Define    ADC_BITS    10    ' Set number of bits in result
    Define    ADC_CLOCK    3    ' Set clock source (3=rc)
    Define    ADC_SAMPLEUS    50    ' Set sampling time in uS
    
    ' Alias I2C pins
    scl VAR PORTC.3        ' I2C clock input
    sda VAR PORTC.4        ' I2C data input
    
    ' Define used register flags
    SSPIF VAR PIR1.3       ' SSP (I2C) interrupt flag
    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
    
    ' Define constants
    I2Caddress CON  $a0      ' Make our address 2
    
    ' Allocate alias
    qUp     var     PORTA.2
    qDown   var     PORTA.5
    
    ' Allocate variables
    qpot    var     word 'raw potentiometer reading
    qpotflt var     word 'raw pot filtered
    xqpot   var     word 'used to compute average
    qpotnb  var     byte 'filtering number
    qpotold var     word
    qpotCal var     byte 'calibrated pot reading (20 - 220)
    qpos    var     byte  '0 down, 1 up
    CalFlag var     byte 
    x       var     word
    y       var     word
    QDmax   var     word
    QUmax   var     word
    Qmin    var     word
    PotDA   var     word  'amplitude pot for Down position
    PotDOf  var     word  
    PotUA   var     word  'amplitude pot for up position
    PotUOf  var     word  
    QposPerc var    byte  
    Qdraft  var     byte  
    ind     var     byte
    bogus   var     word  'dummy for div32
    Qstatus var     byte  'to send status info to Master, 0 acq, 1 cal, 2 mov up, 3 mov down
    datain  var     byte  'received data from Master
    DataOut var     byte[4]
    readcnt var     byte
    result  VAR     BYTE       ' ADC result
    
    
    ' Initialize ports and directions
    ADCON1 = %10010101         
    TRISA = %11111111    ' Set PORTA to all input
    
    ' Initialize I2C slave mode
       SSPADD = I2Caddress ' Set our address
       SSPCON2 = 0         ' General call address disabled
       SSPCON = $36        ' Set to I2C slave with 7-bit address
    
       readcnt = 0         ' Zero counter
    
       GoTo mainloop       ' Skip over subroutines
    
       '*****************************QMove******************************************
    QMove:
    if qpotold > qpot then
        if qpotold-qpot > 4 then
            if qUp=1 then qPos=0
            if qDown=1 then qpos=1
        endif
    else
        if qpot-qpotold > 4 then
            if qUp=1 then qPos=1
            if qDown=1 then qpos=0
        endif
    endif
    return
    '*****************************CalProc****************************************
    CalPROC:
    if qUp=1 and qpos=1 then
      QUmax = QUmax max qpot
    endif
    if qDown=1 and qpos=0 then
      QDmax = QDmax max qpot  
    endif
    Qmin = Qmin min qpot
    
    if qdown=1 then calflag=2                
    if calflag=2 and qdown=0 then calflag=3  
    if calflag=3 and qUp=1 then calflag=4    
    if calflag=4 and qUp=0 then              
        PotDA=qdmax-qmin
        x=qmin*220
        y=div32 PotDa    
        PotDOf= 120-y      'offset +100 to avoid any negative number
        PotUA=qdmax-qmin
        x=qmin*220  
        y=div32 PotUa  
        PotUOf= 120-y      'offset +100 to avoid any negative number
        write 0, word potda, word PotDOf, word PotUA, word PotUOf, qpos 
        calflag=0          'back to acquisition mode
    endif
    return
    
    
    '*****************************Getx*******************************************        
    ' Subroutine to get pot value
    getx:
        ADCIN 0, qpot        ' Read channel 0 to qpot
        xqpot=xqpot+qpot
        qpotnb=qpotnb+1
        if qpotnb= 8 then
            qpotnb=0
            qpotflt=xqpot/8
            xqpot=0
            
            dataout[0]=qpotflt
            dataout[1]=qpotCal
            dataout[2]=Qstatus 
            hserout ["$pot,", dec qpotflt]
            hserout ["$qup,", dec qUp]
            hserout ["$qdown,", dec qDown]
            hserout ["$cf,", dec calflag]
            hserout ["$qdm,", dec qdmax]
            hserout ["$qum,", dec qumax]
            hserout ["$qm,", dec qmin]
            gosub QMove
            if calflag=0 then
              if qpos=0 then
                bogus = 220 * qpot
                qpotcal = div32 potda
                qpotcal=qpotcal+PotDOf-100
              else
                bogus = 220 * qpot
                qpotcal = div32 potUa
                qpotcal=qpotcal+PotUOf-100  
              endif
              gosub convert
            else
              gosub CalPROC
            endif
        endif
    Return
    
    '*******************************conversion***********************************
    convert:
    if qpos=0 then
      ' down position
      lookdown2 qpotcal,<=[20,22,26,33,42,55,73,96,127,167,192,206,230],ind
      lookup ind,[67,70,73,77,80,83,87,90,93,97,98,99,100], qposperc
      lookup ind,[166,171,176,180,184,187,191,193,196,198,199,200,200],qdraft
    else
      ' up position
      lookdown2 qpotcal,<=[20,21,24,28,33,39,46,53,62,72,83,94,106,119,133,148,163,179,195,204,208,220],ind
      lookup ind,[63,60,57,53,50,47,43,40,37,33,30,27,23,20,17,13,10,7,3,2,1,0],qposperc
      lookup ind,[161,156,150,144,138,132,125,118,111,104,97,89,81,73,65,56,48,39,30,26,23,20],qdraft
    endif
    'dataout[0]= qposperc
    'dataout[0]= qpot
    ''dataout[1]= qdraft
    'dataout[1]= qpot
    'dataout[2]= Qstatus
    return
    
    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 data into array
       if datain=127 then     
         calflag=1         ' goes into calibration mode
         qpos=1            ' calibration is started from keel
       endif
       wflag=0
       GoTo i2cexit
    
    i2crd:                 ' I2C read data from us
       IF D_A = 0 Then
          readcnt = 0      ' Mark as first read
       EndIF
    
       SSPBUF = dataout[readcnt]    ' Get data from array
       CKP = 1                      ' Release SCL line
       readcnt = readcnt + 1        ' Move along read count
       GoTo i2cexit                 ' That's it
    
    i2cexit:
       Return
    
    mainloop:              ' Main program loop
       IF SSPIF  ' Check for I2C interrupt flag
            GoSub i2cslave
       EndIF
    if calflag>0 then
      Qstatus=1
    else
      if qUp=1 then 
        Qstatus=2
      elseif qDown=1 then 
        Qstatus=3
      else 
        Qstatus=0
      endif
    endif
    gosub getx
    'dataout[0]=qpotflt                   '----------------With everything as comment, I2C works to write and read
    'dataout[1]=qpotCal                  '---------------- if I uncomment all this, i2c still works with a read command
    'dataout[2]=Qstatus                  '---------------- if I uncomment either the hserout or only the call to the subroutine
    'hserout ["$pot,", dec qpotflt]      '---------------- read comment is still OK but write command fails
    'hserout ["$qup,", dec qUp]
    'hserout ["$qdown,", dec qDown]
    'hserout ["$cf,", dec calflag]
    'hserout ["$qdm,", dec qdmax]
    'hserout ["$qum,", dec qumax]
    'hserout ["$qm,", dec qmin]
    'gosub QMove
    'if calflag=0 then
    '  if qpos=0 then
    '    bogus = 220 * qpot
    '    qpotcal = div32 potda
    '    qpotcal=qpotcal+PotDOf-100
    '  else
    '    bogus = 220 * qpot
    '    qpotcal = div32 potUa
    '    qpotcal=qpotcal+PotUOf-100  
    '  endif
    '  gosub convert
    'else
    '  gosub CalPROC
    'endif
    
       GoTo mainloop       ' Do it all forever
    
       End
    Last edited by ScaleRobotics; - 22nd June 2011 at 18:17. Reason: added code tags

  4. #4
    Join Date
    May 2011
    Posts
    8


    Did you find this post helpful? Yes | No

    Default Re: I2C problem writing to slave

    OOOPS, I posted the wrong code. I tried to modify the code once I had issues and moving around some procedure and did not posted the original one which did not have dupplicate.
    I am going to clean that and will post the right one later.

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