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 again and again and again and ...
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PICoHolic



Joined: 04 Jan 2005
Posts: 224

View user's profile Send private message

I2C slave again and again and again and ...
PostPosted: Mon Apr 07, 2008 1:49 pm     Reply with quote

Hi to all,
This time it's a PIC18F2431 (slave). The interrupt is not working and the master is NOT stalling at all (writing and reading)

Master code: (working for sure, captured on scope)
Code:

//test
   i2c_start();
   i2c_write(0xE0);  //slave address
   i2c_write(0x00);
   i2c_write(0xAA);
   i2c_write(0x55);
   i2c_write(0xA5);
   i2c_write(0x5A);
   i2c_stop();
   
   delay_ms(100);
   
   i2c_start();
   i2c_write(0xE0);  //slave address
   i2c_write(0x00);
   i2c_start();
   i2c_write(0xE1);  //read
   dummy1 = i2c_read();
   dummy2 = i2c_read();
   dummy3 = i2c_read();
   dummy3 = i2c_read();
   i2c_stop();



slave code:
Code:

#include <18F2431.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC                 //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code NOT protected from reads
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NOBROWNOUT               //NO Reset when brownout detected
#FUSES BORV27                   //Brownout reset at 2.7V
#FUSES PUT                      //Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES NOSTVREN                 //Stack full/underflow will not cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled
#FUSES NOWINEN                  //WDT Timer Window Disabled
#FUSES T1LOWPOWER               //Timer1 low power operation when in sleep
#FUSES HPOL_HIGH                //High-Side Transistors Polarity is Active-High (PWM 1,3,5 and 7)
   //PWM module high side output pins have active high output polarity
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES LPOL_HIGH                //Low-Side Transistors Polarity is Active-High (PWM 0,2,4 and 6)
   //PWM module low side output pins have active high output polar
#FUSES PWMPIN                   //PWM outputs disabled upon Reset
#FUSES MCLR                     //Master Clear pin enabled

#use delay(clock=8000000)
#use rs232(baud=38400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, BRGH1OK)
#use i2c(Slave,Slow,sda=PIN_C4,scl=PIN_C3,address=0xE0, FORCE_HW)
#use spi(Master, MSB_FIRST, DI=PIN_A2, DO=PIN_A3, CLK=PIN_A4, BITS=8, BAUD = 100000, MODE=0)

#byte PORTA = 0xF80
#byte PORTB = 0xF81
#byte PORTC = 0xF82
#byte TRISB =0xF83
#byte TRISC =0xF84
#byte SSPADD = 0xFC8

#byte SSPCON   =  0xFC6
#byte SSPSTAT  =  0xFC7
#bit  SSPOV    =  SSPCON.6
#bit  DA       =  SSPSTAT.5
#bit  P        =  SSPSTAT.4
#bit  S        =  SSPSTAT.3
#bit  RW       =  SSPSTAT.2
#bit  BF       =  SSPSTAT.0
#bit  CKP      =  SSPCON.4

#define SSPSTATMASK  0B00101101
///////////////////////////////////////////////////////////////////////////////
BYTE Page[256] = {0x01, 0x02, 0x03, 0x04};
BYTE InternalAddressCounter = 0;
int1 InternalAddress = TRUE;
///////////////////////////////////////////////////////////////////////////////
#int_SSP
void SSP_isr(void)
{
   BYTE incoming, state;
   
   state = SSPSTAT & SSPSTATMASK;
   
   RX_LOS_SFP = 0;   //LED indicator
   
   switch (state)
   {
   case 0B00001001:  // i2c write operation, last byte was address
      incoming = i2c_read(); // dummy read!
      InternalAddress = TRUE;
   break;
   
   case 0B00101001:  // i2c write operation, last byte was data
      incoming = i2c_read();  // data read
      if (InternalAddress)
      {
         InternalAddressCounter = incoming;
         InternalAddress = FALSE;
      }
      else
         Page[InternalAddressCounter++] = incoming;
   break;
   
   case 0B00001100:  // i2c read operation, last byte was address     
      i2c_write(Page[InternalAddressCounter++]);  // data write
   break;
   
   case 0B00101100:  // i2c read operation, last byte was data
      i2c_write(Page[InternalAddressCounter++]);  // data write
   break;
   
   case 0B00101000:  // slave i2c logic reset by NACK from master
     
   break;
   
   default:
   
   break;
   }

   SSPOV = 0;  // process errata
}
///////////////////////////////////////////////////////////////////////////////

#bit  CDR_SHDN    =  PORTC.1
#bit  OSC_SHDN    =  PORTC.2
#bit  RX_CDR_LOS  =  PORTB.2
#bit  LOLN        =  PORTB.3
#bit  RX_LOS_SFP  =  PORTA.1
#bit  TX_FAULT_SFP=  PORTA.0

////////////////////////////////////////////////////////////////////////////////
void main()
{
   int8 Length;
   
   setup_oscillator(OSC_8MHZ|OSC_TIMER1);
   PORTA = 0x80;
   set_tris_a(0x04);
   PORTB = 0x00;
   set_tris_b(0xFF);
   PORTC = 0x00;
   set_tris_c(0xB8);
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0|ADC_WHEN_INT0|ADC_INT_EVERY_OTHER);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_INTERNAL);
   setup_timer_2(T2_DISABLED,0,1);
   //enable_interrupts(INT_RDA);
   enable_interrupts(INT_SSP);
   SSPCON |= 0x0E;
   SSPOV = 0;
   BF = 0;
   clear_interrupt(INT_SSP);
   enable_interrupts(GLOBAL);

       
   RX_LOS_SFP = 1;
   TX_FAULT_SFP = 1;
   
   while(1);
}



Once the interrupt occurs the LED should turn off:
Code:

RX_LOS_SFP = 0;   //LED indicator


But it's always on, no interrupt!!
Any thoughts? Shocked
10x
Matro
Guest







PostPosted: Mon Apr 07, 2008 2:36 pm     Reply with quote

Use output_low() and output_high() instead of assigning directly the register to change output levels.

We already wrote in a previous post that the last read of a master shall return a NACK :
i2c_read(0);

Last thing is that you have to ensure that the tris of port C is not changes during I²C operations, i.e. that no pin level is changed since you don't use fast_io or fixed_io.

Matro
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Apr 07, 2008 2:38 pm     Reply with quote

I didn't look at your whole program, but I noticed this immediately:
Quote:

i2c_start();
i2c_write(0xE0); //slave address
i2c_write(0x00);
i2c_start();
i2c_write(0xE1); //read
dummy1 = i2c_read();
dummy2 = i2c_read();
dummy3 = i2c_read();
dummy3 = i2c_read();
i2c_stop();

The last i2c_read operation in the Master must do a NACK. In CCS this
is done by giving it the 0x00 parameter as shown in bold below:
Quote:
dummy3 = i2c_read(0);
PICoHolic



Joined: 04 Jan 2005
Posts: 224

View user's profile Send private message

PostPosted: Tue Apr 08, 2008 12:52 am     Reply with quote

You're right PCM programmer, but it has nothing to do with issuing an interrupt on the slave side since the master has written first (no interrupt occured)

Matro, i've always used the direct pin assignment and it works perfect. I'll double check the TRISC issue.

One thing to mention is SDA & SCL on PIC18LF2431 can also be configued as INT1 & INT2 Confused
Could it be that the micro is looking at those pins as INT1 & INT2 instead of SDA & SCL!?!? (That's why no interrupt is occuring on SSP). PIC18LF2431 is one of the micros that has no silicon errata regarding SSP!

Note: compiler version: 4.066

Thank you,
Matro
Guest







PostPosted: Tue Apr 08, 2008 2:44 am     Reply with quote

Could you try with the following lines removed from your code :
Code:

   PORTA = 0x80;
   set_tris_a(0x04);
   PORTB = 0x00;
   set_tris_b(0xFF);
   PORTC = 0x00;
   set_tris_c(0xB8);

Have this test and tell us about results.

Matro.
PICoHolic



Joined: 04 Jan 2005
Posts: 224

View user's profile Send private message

PostPosted: Tue Apr 08, 2008 3:46 am     Reply with quote

Matro,
i cannot remove these lines but i re-initialized i2c instead, right after

Code:

...
// Call
InitI2CSlave();
...
// Implementation
void InitI2CSlave(void)
{
   set_tris_c(0xB8);
   SSPSTAT = 0x00;
   SSPADD  = 0xE0;
   SSPCON  = 0x36;
}


The interrupt works only one time and BF stays 1 Confused
I even tried the SSP_ISR provided by CCS, same problem Rolling Eyes

Thanks
Matro
Guest







PostPosted: Tue Apr 08, 2008 4:19 am     Reply with quote

PICoHolic wrote:
Matro,
i cannot remove these lines but i re-initialized i2c instead, right after

Code:

...
// Call
InitI2CSlave();
...
// Implementation
void InitI2CSlave(void)
{
   set_tris_c(0xB8);
   SSPSTAT = 0x00;
   SSPADD  = 0xE0;
   SSPCON  = 0x36;
}


The interrupt works only one time and BF stays 1 Confused
I even tried the SSP_ISR provided by CCS, same problem Rolling Eyes

Thanks

Just remove these lines for a test purpose. I don't think it's really a problem.
Remove (comment) all lines that are setting/changing tris or port and have a test without these lines.
It's just to have information. ;-)

Matro.
PICoHolic



Joined: 04 Jan 2005
Posts: 224

View user's profile Send private message

PostPosted: Tue Apr 08, 2008 5:11 am     Reply with quote

OK, Done Smile

The interrupt is still not occuring :(

Using the
Code:
InitI2CSlave();
it was better.

Thanks
Matro
Guest







PostPosted: Tue Apr 08, 2008 5:39 am     Reply with quote

You can remove the InitI2CSlave() too.
All you are doing in this function is already done because of the #use i2c directive.

Really try without any line modifying any tris or port, and if possible modify your isr to use the i2c_isr_state instead of your SSPSTATMASK.

It should be a good starting point to debug.
Try with this simple isr:
Code:

#INT_SSP
void i2c_isr()
{
   unsigned int8 state;
   state = i2c_isr_state();
  if(state >= 0x80)
  {
     i2c_write(state);
     //you can add here a serial trace or a LED toggle (not on port C)
  }
  else
  {
    state = i2c_read();
    //you can add here a serial trace or a LED toggle (not on port C)
   }
}

AND do not set or change tris in your code. Ensure too that no tris or port change could appear during the main endless loop (your code doesn't need to stay as it later but that is for test purpose).

Tell me about the result.
Matro.
PICoHolic



Joined: 04 Jan 2005
Posts: 224

View user's profile Send private message

PostPosted: Tue Apr 08, 2008 6:20 am     Reply with quote

Thanks Matro,

I have tried it. i swear Smile
Same problem Rolling Eyes No interrupt!

10x
Matro
Guest







PostPosted: Tue Apr 08, 2008 6:31 am     Reply with quote

No interrupt at all, or 1 interrupt and after no more?
or some interrupts and after no more?

Could you try it?
- add in the initialization of your slave main()
Code:

dummy = i2c_read(); //dummy can be any byte variable
SSPOV = 0;

- compile and program your slave
- reset the master and keep it in reset
- reset the slave and let it run some seconds
- only now release the master reset and let it run.

What are the results of this test?

Matro.
PICoHolic



Joined: 04 Jan 2005
Posts: 224

View user's profile Send private message

PostPosted: Tue Apr 08, 2008 7:22 am     Reply with quote

here's my new isr:
Code:

#INT_SSP
void SSP_isr(void)
{
   BYTE incoming, state;
   
   state = SSPSTAT & SSPSTATMASK;
   
   RX_LOS_SFP = 0;   //LED indicator
   
 
   // test
   if (BF)
      incoming = i2c_read();
   
   SSPOV = 0;
   BF = 0;
   RX_LOS_SFP = 1;   //LED indicator
}


RX_LOS_SFP (monitored on scope) stays off given that it was ON initially. that means that the interrupt is occuring only once!

The micro is stalling on [incoming = i2c_read();] even if BF is H

Thanks
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Tue Apr 08, 2008 8:17 am     Reply with quote

Quote:
#use spi(Master, MSB_FIRST, DI=PIN_A2, DO=PIN_A3, CLK=PIN_A4, BITS=8, BAUD = 100000, MODE=0)

I'm not sure if this might be your problem but you might not be able to have both I2C & SPI declared. Try commenting out the above line and see if that will enable your I2C routine.

Ronald
PICoHolic



Joined: 04 Jan 2005
Posts: 224

View user's profile Send private message

PostPosted: Tue Apr 08, 2008 8:24 am     Reply with quote

This is software SPI. It has nothing to do with hardware I2C
Matro
Guest







PostPosted: Tue Apr 08, 2008 8:38 am     Reply with quote

What is the #use i2c used for the master?
If "force_hw" is present at master level, it can lock the system so you can try to remove it if present.
But I don't think it can be the problem root here.
In your isr try to replace
Code:

incoming = i2c_read();

by
Code:

#ASM
MOVF SSPBUF,W
#ENDASM

Of SSPBUF shall be declared with a #BYTE but I let you do that by yourself.

Did you already try to test your program with several chips or is it always the same?

Matro
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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