|
|
View previous topic :: View next topic |
Author |
Message |
vetinaspin
Joined: 19 Nov 2005 Posts: 5 Location: Devon, England
|
Help needed - Changing modes in I2C |
Posted: Mon Jan 02, 2006 6:45 am |
|
|
Happy New year!!
No-one answered my question I posed before Christmas about changing between I2C Master and Slave modes at runtime.
Is it impossible, or does nobody know the answer?
I can't believe with all the code-writers out there that it hasn't been done.
I am using a PIC18F452 and for most of the time I want the PIC to act as a master on the i2c bus. Occassionally it needs to be a slave.
I initialise the i2c port with:
#use i2c(MASTER, sda=PIN_C4, scl=PIN_C3,FORCE_HW)
Later on in the code when I need to receive data from another device I try to change the I2c port by:
#use i2c(SLAVE, sda=PIN_C4, scl=PIN_C3, Address=0xA0)
But it doesn't work!! The PIC stays as a master.
If I look at the CCS listing there is no new code added where I want the change to take effect.
How do you change from master to slave and back again and why does the compiler ignore the directive?
grateful for any suggestions |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jan 02, 2006 2:29 pm |
|
|
Quote: | No-one answered my question I posed before Christmas about changing
between I2C Master and Slave modes at runtime. Is it impossible, or
does nobody know the answer?
I can't believe with all the code-writers out there that it hasn't been done. |
I haven't done this, but no one else has responded so I've put
together a possible framework that might solve your problem.
You will have to fill in the missing code.
The key thing that you need to understand is that once you put
down a #use i2c() statement, all i2c library functions after that
that point will be configured according to the parameters specified
in the #use i2c() statement.
If you then put down another #use i2c() statement farther down
in the program, all i2c library functions after that point will
use the parameters specified in that statement. You can see how
I use this feature in the code below.
However, CCS does not really expect you to be doing this, so they
don't have routines that you can call, to init for master or slave mode.
They put code in there to do that, but it's part of the hidden init code
that they insert at the start of main(). In the program shown below,
only code for Master mode will be inserted by the compiler at the
start of main().
Because you want to switch between modes, you need to look at the
.LST file and determine which lines of ASM code are used to init the
master mode, and then essentially copy that code and put it into your
own master_i2c_init() routine.
To find out how CCS initializes the slave mode, you need to compile
their example program, EX_SLAVE.C, and do that same thing.
Look at the .LST file near the start of main() and copy the code and
put it into slave_i2c_init().
By "copy the code", I actually mean re-write it, by using direct register
access statements, and use #byte and #bit statements to define the
register and bit addresses. Also consult the PIC data sheet while doing
this.
Code: | #include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
// The following 3 lines are from EX_SLAVE.C.
typedef enum {NOTHING, CONTROL_READ,
ADDRESS_READ, READ_COMMAND_READ} I2C_STATE;
I2C_STATE fState;
BYTE address, buffer[0x10];
//---------------------------------
void master_i2c_init(void)
{
// Disable slave interrupts.
disable_interrupts(INT_SSP);
clear_interrupt(INT_SSP);
// Put code here to setup MSSP module for i2c master mode.
// Look in the PIC data sheet to find the proper registers.
// Use #byte and #bit directives to define the addresses
// of the registers.
// Also, look at the .LST file, to see how CCS initializes
// the master mode. Copy what they do.
}
//---------------------------------
void slave_i2c_init(void)
{
// Put code here to setup MSSP module for i2c slave mode.
// Look in the PIC data sheet to find the proper registers.
// Use #byte and #bit directives to define the addresses
// of the registers.
// Also, look at the .LST file, to see how CCS initializes
// the slave mode. Copy what they do.
// After doing that, enable interrupts for the slave.
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
}
//----------------------------------
#use i2c(Slave, sda=PIN_C4, scl=PIN_C3, address=0xA0, Force_HW)
#INT_SSP
void ssp_interupt ()
{
// Put isr code here from the CCS example file, EX_SLAVE.C
}
#use i2c(Master, sda=PIN_C4, scl=PIN_C3, Force_HW)
//=====================================
void main()
{
int8 result;
int16 address;
// Configure for Master mode.
master_i2c_init();
address = 0x0000;
// Master reads a byte from 24LC256 eeprom.
i2c_start();
i2c_write(0xA0); // i2c write address
i2c_write(address >> 8);
i2c_write(address);
i2c_start(); // re-start
i2c_write(0xA1); // i2c read address
result = i2c_read(0); // Read with NACK
i2c_stop();
// Configure for Slave mode.
slave_i2c_init();
while(1);
}
|
|
|
|
vetinaspin
Joined: 19 Nov 2005 Posts: 5 Location: Devon, England
|
Changing modes in I2C |
Posted: Tue Jan 03, 2006 2:16 am |
|
|
Thanks for your reply.
I had hoped there was another solution but looking at the way the CCS compiler references the initial code I can see there is not. I know exactly what you are saying regarding the solution so I will go down this route.
Many thanks. |
|
|
|
|
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
|