CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I2C Stop Conditions

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PhilWinder



Joined: 16 Apr 2005
Posts: 23

View user's profile Send private message

I2C Stop Conditions
PostPosted: Wed Dec 13, 2006 3:08 pm     Reply with quote

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;
}
Ttelmah
Guest







PostPosted: Wed Dec 13, 2006 4:00 pm     Reply with quote

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
PhilWinder



Joined: 16 Apr 2005
Posts: 23

View user's profile Send private message

PostPosted: Fri Dec 15, 2006 6:32 pm     Reply with quote

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
Ttelmah
Guest







PostPosted: Sat Dec 16, 2006 11:22 am     Reply with quote

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
PhilWinder



Joined: 16 Apr 2005
Posts: 23

View user's profile Send private message

PostPosted: Sat Dec 16, 2006 4:40 pm     Reply with quote

Yep already done that. Sorry!

Thanks,

Phil Winder
Kyaw Kyaw



Joined: 17 Dec 2006
Posts: 15
Location: Singapore

View user's profile Send private message AIM Address MSN Messenger

confusing with I2C mode
PostPosted: Mon Dec 18, 2006 1:18 am     Reply with quote

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.
Ttelmah
Guest







PostPosted: Mon Dec 18, 2006 3:32 am     Reply with quote

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
Kyaw Kyaw



Joined: 17 Dec 2006
Posts: 15
Location: Singapore

View user's profile Send private message AIM Address MSN Messenger

Still got the problem!
PostPosted: Mon Dec 18, 2006 7:13 pm     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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