CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

i2c communication: one master and several slaves
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Mon Jan 23, 2023 8:55 am     Reply with quote

Try modifying your INT_SSP like this:
Code:

#bit CKP=getenv("BIT:CKP")

#INT_SSP
void ssp_interrupt()
{
   state = i2c_isr_state();
   if(state== 0 )
      i2c_read(); //read address and ACK
   if(state == 0x80)
      i2c_read(2); //read address and allow stretch
   if(state >= 0x80)
   {
      i2c_write(STATO); //write data requested in buffer
      CKP=TRUE; //force clock release.
   }
   else if(state > 0)
   {
      da_master = i2c_read(); //read data from master and ACK
      Arrivato=TRUE; //set the flag
   }
}


This is a fix that has to be used on some other chips that are unreliable
at releasing the clock when the data is written to the buffer. Your chip
is not shown as being one with this problem, but it is worth trying.
However your master test code does not show a write being done,
which this affects, not a read. You can though try adding the same after
the read.

If you are clocking at 10000, which your master shows, this should
be slow=10000. The fast and slow keywords affect some other parts
of the I2C timing. Fast should only be used above 100KHz.

Now, though your bus is short, the capacitance could be quite high.
Each device adds at least 5pF, and possibly more, depending on your
board layout. At 100K, 3K3 would only be low enough for about 80pF
total capacitance. Might well be worth reducing this to perhaps 1K5.

Aaargh!..
Just spotted what is probably your problem. These chips have slew rate
control. Look at the sticky at the top of the forum. You need to be turning
this off, or it'll always be unreliable.

set_slow_slew_c(FALSE);

(at both ends).

The _port_ slew rate control is separate from the I2C slew rate control
which the I2C setup manages.
Mvedovetto



Joined: 17 Aug 2007
Posts: 38

View user's profile Send private message Send e-mail

PostPosted: Mon Feb 06, 2023 12:58 pm     Reply with quote

Sorry for delay...

Thank you Ttelmah for your reply

I tried to modify code with

Code:
set_slow_slew_c(FALSE);
.

But no success. Evil or Very Mad

Moreover, MPLAB 5.40 does not recognize more pre-processor #bit.

Microchip Datasheet at chapter 29.5.2 says that 16F18424 stretches SCL not only in transmission, but also in reception. I tried to write my own i2c code.

Stretching SCL control has no issues if applied to data bit reception, but because slave does not ack, i tried to control stretching SCL also prior to check ack. software stucks if I add this control there.

Here it is i2c write function

Code:
int i2cc_write(int o_byte)
{
   int n;
   for(n=0; n<8; n++)
   {
     
     
      if(bit_test(o_byte,7-n))
      {
         i2c_high_sda();
      }
      else
      {
         i2c_low_sda();
      }
     
      do                                        // manage slave clock stretching
       i2c_high_scl();         
      while(I2C_SCL==0);       //<<< this gives no problem

      i2c_low_scl();
     
   }
   i2c_high_sda();                 //wait for slave answer (sda pin in input mode with tris_b)
   
   
   i2c_high_scl();                      //<<< this gives no problem


                             //if here I put the code to manage slave clock stretching
 
                            // do                                       
                           //    i2c_high_scl();         
                            // while(I2C_SCL==0);      
                           
                           //flow stucks
                             


   n=input(I2C_SDA);              //check for ack
   i2c_low_scl();                        //control the bus
   
   
   return(n);      // return 1 => NO ACK; 0 => ACK
 
   
}


I also explore for hardware issues. Because slave drives solenoids (with no switch) I thought that some EMI could cause malfunctioning: I add TVS on SDA and SCL lines, without success. I leave solenoids unmounted. But no improvement!
I begun to use i2c with microchip 15 years ago. Never occurred such stuff!
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Tue Feb 07, 2023 2:04 am     Reply with quote

First, it is CCS that is compiling your project, not MPLAB. So what MPLAB
recognises does not matter at all. Second though, if the project is correctly
including the CCS header file, the syntax checking in MPLAB, merrily
recognises #bit. If this is not being recognised, something is wrong in
your MPLAB setup, or the file include order. May explain why you are
having problems.....

If it isn't CCS that is compiling your project, then you are in the wrong
forum. This is a support forum for the CCS compiler.

SCL stretching, is _required_ in I2C. Part of it. Otherwise how can
the slave tell the master 'hold it I'm busy'. The point is that the hardware
clears the stretching when the data is correctly read. However on some
PIC's this doesn't always work correctly, which is why the CKP clear
may be needed.
Get #bit working. On some chips it is essential.

Stop specifying the ack/nack in your I2C commands. Let it be default,
except on the single read that requires clock stretching. Look at the CCS
example file. The only place this is specified is in the one where the
clock has to be held. Look in particular at the example for the K42,
(ex_slave_K42.c), which shows handling a slave on a chip with PPS.
In particular note that this uses NOCLEAR. The reason for this, is to
ensure the interrupt is not prematurely cleared, till the hardware
itself clears the bit.
Mvedovetto



Joined: 17 Aug 2007
Posts: 38

View user's profile Send private message Send e-mail

PostPosted: Wed Feb 08, 2023 3:54 am     Reply with quote

Thank you for reply and patience

Quote:
First, it is CCS that is compiling your project, not MPLAB. So what MPLAB
recognises does not matter at all. Second though, if the project is correctly
including the CCS header file, the syntax checking in MPLAB, merrily
recognises #bit. If this is not being recognised, something is wrong in
your MPLAB setup, or the file include order. May explain why you are
having problems.....

If it isn't CCS that is compiling your project, then you are in the wrong
forum. This is a support forum for the CCS compiler.


Sure, I'm compiling with CCS and no error or warning arises when code compiles. So warning in IDE will be a don't care for me.

I'll do a deeper analysis and update.
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Wed Feb 08, 2023 4:07 am     Reply with quote

I just went and tried with the 324 chip in MPLAB, and on both an old V5
version and a V6 version the #bit is not being flagged in MPLAB for me.
Odd.
Mvedovetto



Joined: 17 Aug 2007
Posts: 38

View user's profile Send private message Send e-mail

PostPosted: Thu Feb 09, 2023 10:45 am     Reply with quote

Thank you very much, Ttelmah, for your reply,
I have been working on solving the problem. I will have a look at mplabx ide issue next time.

But I am happy to say that I solved it! And thanks to all of you! Really a big help!

I realised by your support that i2c was well done: I used all your suggestions. In the end I focused on the whole application. I built an i2c scanner and by chance I observed that after the master had configured all the slaves by assigning each a unique address, this address was not loaded at power-up. As I said, I use an external pin to switch between configuration mode and operation mode. In configuration mode, the address is always the same and only one slave at a time receives it and is different from the others (a maximum of 64 slaves are allowed). When I forced the input status of the external pin, I no longer had any problems! In the real application, each slave sets or deletes the external pin of the next slave. Now, if a slave starts up a little earlier than the previous slave (note that the slave has a pre-processor directive PUT_1MS anyway) and the voltage on the pin is higher than the logical high threshold, the slave realises that it has to enter configuration mode and sets the appropriate address for configuration not operation. So when the master looks for the operational address it cannot find it and skips the slave. I put a pull-down resistor on the configuration pin of each slave and have had no more problems!

Thanks again for the support
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Thu Feb 09, 2023 12:09 pm     Reply with quote

Jay was querying how the address reprogramming was done.
Ouch!...
Makes total sense though. Sad
asmallri



Joined: 12 Aug 2004
Posts: 1635
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Feb 15, 2023 9:40 pm     Reply with quote

Mvedovetto wrote:
OK guys, this is the interrupt routine of slave

Code:

void ssp_interrupt(){
       
    state = i2c_isr_state();
    if(state== 0 ) i2c_read();              //read address and ACK
    if(state == 0x80)
    i2c_read(2);                            //read address and allow stretch
    if(state >= 0x80)
    i2c_write(STATO);                       //write data requested in buffer
    else if(state > 0)
    {
        da_master = i2c_read();             //read data from master and ACK
        Arrivato=TRUE;                      //set the flag
    }

}


This code spends too long in the interrupt handler. Consider changing it like this.

Code:

void ssp_interrupt(){
       
    state = i2c_isr_state();
    if (state == most common possible state)
    {
       do something
       exit the interrupt handler
    }

    if (state == next highest common possible state)
    {
       do something
       exit the interrupt handler
    }

    if (state == next highest common possible state)
    {
       do something
       exit the interrupt handler
    }

   // here all other states high frequency states able been handled
   // therefore this is the last possible state so no test required
   do something
}

_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Mvedovetto



Joined: 17 Aug 2007
Posts: 38

View user's profile Send private message Send e-mail

PostPosted: Mon Feb 20, 2023 10:47 am     Reply with quote

Thank you asmallri for suggestion,
you're right, although I have just to read the value sent by master and use it in the main code, it could be interesting optimizing handling.
Mvedovetto



Joined: 17 Aug 2007
Posts: 38

View user's profile Send private message Send e-mail

PostPosted: Mon Feb 20, 2023 10:56 am     Reply with quote

Ttelmah wrote:
Jay was querying how the address reprogramming was done.
Ouch!...
Makes total sense though. Sad


I realised that the answer to Jay (Temtronic) was not clear on how to reprogramme the slave address. But that was when I discovered the problem! Crying or Very sad
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group