Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronic Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

I2C Problem. Multiple Slaves hang

Status
Not open for further replies.
Joined
Dec 4, 2012
Messages
4,294
Helped
822
Reputation
1,654
Reaction score
793
Trophy points
1,393
Location
Bangalore, India
Activity points
0
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.
 

Attachments

  • i2c1s.jpg
    i2c1s.jpg
    667.3 KB · Views: 7
  • i2c2s_.jpg
    i2c2s_.jpg
    558 KB · Views: 6

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
48,211
Helped
14,207
Reputation
28,673
Reaction score
12,903
Trophy points
1,393
Location
Bochum, Germany
Activity points
279,282
Looks like a slave code problem at first sight, presumed Proteus is managing everything correctly.

Can show the slave code?
 

Joined
Dec 4, 2012
Messages
4,294
Helped
822
Reputation
1,654
Reaction score
793
Trophy points
1,393
Location
Bangalore, India
Activity points
0
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:

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
48,211
Helped
14,207
Reputation
28,673
Reaction score
12,903
Trophy points
1,393
Location
Bochum, Germany
Activity points
279,282
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.
 

Joined
Dec 4, 2012
Messages
4,294
Helped
822
Reputation
1,654
Reaction score
793
Trophy points
1,393
Location
Bangalore, India
Activity points
0
@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.
 

Attachments

  • i2c_read1.jpg
    i2c_read1.jpg
    332 KB · Views: 3

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
48,211
Helped
14,207
Reputation
28,673
Reaction score
12,903
Trophy points
1,393
Location
Bochum, Germany
Activity points
279,282
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.
 

Joined
Dec 4, 2012
Messages
4,294
Helped
822
Reputation
1,654
Reaction score
793
Trophy points
1,393
Location
Bangalore, India
Activity points
0
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.
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
48,211
Helped
14,207
Reputation
28,673
Reaction score
12,903
Trophy points
1,393
Location
Bochum, Germany
Activity points
279,282
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.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top