+ Post New Thread
Results 1 to 9 of 9
  1. #1
    Banned
    Points: 23,048, Level: 36

    Join Date
    Dec 2012
    Location
    Bangalore, India
    Posts
    4,294
    Helped
    826 / 826
    Points
    23,048
    Level
    36

    I2C Problem. Multiple Slaves hang

    I have written a program in CCS C. It is for I2C communication between One Master PIC16F887 and two Slave PICs PIC16F887. When I use any one of the slaves the master reads the data from slave and displays it on masters uart but if I use both the slaves then it reads data from slaves and prints it on uart the first time and after that it reads 0 from the slaves and slaves hang. The i2c debugger shows that nack is being performed where ack has to be performed but If I use only one slave (any slave) then ack and nack happens properly as desired and I see data sent by slave is updated in master whenever the data in slave changes. Actually the slaves send the adc reading which is a float value.

    See the images. I have pointed where nack's is being performed if two slaves are used (first time the data is read properly after that it reads 0) The 0.0000 0.0000 is the data read the second time.

  2. #2
    Super Moderator
    Points: 236,455, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    40,894
    Helped
    12495 / 12495
    Points
    236,455
    Level
    100

    Re: I2C Problem. Multiple Slaves hang

    Looks like a slave code problem at first sight, presumed Proteus is managing everything correctly.

    Can show the slave code?



    •   Alt26th March 2013, 19:10

      advertising

        
       

  3. #3
    Banned
    Points: 23,048, Level: 36

    Join Date
    Dec 2012
    Location
    Bangalore, India
    Posts
    4,294
    Helped
    826 / 826
    Points
    23,048
    Level
    36

    Re: I2C Problem. Multiple Slaves hang

    Here is the code for Slave. Both Slaves have the same code but the address value in #USE i2c is different.

    Code C - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    
    #include <16F887.h>
    #device adc=10
     
    #fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
    #use delay(clock=20000000)                //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
    #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
    #use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xA0) //FORCE_HW, stream=I2CS
     
    #define LCD_ENABLE_PIN  PIN_D2                                    
    #define LCD_RS_PIN      PIN_D0                                    
    #define LCD_RW_PIN      PIN_D1                                    
    #define LCD_DATA4       PIN_D4                                    
    #define LCD_DATA5       PIN_D5                                    
    #define LCD_DATA6       PIN_D6                                    
    #define LCD_DATA7       PIN_D7
     
    #include <lcd.c>
     
    float temp = 0, old_val = 0;
    int8 ctr = 0;
    union float2bytes { 
        float fval; 
        int8  bytes[4]; 
    } fvalue;
     
    int8 data = '0';
     
    BYTE addr, buffer[16]; 
     
    #INT_SSP 
    void ssp_interupt (){ 
       BYTE incoming, state; 
     
       state = i2c_isr_state(); 
            
       if(state < 0x80)                     //Master is sending data 
       { 
          incoming = i2c_read(); 
          if(state == 1)                    //First received byte is address 
             addr = incoming; 
        if(state == 2)                    //Second received byte is data 
            data = incoming;
           
        }
        //else if(state == 0x80){ 
          //i2c_read(); 
          //i2c_write('U');
        //}
        else if(state >= 0x80)                     //Master is requesting data 
        { 
          i2c_write(fvalue.bytes[ctr]);
          ctr++;
          if(ctr < 4)i2c_read();
          if(ctr==4){i2c_read(0); ctr = 0;}
          //i2c_write('M');
          
          
        } 
    }
     
    void main()
    {
       int16 adc_val = 0;
       //set_tris_c(0xFF);
       setup_adc_ports(sAN0|VREF_VREF);
       setup_adc(ADC_CLOCK_DIV_2);
       setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
       
       delay_ms(250);
       lcd_init();
       delay_ms(250);
       lcd_putc("\fSlave 1...\n");
       set_adc_channel(0); 
       delay_us(20);
       
       enable_interrupts(INT_SSP); 
       enable_interrupts(GLOBAL);
             
       while(TRUE)
       {
          adc_val = read_adc();
          delay_ms(20);
          temp = (float)(adc_val * 0.196078431372549);
          fvalue.fval = temp;
          if(old_val != temp){
             printf(lcd_putc, "\a%7.3f", temp);
             printf("Temperature is: %7.3f", temp);
             printf(" Degree Centigrade\r\n");
             printf("%7.3f\r\n", fvalue.fval);
             printf("%lu\r\n", adc_val);
          }
          if(data == 'K'){
             printf("%c\r\n", data);
             data = '\0';
          }
          //delay_ms(1000);
          old_val = temp;
          
                  
       }
     
    }

    In CCS C i2c_read() performs ack and i2c_read(0) performs nack.
    Last edited by jayanth.devarayanadurga; 26th March 2013 at 19:39.



  4. #4
    Super Moderator
    Points: 236,455, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    40,894
    Helped
    12495 / 12495
    Points
    236,455
    Level
    100

    Re: I2C Problem. Multiple Slaves hang

    I see some differences to CCS example code respectively compiler manual suggestion given with i2c_isr_state():
    - address isn't read for state == 0x80 (read address received)
    - there are extra i2c_read() calls for state > 0x80

    I must confess however that I didn't yet implement I2C slave functionality with CCS, thus I'm not aware of possible documentation faults. Another, partly unrelated question is how Proteus might handle possible I2C programming faults. I would primarly check all I2C issues with real PIC hardware and MPLAB debugger.



    •   Alt26th March 2013, 22:14

      advertising

        
       

  5. #5
    Banned
    Points: 23,048, Level: 36

    Join Date
    Dec 2012
    Location
    Bangalore, India
    Posts
    4,294
    Helped
    826 / 826
    Points
    23,048
    Level
    36

    Re: I2C Problem. Multiple Slaves hang

    @FvM

    I have tried it both in hardwrae and Proteus and have same problem in both. See the attached image. It is from the CCS C manual. It tells to perform read and write when i2c_isr_state() is 0x80.



  6. #6
    Super Moderator
    Points: 236,455, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    40,894
    Helped
    12495 / 12495
    Points
    236,455
    Level
    100

    Re: I2C Problem. Multiple Slaves hang

    See the attached image. It is from the CCS C manual. It tells to perform read and write when i2c_isr_state() is 0x80.
    Yes. But your code doesn't follow the template. It doesn't read for state 0x80 and reads after write for state > 0x80.

    I'm referring to post #3.



  7. #7
    Banned
    Points: 23,048, Level: 36

    Join Date
    Dec 2012
    Location
    Bangalore, India
    Posts
    4,294
    Helped
    826 / 826
    Points
    23,048
    Level
    36

    Re: I2C Problem. Multiple Slaves hang

    Ofcourse it reads for 0x80. I have used state >= 0x80. If I put the read before write in the if(state >= 0x80) condition then it is not working.



    •   Alt27th March 2013, 08:54

      advertising

        
       

  8. #8
    Super Moderator
    Points: 236,455, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    40,894
    Helped
    12495 / 12495
    Points
    236,455
    Level
    100

    Re: I2C Problem. Multiple Slaves hang

    Ofcourse it reads for 0x80.
    I can only comment the present code as written in post #3, not what might be intended or has been previously there and is commented out now.

    Thus I can't but keep my statement in post #4 that your code differs in the said points from the CCS manual example.

    Apart from the obvious C code differences, I would check what the CCS built-in functions are actually doing on the assembly level and if the sequence required by the Microchip manual is exactly reproduced. I have no doubt that PIC16 basically works in slave mode. So there's either a problem in CCS built-in functions, the CCS documentation or your code.

    I assume, that besides documentation details, the Ex_slave.c code shipped with CCS C does work.



  9. #9
    Banned
    Points: 23,048, Level: 36

    Join Date
    Dec 2012
    Location
    Bangalore, India
    Posts
    4,294
    Helped
    826 / 826
    Points
    23,048
    Level
    36

    Re: I2C Problem. Multiple Slaves hang

    Ex_slave.c didn't work for me. I am using PCM Compiler for 14 bit devices.



--[[ ]]--