![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
PhilWinder
Joined: 16 Apr 2005 Posts: 23
|
I2C Stop Conditions |
Posted: Wed Dec 13, 2006 3:08 pm |
|
|
Hi,
Ive been battling with I2C Routines, and I notice that I cannot effectively find the end of the I2C data.
There should be two options, the first is to send a byte which contains the length of the data about to be transmitted.
The other, and better option, is to wait for an interrupt caused by the stop bit and then see how many bytes have been received.
The problem is that when I do try and wait for the stop bit, the communication is very unreliable.
I can basically get everything working with the stop bit interrupts when there are delays in the master routine (the master is using the standard CCS functions), but once the delays are removed, the transmission only works about 1 in 10 times.
The only thing I can think that I could do is try and shave precious uS's off the code, but ive tried, and it now looks messy, and to no avail.
BUT, it does still work well when I use the "send a length byte" method. It works 100% but obviously removes one of my error checking options.
Any thoughts?
Cheers,
Phil Winder
p.s. Just for completness ill add some code:
Code: |
#int_ssp
#inline
void Interrupt_SSP(void)
{
unsigned int8 data;
int8 dummy;
/* Make sure the buffer has not overflowed */
if (SSPCONbits.SSPOV)
{
I2C_Flags = BUFFER_OVERRUN;
}
else
{
if (I2C_Rx_Msg.msg.status != MSG_READY)
{
//I2C_Rx_Byte();
if (SSPSTATbits.P && (I2C_State == I2C_RxING))
{
I2C_Rx_Msg.msg.status = MSG_READY_PARSING;
I2C_Bus_Timeout = 0;
}
// The buffer is full, the byte was our address and there has just been
// a start bit
else if (SSPSTATbits.BF && !SSPSTATbits.D_A && SSPSTATbits.S && !SSPSTATbits.R_W)
{
for (dummy = 0; dummy < (MAX_MSG_LEN); dummy++)
{
I2C_Rx_Msg.buf[dummy] = 0;
}
data = SSPBUF;
I2C_State = I2C_RxING;
I2C_Rx_Msg.msg.status = NO_MSG;
Rx_Count = 0;
I2C_Bus_Timeout = 11;
}
else if (SSPSTATbits.BF && SSPSTATbits.D_A && (I2C_State == I2C_RxING))
{
// Read the data
/*data = SSPBUF;*/
++Rx_Count; // keep track of how many bytes
I2C_Rx_Msg.buf[Rx_Count] = SSPBUF;
/* if (I2C_Rx_Msg.msg.len == (Rx_Count - 3) )
I2C_Rx_Msg.msg.status = MSG_READY_PARSING;*/
/* I2C_Bus_Timeout = 11;*/
}
else if (SSPSTATbits.BF && !SSPSTATbits.D_A && SSPSTATbits.S && SSPSTATbits.R_W)
{
I2C_State = I2C_SLAVE_TxING;
SSPBUF = Write_Value;
SSPCONbits.CKP = 1;
I2C_Bus_Timeout = 11;
}
}
}
clear_interrupt(int_ssp);
return;
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Wed Dec 13, 2006 4:00 pm |
|
|
You can set the interrupt to occur on the stop/start condition as well as normal data. Then just send a 'stop' when the data is complete. In the intrrupt handler, test the bit in the control register, that says a 'stop' has been received, and 'voila'.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
PhilWinder
Joined: 16 Apr 2005 Posts: 23
|
|
Posted: Fri Dec 15, 2006 6:32 pm |
|
|
Hi,
Im a bit confused with your explanation, this is the Slave part of the device, and what I am saying is that the stop bit is not being interrupted, I think, because I am still in the interrupt routine dealing with the last byte of data.
Although, I was under the impression that the following interrupt would be stored, and indicated once this interrupt has finished.
Quote: | n the intrrupt handler, test the bit in the control register, that says a 'stop' has been received, and 'voila'. |
So this is what im trying to do, but unless I put delays in the master routine, it doesnt work.
I am going to rewrite some master code too, maybe using my own routines instead of CCS's will solve the problem.
Thanks for replying,
Phil WInder |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sat Dec 16, 2006 11:22 am |
|
|
There is a flag in the interrupt configuration register, which determines whether the chip will interrupt for a start/stop condition. Normally this is _disabled_, since people only want to receive data, and not be bothered to handle these conditions. You need to enable this flag, then the interrupt handler will be called for these conditions. Then in the interrupt handler you need to test the I2C status bits, to find out if start or stop has been received.
For a 18F252 for example, you need to set bit 3, of SSPCON1, to enable the exra interrupts, and whn the interrupt occurs, test bits 3, and 4 of SSPSTAT, to detect the START, and STOP bits respectively.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
PhilWinder
Joined: 16 Apr 2005 Posts: 23
|
|
Posted: Sat Dec 16, 2006 4:40 pm |
|
|
Yep already done that. Sorry!
Thanks,
Phil Winder |
|
![](templates/subSilver/images/spacer.gif) |
Kyaw Kyaw
Joined: 17 Dec 2006 Posts: 15 Location: Singapore
|
confusing with I2C mode |
Posted: Mon Dec 18, 2006 1:18 am |
|
|
Hello all,
I am a just starting user of PIC and CCS. Now I am trying to communicate ISL29001 I2C enabled light sensor and PIC 16F877A. I read through the CCS manual and write down the code as below but i cannot communicate with this device. ISL29001's address is 44h and it is needed to set internally timed by sending 30h. I also want to communicate with Computer via RS232 mode. Is it possible to use RS232 and I2C mode in one chip? Could you please give me any advise?
My written codes is as folllows;
i2c_start ();
i2c_write (68); //write the device address 44 Hex
i2c_write (48); //Set the ISL29001 as externally timed (30 Hex)
i2c_stop ();
i2c_start ();
i2c_write (68); //write the device address
data1 = i2c_read (); //Read the 8 bit data value
data2 = i2c_read (); //Read the clk information
i2c_stop ();
RETURN (data1, data2);
Thanks and Best Regards,
Kyaw Kyaw. _________________ Thanks and Best Regards,
Kyaw Kyaw. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Mon Dec 18, 2006 3:32 am |
|
|
The reason you can't read, is that if the device address is 68, then the read address will be 69.
The 'address' in I2C, only occupies the top 7 bits of the byte sent. The bottom bit is the R/W flag. So a device at address '0x44', needs to receive '0x45', to start returning data.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
Kyaw Kyaw
Joined: 17 Dec 2006 Posts: 15 Location: Singapore
|
Still got the problem! |
Posted: Mon Dec 18, 2006 7:13 pm |
|
|
Hi Ttelmah,
Now my pic can work with I2C mode but it showed all value of FF (hex) when i read the data from the light sensor. When I read through the sensor manual, it acceptable freq for I2C is 400KHz (max). My PIC clk freq is 20MHz. Is it may be the problem to communicate each other? Anyway thanks for your help and advices!
Thanks and Best Regards,
Kyaw Kyaw. _________________ Thanks and Best Regards,
Kyaw Kyaw. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|