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 Slave not getting Interrupt

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



Joined: 28 Sep 2016
Posts: 3

View user's profile Send private message

I2C Slave not getting Interrupt
PostPosted: Wed Oct 05, 2016 10:41 am     Reply with quote

I'm using a 18F67J94 and trying to connect it to an ARM using I2C. The ARM is the master device and the PIC is the slave. Both are running at 3.3 V and the PIC has 4.7 K pull-up resistors. In addition the ARM has other I2C devices that it is able to communicate with. There is also an EEPROM on the same lines as the PIC and the ARM can communicate with it, so we believe the hardware is correct. I have also used a scope to look at the SDA and SCL lines and everything looks correct except for the fact that the PIC does not ACK the Address.

The problem that I'm running is that on the PIC I'm not getting to the ISR for some reason. I have put both a counter, and I drive an LED to indicate that I enter the ISR. In addition using a debugger I place a breakpoint at the first instruction. Then when I send a command from the ARM (using address 0x33) to the PIC, the LED never turns on and I don't hit my breakpoint. Once I manually pause, the ISR count is still 0. After pausing and looking at the PIC registers they have the following settings:
Code:

SSP1ADD = 0x66
SSP1BUFF = 0x66
SSP1STAT = 0x11   (BF and P are 1)
SSP1CON1 = 0x36
SSP1CON2 = 0x41  (ACKSTAT is 1)
SSP1CON3 = 0x0
SSP1MSK = 0xFF
TRISC = 0xFC (C3 and C4 are high)
PIR1 = 0x10
PIE1 = 0x28 (SSP1IE is 1)
INTCON = 0xE6 (PEIE_GIEL and GIE_GIEH are 1)

Here's my code (For simplicity not including code to process the I2c data):
Code:

#fuses NOIESO, CKSNOFSM, NOCLOCKOUT, WDT_SW, WDT256, NOPROTECT, BROWNOUT_SW, BORV20

#use_delay (clock=64MHz, crystal=24MHz, USB_FULL)

#pin_select U1TX=PIN_C6
#pin_select U1RX=PIN_C7
#pin_select U2TX=PIN_G0
#pin_select U2RX=PIN_G1
#pin_select U3TX=PIN_E0
#pin_select U3RX=PIN_E1
#pin_select U4TX=PIN_E3
#pin_select U4RX=PIN_E4

#use rs232(stream=SP1, bits=8, parity=N, baud=19200, errors UART1)
#use rs232(stream=SP2, bits=8, parity=N, baud=19200, errors, UART2)
#use rs232(stream=SP3, bits=8, parity=N, baud=19200, errors, UART3)
#use rs232(stream=SP4, bits=8, parity=N, baud=19200, errors, UART4)

//#use i2c(SLAVE, sda=PIN_C4, scl=PIN_C3, address=0x66, stream=I2CS)
//#use i2c(SLAVE, I2C1, address=0x66, stream=I2CS, FORCE_HW, NO_STRETCH, SLOW)
//#use i2c(SLAVE, I2C1, address=0x66, stream=I2CS)
#use i2c(SLAVE, sda=PIN_C4, scl=PIN_C3, address=0x66, stream=I2CS)

#INT_RDA
void intRdaIsr() { rsBuffer1[rsBufferNextIn1] = getc(SP1); }

#INT_RDA2
void intRda2Isr() { rsBuffer2[rsBufferNextIn2] = getc(SP2); }

#INT_RDA3
void intRda3Isr() { rsBuffer3[rsBufferNextIn3] = getc(SP3); }

#INT_RDA4
void intRda4Isr() { rsBuffer4[rsBufferNextIn4] = getc(SP4); }

#INT_SSP // interrupt on i2c
void i2c_isr(void) {
  uint8_t state, address;

  state = i2c_isr_state(I2CS); // Breakpoint here

  nIsrI2cCount++;
  outputHigh(PIN_X);

  if (state = 0x0)  {
    // master has sent a write request
    address = i2c_read(I2CS);
  }
  else if ((state > 0x0) && (state < 0x80)) {
    i2cRxBuffer[i2cBufferNextIn++] = i2c_read(I2CS);
  }
  else if (state == 0x80) {
    // Master sent a read request
    address = i2c_read(I2CS);

    i2c_write(I2CS, 0);
  }
  else  {
    i2c_write(I2CS, 0);
  }
}

void initInterrupts() {
  clear_interrupt(INT_RDA);
  clear_interrupt(INT_RDA2);
  clear_interrupt(INT_RDA3);
  clear_interrupt(INT_RDA4);
  clear_interrupt(INT_SSP);

  enable_interrupts(INT_RDA);
  enable_interrupts(INT_RDA2);
  enable_interrupts(INT_RDA3);
  enable_interrupts(INT_RDA4);
  enable_interrupts(INT_SSP);
  enable_interrupts(GLOBAL);

void main (void) {
  setup_wdt(WDT_OFF)

  initInterrupts();

  while(TRUE) {
    restart_wdt();
  }
}

If anyone has any ideas with what I'm missing, I would greatly appreciate it. Thanks.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Oct 05, 2016 5:10 pm     Reply with quote

The first thing I would do is strip your program way down, and make a
pure small slave. Use the CCS example program Ex_slave.c and modify
it as required for your PIC.

Then use a 2nd PIC as the master and test that it can detect the slave PIC
by running this i2c scanner program:
http://www.ccsinfo.com/forum/viewtopic.php?t=49713
Modify the #include, #fuses, etc., for your master PIC's development
board.

If that works, maybe try to make the program work on your ARM board.
See if the ARM board can detect the slave.

Quote:
Both are running at 3.3 V and the PIC has 4.7 K pull-up resistors
You are running several i2c slaves on the same bus. Your 4.7K pull-ups
are a little light for this. The capacitance is the issue. I'd use 1 ma
pull-ups at a minimum. That would be 3.3K pull-ups. And maybe use
stiffer ones than that, such as 2.2K.

Arrow What's your CCS compiler version ?

Also, this is typed in code below, because there should be no underscore
between #use and delay(). This line will generate a compiler error:
Quote:
#use_delay (clock=64MHz, crystal=24MHz, USB_FULL)


Also, the code below will fail to work as expected. You are setting 'state'
to 0x0 in the top line:
Quote:
if (state = 0x0) {
// master has sent a write request
address = i2c_read(I2CS);
}

I suppose you want to test 'state' and see if it's 0x00. But this is not the
way that the CCS example file Ex_slave.c does it. You should be largely
copying Ex_slave.c if you want your program to work.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Thu Oct 06, 2016 1:22 am     Reply with quote

Some other comments.

4K7, is rather large for the pull-ups on a 3.3v I2C bus.

'But other things work' I hear you say. The PIC uses the correct 'I2C' specified bus levels. The ARM and quite a lot of other devices don't (they use standard CMOS thresholds). This makes the PIC more strict about getting the pullups good. You can change the PIC bus levels by using:

#use i2c(SLAVE, I2C1, address=0x66, SMBUS, stream=I2CS)

Are you sure about your address?.

The ARM, uses Texas style 7bit addresses.

If the ARM is trying to talk to address 0x66, the PIC will need to be set to use address 0xAA. The PIC requires the address shifted into the top 7bits.

Your first big problem is the last one that PCM_Programmer has pointed out. This will be stopping anything from happening right....
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