|
|
View previous topic :: View next topic |
Author |
Message |
Steve Smith
Joined: 30 Mar 2011 Posts: 6 Location: Hampshire
|
General Call Problem with I2C Slave code within PIC16F1936 |
Posted: Wed Mar 30, 2011 7:51 am |
|
|
I have a problem with General Call in my I2C slave code. I hope that someone can help.
I have copied the format of the pksa.c file in the Microchip website. The main difference is that my code is within an ISR. I have four states which are derived from masking SSPSTAT for relevant bits.
Everything seems to work fine until I address my slave with General Call.
Then things go a bit strange.
If the previous command to my slave was purely writing data from the Master, then the General Call works absolutely fine.
However, if the previous command to my slave includes the Master reading data from the slave (which also works fine), the General Call goes 'screwy' after this point.
My slave always generates an ACK (addr match), but the R/W bit is set! This bit stays set for every subsequent data byte written from Master to Slave. As my states are expecting the R/W bit to be clear when writing data in to slave, the data is being lost!
This happens 100% of the time. The only way I can use General Call to write commands in to the slave, is to precede the General Call with a 'Unique I2C Address match' command containing purely write bit set data.
After which General Call works again.
I currently only use General call to change the unique I2C Address of the Slave.
CCS Compiler Version 4.119. PIC16F1936.
Code: |
#define _STATUS_MASK 0x2C
SSPSTAT = 0x80; //Slew rate disabled for standard speed mode (100KHz)
SSPCON1 = 0x36;
GCEN = ENABLED;
SSPCON2 = 0x81;
SSPCON3 = 0x00;
Cut down code
#INT_SSP
void i2c_isr(void)
{
BYTE incoming, _I2C_State;
static byte index = 0x00;
byte temp1;
state = i2c_isr_state();
_I2C_State = SSPSTAT & _STATUS_MASK;
switch (_I2C_State)
{
case ADDR_WRITE:
AddressedToMe = TRUE;
incoming = SSPBUF; index = 0x00;
break;
case DATA_WRITE:
incoming = SSPBUF;
index++;
if (index < MAXBUFFERSIZE) {
CommsReceiveBuffer[index-0x01] = incoming; }
else
{
CommsReceiveBuffer[MAXBUFFERSIZE-0x01] = incoming; }
break;
case ADDR_READ:
index = 0x00;
case DATA_READ:
{
NeedToWriteToMaster = TRUE; SSPBUF = CommsSendBuffer[state - 0x80];
if ((CommsReceiveBuffer[COMMANDPOSITION] == READ_FROM_NV_MEMORY_REQ) && (DataReadFromEeprom == FALSE))
{
I2C_CLK_LINE_STATE = HOLD; ReadFromEeprom();
DataReadFromEeprom = TRUE;
}
if (index <= MAXBUFFERSIZE) {
do
{
WCOL = 0;
SSPBUF = CommsSendBuffer[index];
}while(WCOL);
I2C_CLK_LINE_STATE = RELEASE;
index++;
}
else
{
do
{
WCOL = 0;
SSPBUF = 0xFF;
}while(WCOL);
I2C_CLK_LINE_STATE = RELEASE;
index++;
}
}
}
SSPIF = CLEAR;
enable_interrupts(INT_SSP);
I2C_CLK_LINE_STATE = RELEASE;
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Wed Mar 30, 2011 8:12 am |
|
|
I don't think a GCA, with 1 in the low bit is legal.
GCA, is a broadcast from the master to all slaves on the bus. The I2C documentation only shows this with a 0 in the low bit. How can you broadcast to everyone, then have a reply?. After all every device on the bus would reply to this?.
You can set an address inside GCA, and then address a specific slave, and have this reply, but a 'general call', with all devices replying, would break the bus....
Best Wishes |
|
|
Steve Smith
Joined: 30 Mar 2011 Posts: 6 Location: Hampshire
|
Reply to Ttelmah |
Posted: Wed Mar 30, 2011 8:28 am |
|
|
Firstly, thank you for looking at my issue and replying so quickly.
I agree, a GCA with a 1 in the R/W bit is illegal. Also, if I tried to do this, all slaves would talk at once. However, this is what the PIC is generating within SSPSTAT register. I can not control it. This is the problem I have.
When I carry out a General Call, all I wish to do is to write a command and data to the slave, and because of this I would expect the R/W bit to be 0 (write). I do not ever try to read data from the slave under General Call.
The R/W bit seems to be set to a 1 by the PIC during a General Call, ONLY if the previous communications between Master and Slave included the Master reading data from the Slave. If the previous communcation was the Master purely writing to the Slave, then the next General Call works absolutely fine.
Regards |
|
|
Steve Smith
Joined: 30 Mar 2011 Posts: 6 Location: Hampshire
|
|
Posted: Wed Mar 30, 2011 8:41 am |
|
|
Just to clarify, when I talk about 'previous communications between Master and Slave' and 'Everything else seems to work fine', I am referring to addressing the Slave with its unique address.
The only issue I seem to be getting, is when I try to send a command and data to the slave under General Call after I have read data from slave addressing it with its unique address value.
Sorry for any confusion.
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Wed Mar 30, 2011 8:43 am |
|
|
So are you following the full CGA standard?. Send the GCA, followed by '4', or '6' (the former says 'set the settable part of the address', while the latter says 'reset, and set this address'. The slave device to a GCA, is _required_ to ACK the bus, and wait for the second byte. A GCA, is not complete, till the second byte is sent. This is then followed by the 'programming sequence' (which you will have to define), designed to send the addresses in such a way that chips will each get a unique address.
Best Wishes |
|
|
Steve Smith
Joined: 30 Mar 2011 Posts: 6 Location: Hampshire
|
|
Posted: Wed Mar 30, 2011 9:25 am |
|
|
Thanks again. I will look at the spec more closely for General Call.
However, if I pause my code (running in MPLAB Debugger) straight after I send Start then 00 (general call), the R/W bit in SSPSTAT is still a 1. Surely this bit should be a 0?
Regards |
|
|
|
|
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
|