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 misses data

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



Joined: 01 Jun 2004
Posts: 39
Location: Trois-Rivières

View user's profile Send private message

i2c : slave misses data
PostPosted: Thu Sep 30, 2004 4:03 pm     Reply with quote

Hi,

I'm working on a pic to pic i2c communication link.

Master : PIC18F452 (running at 40MHz)
Slave : PIC18F452 (running at 10MHz)

The master executes a comm. routine which sends many bytes to the slave.

The slaves reads the bytes in an interruption routine.

I found out that if I let the master running top speed, the slave doesn't even see the i2c events (doesn't enter in the interruption service routine). If I send the i2c events (start, adress, data1, data2, etc.) one at a time using the ICD2 debugger with breakpoints, it works perfectly (the slave enters in the int. routine and receives valid data).

Any idea about what can cause this?

Could it be some hardware issue, as the value of the pull-up resistor (anyway what could be a good value?)?

Thanks in advance for your advices...
_________________
Alex
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Sep 30, 2004 5:36 pm     Reply with quote

Depending on the I2C bus speed, if you are using the standard interrupt handler you may have too much latency because of the context switching. If this is the problem then investigate using high priority interrupts and assembler with a RETFIE 1
alexbilo



Joined: 01 Jun 2004
Posts: 39
Location: Trois-Rivières

View user's profile Send private message

PostPosted: Fri Oct 01, 2004 9:19 am     Reply with quote

Hi,

Quote:
If this is the problem then investigate using high priority interrupts and assembler with a RETFIE 1


I tried the fast interrupts to be sure, because it's possible that the lenghty ISR I use become a problem. However, even if the ISR takes too long to execute, it should at least enter in it when it first receives the adress. This isn't happening, as if the hardware doesn't even get triggered by the i2c events.

Here's the flow of events :

Start condition (no interrupt generated)
Adress sent, write mode (interrupt should be generated)
Data1 sent (another interrupt)
Data 2 sent, etc.

If, in the master, I executes these commands one at a time (breakpoint between) each, the slave reacts properly. If a set a breakpoint only before data2 is sent, per example, nothing happens in the slave (doesn't even enter in the ISR).

Thanks again,
_________________
Alex
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Fri Oct 01, 2004 11:10 am     Reply with quote

You would probably get more help if you posted a small test program that demonstrates the problem. Remember to use the code button!
alexbilo



Joined: 01 Jun 2004
Posts: 39
Location: Trois-Rivières

View user's profile Send private message

PostPosted: Fri Oct 01, 2004 11:52 am     Reply with quote

Since the code is a little bit complicated, I choosed to explain it in words instead... But since you ask for it Wink

Note that I use my own functions, not the CCS' functions.

Master code :

Code:

   i2c_start();
   ack=i2c_send(WRITE);
   ack+=i2c_send(data=make8(tension,1));
   temp^=data;
   ack+=i2c_send(data=make8(tension,0));
   temp^=data;
   ack+=i2c_send(data=make8(courant,1));
   temp^=data;
   ack+=i2c_send(data=make8(courant,0));
   temp^=data;
   ack+=i2c_send(data=make8(temperature,1));
   temp^=data;
   ack+=i2c_send(data=make8(temperature,0));
   temp^=data;
   ack+=i2c_send(data=control_status);
   temp^=data;
   ack+=i2c_send(temp);
   // Réception des informations
   i2c_repstart();
   ack=i2c_send(READ);
   // Lire l'indicateur de transmission
   temp=i2c_recv(0);
   .
   .
   .


Slave ISR :

Code:

/* ssp_isr()
      Événement du module i2c
      Arguments : aucun
      Valeur retournée : aucune
*/
#INT_SSP FAST
void ssp_isr(void) {

   static int index;
   int temp, i, buffer[20];
   int W_save, STATUS_save, FSR0L_save, FSR0H_save;
   int scratch_save[5];

   // Sauvegarder l'état des registres
   W_save=WREG;
   STATUS_save=STATUS;
   FSR0L_save=FSR0L;
   FSR0H_save=FSR0H;
   scratch_save[0]=*0x1;
   scratch_save[1]=*0x3;
   no_step++;
   
   // Le contrôleur envoie des données
   if(!RW) {
      // Réception de l'adresse et remise à zéro des variables
      if(!DA) {
         temp=i2c_recv();
         last=temp;
         index=0;
         //no_step=0;
         if(!com_status) com_status=SYNCH;
      }
      // Réception des données du contrôleur
      else {
         // Lire la donnée
         if(index<NB_DATA) {
            buffer[index]=i2c_recv();
            last=buffer[index];
         }
         // Incrémenter l'index
         index++;
         //no_step++;  // POUR DÉBOGAGE
         // Fin de la réception
         if(index==NB_DATA) {
            // Calcul du checksum
            temp=0;
            for(i=0;i<(NB_DATA-1);i++) {
               temp^=buffer[i];
            }
            // Si CRC valide, enregistrer les données
            if(temp==buffer[(NB_DATA-1)]) {
               com_status=OK;
               tension_brute=make16(buffer[0], buffer[1]);
               courant_brut=make16(buffer[2], buffer[3]);
               temperature_brute=make16(buffer[4], buffer[5]);
               control_status=buffer[6];
               fin_com=1;
            }
            // Sinon erreur de communication
            else com_status=NOCOM;
         }
      }
   }
   // Envoi des données au contrôleur
   else if(RW) {
      // Si nouvelles données et aucun verrou
      if(!verrou_trans && nouv_trans) {
         // Envoi du caractère de confirmation de transmission
         i2c_send('D');
         // Envoi des informations
         i2c_send(consigne_msb);
         i2c_send(consigne_lsb);
         i2c_send(courant_max_msb);
         i2c_send(courant_max_lsb);
         i2c_send(temp_max_msb);
         i2c_send(temp_max_lsb);
         i2c_send(tension_max_msb);
         i2c_send(tension_max_lsb);
         i2c_send(mode);
         i2c_send(commande);
      }
      // Sinon
      else {
         // Envoi du caractère d'inhibition de transmission
         i2c_send('N');
         DEL_verte();
      }
      // Fin de transmission
      i2c_send('\n');
      DEL_off();
   }

   // Restaurer l'état des registres
   *0x3=scratch_save[1];
   *0x1=scratch_save[0];
   FSR0H=FSR0H_save;
   FSR0L=FSR0L_save;
   STATUS=STATUS_save;
   WREG=W_save;
}


In fact, all this works when I execute the master code step by step, but doesn't work if I let it run at full speed (40MHz xtal for the master and 10MHz xtal for the slave).

Let me know if you want more details...

Thanks,
_________________
Alex
alexbilo



Joined: 01 Jun 2004
Posts: 39
Location: Trois-Rivières

View user's profile Send private message

PostPosted: Fri Oct 01, 2004 12:43 pm     Reply with quote

Hi,

I got it to work by adding delays between each i2c commands. Seems that the slave's ISR wasn't fast enough finaly.

Thanks to all...
_________________
Alex
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Fri Oct 01, 2004 5:56 pm     Reply with quote

Remember that the SCL line should be held low, by the Slave, indicating that it's not done doing it's thing. The Master will monitor this line to know when it can start sending clock pulses again. Try setting the CKP bit (this might be in the SSPCON register) low before each piece of data to be sent and then setting it high, when you're done sending that data, to allow the Master to continue. I'm not sure if the built in functions "i2c_send()" does this or not. If it will work the communications should be faster than waiting for all of the delays.

Ronald
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