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 support@ccsinfo.com

I2C slave problem

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



Joined: 26 Apr 2010
Posts: 56

View user's profile Send private message

I2C slave problem
PostPosted: Fri Jun 10, 2011 11:37 am     Reply with quote

Hi,

I2C is set as slave mode but INT_SSP was never triggered. Slave address is 0x40 and bus frequency is 100KHz. On ACK bit, data line kept high which means PIC (slave) did not respond to the address 0x40. From a screen capture, the address from master is correct. Oscilloscope capture is attached.

CCS compiler is ver 4.120d
Chip is 16f687

Please help. Thanks.

Howard

https://picasaweb.google.com/KongFuWang/I2CCapture?authkey=Gv1sRgCImti7Ovms_8pAE#

Code:

#include <16F687.h>

#fuses NOWDT, BROWNOUT, NOPUT, MCLR,NOCPD,INTRC,IESO,FCMEN
#use delay(clock=4M)
#use i2c(SLAVE, SDA=PIN_B4, SCL=PIN_B6, address=0x40,fast=100000,FORCE_HW)
//#use i2c(MASTER, SDA=PIN_B4, SCL=PIN_B6, address=0x03,fast=10000)
unsigned int32 sys_ms = 0, sys_second = 0;
BYTE address = 0, InBuffer[2], OutBuffer[2];

#INT_SSP
void ssp_interupt (void)
{
   BYTE incoming, state;

   state = i2c_isr_state();
   
   if(state < 0x80)                     //Master is sending data
   {
      incoming = i2c_read();
      if(state == 1 && incoming < 2)                     //First received byte is address
         address = incoming;
      if(state == 2)                     //Second received byte is data
         InBuffer[address] = incoming;
   }
   if(state == 0x80)                     //Master is requesting data
   {
      i2c_write(0xa5);
   }
   address = 0;
   output_toggle(PIN_C3);
}

#INT_TIMER0
void TIMER0_ISR(void)
{
   //output_toggle(PIN_C4);
   sys_ms++;
   sys_second = sys_ms / 1000;
}


void main (void)
{
   unsigned int32 lastSec = 0, sec;

   set_timer0(256);      //1 interrupt every 2ms
   setup_timer_0( T0_INTERNAL | T0_DIV_8);
   I2C_SlaveAddr(0x40); //additional line to make sure address is set as 0x40
   
   enable_interrupts(INT_SSP);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);

   
   while (TRUE)
   {
      delay_ms(10);
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19326

View user's profile Send private message

PostPosted: Fri Jun 10, 2011 3:20 pm     Reply with quote

Several small things wrong:
1) Don't clear the storage address at the end of the ISR. This needs to be held till the next call, or the code won't work.
2) Get rid of the clock rate. Only _master_ devices have a clock rate.
3) Get rid of the second slave address setting. The two I2C setup methods (USE_I2C, and the separate functions), are often incompatible. Use one or the other.
3) Get rid of doing a /1000 in the timer interrupt. This operation, will take over 1mSec to complete (1066uSec at 4MHz). This _will_ cause problems in the future even if it isn't the problem here.

Code:

unsigned int32 sys_second = 0;
int16 sys_ms = 499,  //don't make the counter bigger than it needs to be

#INT_TIMER0
void TIMER0_ISR(void) {
   if (sys_ms) --sys_ms;
   else {
      sys_second++;
      sys_ms=499;
   }
}

For comparison, this takes less than one fiftieth the time to execute.

4) Then the big comment. Your picture does not show address 0x40 being generated. You have the start, then the very first transmitted bit is high. You have address 0x81 (read) being sent.
PIC's treat the address as an eight bit word, including the R/W bit. So a device set to address 0x40, responds to both 0x40, and 0x41. It looks like you have the address coming from a device using the Intel 7bit format, where the 'address' is just the top seven bits of the value, and the R/W bit is not included. To respond to this address, you will have to change the PIC to use address 0x80.

Best Wishes
kongfu1



Joined: 26 Apr 2010
Posts: 56

View user's profile Send private message

PostPosted: Mon Jun 13, 2011 1:33 pm     Reply with quote

Hi Ttelmah,

Thanks for your help. The I2C address is working now after shifting 1 bit out.
One thing still confused me is that "a device using the Intel 7bit format".

My understanding about I2C format shall be followings:

1. Address is 7 bits or 10 bits. We are using 7 bits.
2. R/W bit
3. ACK bit

There are 9 bits or pulses on SCL line total. And this is Intel 7bit format. Based on your explanation is that regardless of 7 bits address or not, there should be 8 pulses (bits) for I2C address, 1 pulse for R/W and 1 for ACK. In this way, SCL line shall have 10 pulses. That is why you read my screen capture as 0x81.

We may also have to use PIC as I2C master. To better understand the difference of I2C data format could be very helpful. Is there any documentation to explain those on web?

Thanks,
Howard
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 13, 2011 1:40 pm     Reply with quote

Quote:

To better understand the difference of I2C data format could be very
helpful. Is there any documentation to explain those on web?

This TotalPhase page will help:
http://www.totalphase.com/support/kb/10039/
However, I wouldn't call 8-bit address format "incorrect" as they do.
It's widely done. It's just a different style. But I agree it can cause
confusion.
Ttelmah



Joined: 11 Mar 2010
Posts: 19326

View user's profile Send private message

PostPosted: Mon Jun 13, 2011 2:44 pm     Reply with quote

Yes, it is just a nomenclature thing.

I2C always sends 'bytes', and the address is a byte with the top seven bits being the 'I2C address', and the bottom bit the direction flag. The PIC always deals with the 'address' in this format pre-justified to 8bits. Most chip manufacturers also now use the format this way, stating the device address(s) as the byte that needs to be sent to select the device, rather than the seven bit
bus address number, which then needs to be left shifted.

It's rather 'historical'. The original I2C spec dealt with the 7bit address, but usage, has tended to move to using the 8bit format.

Best Wishes
kongfu1



Joined: 26 Apr 2010
Posts: 56

View user's profile Send private message

I2C Master can't read
PostPosted: Mon Jun 20, 2011 8:23 pm     Reply with quote

Hi,

Thanks for everyone's help. I2C has no problem as slave now.
But as master of I2C, it is still not working yet.
In attached code, PIC sends a slave address and asking slave to return one byte.
If slave is not connected, PIC will repeat same action and toggle PIN_B7 every 100 ms.
If salve is connected and sends back one byte, PIC will be stopped. (PIN_B7 will be a flat line all the time).

Anyway, PIC is OK to send data to slave as I2C master.

Please help.
Thanks.
Howard
Code:

#include <16F687.h>

#fuses NOWDT, BROWNOUT, NOPUT, MCLR,NOCPD,INTRC,IESO,FCMEN
#use delay(clock=4M)
//#use i2c(SLAVE, SDA=PIN_B4, SCL=PIN_B6, address=0x80,FORCE_HW)
#use i2c(MASTER, SDA=PIN_B4, SCL=PIN_B6, address=0x2f,fast=100000)  //,SMBUS)  //,FORCE_HW)

void main (void)
{
   output_high(PIN_C4); // to turn pwr on for testing board
   output_low(PIN_C1);  // to turn pwr on for testing board
   output_high(PIN_C3); // to turn pwr on for testing board

   while (TRUE)
   {
      //hello for ack
      i2c_start();
      i2c_write(0x20);
      i2c_stop();

      //read
      i2c_start();
      i2c_write(0x21);
      i2c_read(1);
      i2c_stop();     // Stop condition
     
       
      delay_ms(100);
      output_toggle(PIN_B7);
   }
}
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