|
|
View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19495
|
|
Posted: Mon Jan 23, 2023 8:55 am |
|
|
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
|
|
Posted: Mon Feb 06, 2023 12:58 pm |
|
|
Sorry for delay...
Thank you Ttelmah for your reply
I tried to modify code with
Code: | set_slow_slew_c(FALSE); | .
But no success.
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: 19495
|
|
Posted: Tue Feb 07, 2023 2:04 am |
|
|
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
|
|
Posted: Wed Feb 08, 2023 3:54 am |
|
|
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: 19495
|
|
Posted: Wed Feb 08, 2023 4:07 am |
|
|
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
|
|
Posted: Thu Feb 09, 2023 10:45 am |
|
|
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: 19495
|
|
Posted: Thu Feb 09, 2023 12:09 pm |
|
|
Jay was querying how the address reprogramming was done.
Ouch!...
Makes total sense though. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Wed Feb 15, 2023 9:40 pm |
|
|
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
|
|
Posted: Mon Feb 20, 2023 10:47 am |
|
|
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
|
|
Posted: Mon Feb 20, 2023 10:56 am |
|
|
Ttelmah wrote: | Jay was querying how the address reprogramming was done.
Ouch!...
Makes total sense though. |
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! |
|
|
|
|
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
|