View previous topic :: View next topic |
Author |
Message |
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Sat Jan 11, 2020 2:29 am |
|
|
Hi everybody
From PCM programmer:
Quote: | 1. Don't run both programs at 64 MHz. Run the master at 4 MHz
and the slave at 16 MHz. |
I have 16 MHz crystals for both master and slave on the board. Disabled PLL of the master so master run at 16MHz, slave at 64MHz.
Quote: | 4. Don't run i2c FAST mode. Run it at 100 KHz. |
Changed to Slow 100 KHz
With this two changes, sending/receiving 2 data bytes everything works OK, slave not hanging
Thank you again PCM programmer.
Tried with both master and slave at 64MHz and Slow 50000, the slave hangs.
I will try now to send/receive more bytes with Master at 16MHz, Slave at 64MHz
Best wishes
Joe |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Sat Jan 11, 2020 3:29 am |
|
|
Hi
Update:
Write/read 8 bytes or more works fine, slave not hang
Read 8 bytes or more works fine, slave not hang
The Master works at 16MHz, Slave at 64MHz.
Master Slow=100000
Thank you again for all who posted on this topic
How I can make the program to work if both Master and slave works at 64MHz?
Master Slow=100000 is OK in the program, but the I2C is just part of the program and I need the master to work at 64MHz for some other functions.
Best wishes
Joe |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19477
|
|
Posted: Sat Jan 11, 2020 4:08 am |
|
|
Normal thing is to add a slight delay between sending the read address
and reading the first byte.
The slave has to respond to the address interrupt, then load the byte to
send, before the master can start to read. Typically allow perhaps 60 machine
cycles here (5uSec should be enough). It's always easier to have the slave
running faster than the master because of this.
Most of the other operations should self synchronise.
This is a difference with a 'software controlled' slave, to one where
all the operations are being done by hardware.
Generally, when a chip is run faster it becomes more sensitive to RFI,
and any 'shortcomings' in the layout. So you really do need to be careful
with the supply decoupling etc. |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Sat Jan 11, 2020 4:37 pm |
|
|
Thank you Ttelmah
The program blocks that need high Master speed were working on PIC18F2520 at 32MHz when maximum speed of the microcontroller is 40MHz.
The reason to change to PIC18F26K22:
* To add the I2C communication instead of rs232 serial communication between the Master and Slave.
* To have rs232 master communication with two external (not on board) devices on separate rs232 hardware each, not one rs232 for the Slave and two external device.
* To change speed to 64MHz for the high speed program parts, to get double accuracy.
Originally the high speed program blocks, written in assembler, were working on PIC16F876 at 16MHz.
I changed to CCS C for the PIC18F2520 as at 32MHz CCS C give me better performances than assembler at 16MHz and much more easy maintenance.
As you advised:
* Will check how the I2C works with the delay you proposed.
* I will improve the power supply decoupling for testing.
* I will improve the power supply decoupling as the system works in heavy RFI & EMI environment.
* I will build a new board with 8MHz crystal for Master and 16MHz for the slave to work at 32MHz Master and 64MHz Slave.
Not best solution as I am losing the accuracy I wanted to get working the Master at 64MHz.
Any additional advice is very welcome
Thank you again and best wishes
Joe |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Mon Jan 13, 2020 1:17 am |
|
|
Hi
An update:
* I improve the power supply decoupling
* I added the delay Ttelmah advised.
Both Master and Slave running at 64MHz
At Slow=100000 the slave hangs on different data values
I added additional delays as bellow:
Code: | //write data to Slave PIC
i2c_start();
i2c_write(0xB0);//Slave address with write
delay_us(5);
i2c_write(data0);
delay_us(5);
i2c_write(data1);
delay_us(5);
i2c_write(data2);
delay_us(5);
i2c_write(data3);
delay_us(5);
i2c_write(data4);
delay_us(5);
i2c_write(data5);
delay_us(5);
i2c_write(data6);
delay_us(5);
i2c_write(data7);
delay_us(5);
i2c_stop();
//read back data from the Slave PIC
delay_us(1000); //ensure the Slave has had time to complete the write
i2c_start();
i2c_write(0xB1);//Slave address with read
delay_us(5);
slaverpt0 = i2c_read();
delay_us(5);
slaverpt1 = i2c_read();
delay_us(5);
slaverpt2 = i2c_read();
delay_us(5);
slaverpt3 = i2c_read();
delay_us(5);
slaverpt4 = i2c_read();
delay_us(5);
slaverpt5 = i2c_read();
delay_us(5);
slaverpt6 = i2c_read();
delay_us(5);
slaverpt7 = i2c_read(0);
delay_us(5);
i2c_stop();
I2C26K22SnewdataF=1; |
I made long testing of write/read and read and I had the Slave hangs after 1679, 1342, 1903 and 2269 write/read with read from time to time.
I tested also with FAST=400000 and Slave hangs after approximately 150 write/read and a few read.
I have two questions:
* It is OK to insert the delays before & after each write or read?
* If Slow=50000 the I2C will work at 50000 BPS?
Best wishes
Joe |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Mon Jan 13, 2020 2:16 am |
|
|
Additional update:
Both Master and Slave running at 64MHz
At Slow=50000
I tested for 6,000 write/read and read and I had no Slave hang
I will add watchdog timer and test what happening if Slave hangs
Best wishes
Joe |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19477
|
|
Posted: Mon Jan 13, 2020 7:28 am |
|
|
OK.. What is your pull up resistor value on the bus?.
The slew rate available is controlled by this.
This is dependant on the capacitance of the bus, supply voltage, and the
speed you require.
With your bus going to two devices, the bus capacitance will be higher
than for a single device. Unlikely to be less than perhaps 100pF if the wires
are more than a very few cm long. So for a bus at this capacitance level at
100KHz at 3.3v for a device only supporting the minimum drive current,
we have:
Rp(min) = Vdd-0.4v/0.003 = 966R
Now the max value depends on the slew rate that must be met and is:
Rp(max) = Tr/0.8473 * Cb
Where Cb is the bus capacitance and Tr is the rise time allowed. Standard
mode (50KHz) requires a rise time of 1uSec, while fast mode at 400KHz
requires 300nSec. So with a 50pF bus capacitance, we get:
Rp(max 400K) = 300E-9/0.84673 * 100E-12 = 3K5R
So to run at 400K you need pull up resistors between 1K and 3.3K
(for standard E12 values).
If your resistors are above this, it explains why you have problems
when you increase the speed. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9215 Location: Greensville,Ontario
|
|
Posted: Mon Jan 13, 2020 8:07 am |
|
|
His original post says 5 volts (I just checked, cause I'm old and gets confused easily'.....
Mind you he may have changed things in 4 pages..... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19477
|
|
Posted: Mon Jan 13, 2020 8:40 am |
|
|
OK. Fair enough. I thought I remember him switching to a DsPIC at
some point....
The change to 5v, simply increases the size of Rp(min) for the higher voltage.
Becomes 1300R.
However the Rp(max) doesn't change. So the resistor range to do 400KHz
gets narrower (the reason it doesn't change is that the bus levels are
defined as percentages of the supply rail).
At 400K, resistors a lot smaller than most people start with. |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Mon Jan 13, 2020 4:42 pm |
|
|
Hi Ttelmah and Temtronic
I am working with 5V from the beginning. Never used something else.
From my post at January 8:
Quote: | After getting my new boards and assemble them with two PIC18F26K22 and a 24C512 EEPROM and adapting the I2C programs to the PIC18F26K22 I started testings to be sure that everything works OK.
On the I2C lines I have 2K7 pull-up resistors (on SCL and SDA lines). |
Started from the beginning with 2K7 resistor on SCL and SDA.
I never used DsPIC.
My compiler:
CCS PCH C Compiler, Version 5.062
The lines on the board are:
* 15 mm between Master and 24FC512
* 45 mm between Master and Slave
The board is 2 layers with copper pour both sides.
The lines are 12.5 mill
I can change the resistors to smaller if necessary by building a new board.
Thank you and best wishes
Joe |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Mon Jan 13, 2020 9:38 pm |
|
|
Hi
I tested 4000 write/read and read:
WDT enabled with reset at 16ms
Master and Slave at 64MHz
Code: | #use I2C(MASTER, Fast=400000, I2C1, STREAM=I2CPORT)//I2C1 hardware used |
I had Slave reset at write/read or read as bellow:
364, 579, 739, 2036, 2865, 3158, 3650, 3771, 3843.
I can work with it as above, but I will use:
Code: | #use I2C(MASTER, Slow=50000, I2C1, STREAM=I2CPORT)//I2C1 hardware used |
as this speed is more than enough for my project.
If somebody have additional remarks or advice I will be happy to try to implement them.
Thanks again to everybody that helped me to get here
Best wishes
Joe |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19477
|
|
Posted: Tue Jan 14, 2020 1:31 am |
|
|
There is one other thing you can do to improve the reliability.
Basically on the master, read the input_state of the SDA line before
starting a transaction. If this is not '1', then the I2C bus is hung.
If it is '0', disable the I2C.
1)
Then clock SCL low and release it.
Test SDA again. If still '0' loop back to '1)'.
If now '1', tri-state the SCL line, and re-enable the I2C.
This is the standard 'I2C' recovery sequence for a peripheral that
has missed a bit. |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Tue Jan 14, 2020 2:53 pm |
|
|
Hi Ttelmah
I will implement what you are proposing and will post the implementation.
with Slow 50000, I made one more test of 10,000 read/write and read and I had one Slave hung after 7,132 lines, WDT reset the Slave and everything continued OK.
Thank you and best wishes
Joe |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Fri Jan 31, 2020 5:38 pm |
|
|
Back again on this topic
After integrating the I2C Master with other program blocks, I have some errors NOT with the I2C but other blocks of the program that are interrupt triggered.
When I2C reading the Slave 9 bytes ones in 2000ms the errors are negligible but reading ones in 200ms the errors are much more.
I am posting the LST of the read and write:
Quote: | .................... i2c_write(slavedata0);
00BF4: MOVFF 68,AF
00BF8: RCALL 0944
*
00944: BCF FC6.7
00946: BCF F9E.3
00948: MOVFF AF,FC9
0094C: MOVLW 02
0094E: BTFSC FC6.7
00950: BRA 095C
00952: BTFSS F9E.3
00954: BRA 0952
00956: MOVLW 00
00958: BTFSC FC5.6
0095A: MOVLW 01
0095C: MOVWF 01
0095E: RETURN 0
///////////////////////////////////////////////////////
.................... slaverpt0 = i2c_read();
00CB0: MOVLW 01
00CB2: MOVWF 00
00CB4: RCALL 0988
*
00988: BCF FC6.6
0098A: BSF FC5.3
0098C: BTFSC FC5.3
0098E: BRA 098C
00990: BTFSC 00.0
00992: BCF FC5.5
00994: BTFSS 00.0
00996: BSF FC5.5
00998: BSF FC5.4
0099A: BTFSC FC5.4
0099C: BRA 099A
0099E: MOVFF FC9,01
009A2: RETURN 0 |
The delay LST:
Quote: | .................... delay_us(5);
00CA6: MOVLW 1A
00CA8: MOVWF 00
00CAA: DECFSZ 00,F
00CAC: BRA 0CAA
00CAE: NOP |
I understand the assembler of the LST.
My question is what will happen if an interrupt occurs while the program is in the middle of executing one of the above?
It will go out to serve the interrupt or will serve the interrupt when the execution is ended?
EDIT: In the past for the Master/Slave I was using rs232 in the program and had no errors.
Best wishes
Joe |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19477
|
|
Posted: Fri Jan 31, 2020 11:35 pm |
|
|
The interrupt will occur as normal.
The 'exception', would be if you have either a delay, or an I2C
transaction inside any interrupt. If you do, the compiler will give you
a warning that 'interrupt disabled to prevent reentrancy', and interrupts
will be disabled round each of the matching code in the main.
Much more important though is latency. If you have for example a timer
interrupt in your slave, it will not be guaranteed to react to the I2C
interrupt untill it comes out of this. Result the latency shoots up.
Depending on what interrupts you are actually using, you can add the
line:
#device HIGH_INTS=TRUE
near rhe start of your code, and have the I2C interrupt coded as
#INT_SPI HIGH
This interrupt can then interrupt other interrupts, getting rid of this
extra latency. |
|
|
|