View previous topic :: View next topic |
Author |
Message |
facosta.ie
Joined: 29 Nov 2016 Posts: 5
|
Switch from Slave to Master in I2C during execution. |
Posted: Tue Nov 29, 2016 12:35 pm |
|
|
Hi, I'm trying to change a PIC18F25k80 from slave to master and vice versa during the program execution, is this posible?
My PIC works fine as master and as Slave individualy using the instructions:
#use i2c(SLAVE,ADDRESS=0x16,sda=PIN_C4,scl=PIN_C3,)
Or
#use i2c(MASTER,sda=PIN_C4,scl=PIN_C3)
But I need that the same IC2 works sometimes like master and sometimes like slave.
Thanks in advance. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Tue Nov 29, 2016 2:35 pm |
|
|
Setup the two uses with streams.
You will need to behave like in multi master mode, and not use the master, unless the clock line is high.
Use force_hw on the slave setup, and software for the master (you are already doing this, I2C defaults to software mode for the master unless you use force_hw).
Obviously your master should not try to talk to the address used by the slave. |
|
|
facosta.ie
Joined: 29 Nov 2016 Posts: 5
|
|
Posted: Tue Nov 29, 2016 5:09 pm |
|
|
Slave works ok, but master is not working, I use the Slave Stream in the interrupt and the Master Stream when I want to read another Slave, any suggestion?
P.S when I quit the Slave USE the master works correctly. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Tue Nov 29, 2016 6:00 pm |
|
|
perhaps there is a particular register bit that must be set master vs slave? If so, you may have to do that manually. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Wed Nov 30, 2016 1:49 am |
|
|
You do understand that you have to switch off the slave peripheral to run the master. They can't both be enabled at the same time:
Code: |
#use i2c(SLAVE, ADDRESS=0x16, I2C1 STREAM=slaveI2C)
#use i2c(MASTER,sda=PIN_C4,scl=PIN_C3, baud=100000, STREAM=masterI2C, force_sw) //ensure this is using software
//Then your code in the slave interrupt, must use the stream name
//so:
val = I2C_read(slaveI2C); //etc..
I2C_write(slaveI2C, val); //etc..
//Then when you want to use the master:
while (input(PIN_C3==0)
{
//do something. The master cannot be enabled something else
//is driving the bus
//you really need to use a timer here, and only enable the master
//if the line stays high for a few mSec
}
I2C_init(slaveI2C,FALSE); //switch off the slave peripheral
//Now you should be able to drive the software I2C
I2C_start(masterI2C);
i2C_write(masterI2C, val); //etc..
//Then when the transaction is complete
I2C_init(slaveI2C,TRUE); //re-enable the slave
|
|
|
|
facosta.ie
Joined: 29 Nov 2016 Posts: 5
|
|
Posted: Wed Nov 30, 2016 10:33 am |
|
|
Thanks for your answers, Ttelmah and jeremiah with the I2C_init() instruction was enough to enable and disable one or another, it works fine.
I was testing the clk pin(C3), for enable the master and it stucks, if I don't test this pin, the master enables and disables correctly.
For my application I'll be testing a control pin wich will tell me the moment to act like master or slave, with this pin I will not need check the clk pin right? Only will be one master enabled in the bus. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Wed Nov 30, 2016 11:24 am |
|
|
A control pin is much better.
Remember though to not turn it off on whichever device operates it, until the transaction has completed.
You should be able to read C3 though. I suspect the problem here is TRIS. By default in standard I/O mode, reading the pin would change the TRIS. You read the pin in multi-master mode, and to avoid two devices trying to operate the clock at the same time, but when I've done this I've always been in fast_io mode (so controlling the TRIS). Even with this being read, you have the problem without a separate control, if two devices start at the same time. This is why you have to add bus collision detection when using multi-master. So a separate control line is very much better. |
|
|
facosta.ie
Joined: 29 Nov 2016 Posts: 5
|
|
Posted: Wed Nov 30, 2016 12:25 pm |
|
|
Thank you again for your help Ttelmah, I think that the control line is what I need to sync correctly the devices and avoid collisions.
I'll test the complete system and will tell you the results.
Regards. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Wed Nov 30, 2016 12:35 pm |
|
|
Side note: If you want to read a pin in standard IO mode without changing the input/output state, the input_state() function is an additional option. It'll read the pin without changing the TRIS settings. I prefer to use this rather than fast IO or fixed IO. |
|
|
|