MC9S08SF4 i2c slave not responding to repeated start

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MC9S08SF4 i2c slave not responding to repeated start

564 Views
cws
Contributor I

With the 9S08SF4 as a slave I expected to get an interrupt after the repeated start address byte is received.  Is there somethign I'm missing or setup wrong? 

 

Please see the attached image of a capture from a logic analyzer.  The Debug line toggles a couple of times when the interrupt routine begins and the stays high if IICS_IAAS is true (and goes low if it's false.

 

Here's my setup code:

   /* ### Init_IIC init code */
   /* IICC2: GCAEN=0,ADEXT=0,AD10=0,AD9=0,AD8=0 */
   IICC2 = 0x00U;                         

   /* IICA: AD7=0,AD6=1,AD5=0,AD4=0,AD3=1,AD2=1,AD1=1 */
   //slave address 0x27 shifted up one bit;
   IICA = 0x27 << 1;                                     

   //40Khz baud, 20MHz bus clk --> mul*SCLdivider = 500 so mul of 2 and ICR of 0x23 (SCLdivisor=256) 
   /* IICF: MULT1=0,MULT0=1,ICR5=1,ICR4=0,ICR3=0,ICR2=0,ICR1=1,ICR0=1 */
   IICF = 0x63U;                                     

   /* IICS: TCF=1,IAAS=0,BUSY=0,ARBL=1,SRW=0,IICIF=1,RXAK=0 */
   IICS = 0x92U;                        /* Clear the interrupt flags */

   /* IICC1: IICEN=1 */
   IICC1 |= (unsigned char)0x80U;                     

   /* IICC1: IICEN=1,IICIE=1,MST=0,TX=0,TXAK=0,RSTA=0 */
   IICC1 = 0xC0U; 

 

And my interrupt code:

__interrupt void IsrI2c(void)
{
   uint8_t i2cDummyRead;

   //Clear interrupt flag
   IICS = IICS_IICIF_MASK;

   PTBD &= ~0x01;   
   PTBD |= 0x01;
   PTBD &= ~0x01;   
   PTBD |= 0x01;
   PTBD &= ~0x01;   

   //Lost Arbitration?
   if (IICS & IICS_ARBL_MASK)
   {
      IICS |= IICS_ARBL_MASK;
      //not Addressed as slave?
      if (!(IICS & IICS_IAAS))
      {
         return;
      }
   }
   else //Arbitration not lost
   {
      //not Addressed as slave?
      if ((IICS & IICS_IAAS_MASK) == 0)
      {
         //if Slave TX
         if (IICS & IICS_SRW_MASK)
         {
            IICC1 = IICC_REG_TX;
            if ((IICS & IICS_RXAK_MASK) == 0) //0=ACK, 1=No Ack
            {
               IICC1 = IICC_REG_TX;
               if (mTxCount < MAX_TX_COUNT)
               {
                  IICD = mI2cTxBuf[mTxCount];
                  mTxCount++;

                  mTxRequestedHasBeenSent = TRUE;
               }
               else
               {
                  //send default
                  IICD = 0xFF;
               }
            }
            else
            {
               //no ACK, switch to RX mode
               IICC1 = IICC_REG_RX;
               //dummy read
               i2cDummyRead = IICD;            
            }
         }
         else //Slave RX
         {
            IICC1 = IICC_REG_RX;
            mI2cRxBuf[mRxCount] = IICD;
            mRxCount++;
            if (mRxCount >= MAX_RX_COUNT)
            {
               mRxCount = 0;
            }
         }
         return;
      }
   }


   PTBD |= 0x01;

   //we are addressed as a slave
   //check direction of transfer
   if (IICS & IICS_SRW_MASK)
   {
      //Master requesting us to TX
      IICC1 = IICC_REG_TX;
      IICD = mI2cTxBuf[0];
      mTxCount = 1;
      mTxRequestedHasBeenSent = TRUE;
   }
   else  //Master requesting us to RX
   {
      IICC1 = IICC_REG_RX;
      //reset received byte counter to 0
      mRxCount = 0;
      //dummy read
      i2cDummyRead = IICD;
   }
}

Labels (1)
0 Kudos
2 Replies

277 Views
kef
Specialist I

How are  IICC_REG_TX and  IICC_REG_RX defined?

 

SRW bit is valid only when you are just addressed as a slave. SRW is not valid at other times, it is just LSB of data register or something. The only moment slave is allowed to change data direction from read to transfer (flip bit in control register) is when slave is just addressed as slave and SRW bit tells that master wants to read data. On all other slave interrupts you shoud inspect TX/RX bit control register to determine if you are reading or replying master. Something is not right in your code, I think.

0 Kudos

277 Views
cws
Contributor I

Thanks for the reply Kef and sorry, I forgot to incluse these defines:

 

#define IICC_REG_DEFAULT 0xC0

#define IICC_REG_RX IICC_REG_DEFAULT

#define IICC_REG_TX (IICC_REG_DEFAULT | IICC_TX_MASK)

 

I was trying:

 

  if (IICS &amp; IICS_SRW_MASK)

  {

    IICC1 = IICC_REG_TX;

    if ((IICS &amp; IICS_RXAK_MASK) == 0) //0=ACK, 1=No Ack

    {

 

to see if it might correct the problem, my orignal code was (which still had the same problem):

if (IICC1 &amp; IICC_TX_MASK)

  {

    if ((IICS &amp; IICS_RXAK_MASK) == 0) //0=ACK, 1=No Ack

    {

 

I've removed the extra assignments of the IICC1 register and I'm seeing the same non-response to a repeated start. Here's the newest ISR:

__interrupt void IsrI2c(void)
{
   uint8_t i2cDummyRead;

   //Clear interrupt flag
   IICS = IICS_IICIF_MASK;

   PTBD &= ~0x01;   
   PTBD |= 0x01;
   PTBD &= ~0x01;   
   PTBD |= 0x01;
   PTBD &= ~0x01;   

   //Lost Arbitration?
   if (IICS & IICS_ARBL_MASK)
   {
      IICS |= IICS_ARBL_MASK;
      //not Addressed as slave?
      if (!(IICS & IICS_IAAS))
      {
         return;
      }
   }
   else //Arbitration not lost
   {
      //not Addressed as slave?
      if ((IICS & IICS_IAAS_MASK) == 0)
      {
         //if Slave TX
         if (IICC1 & IICC_TX_MASK)
         {
            if ((IICS & IICS_RXAK_MASK) == 0) //0=ACK, 1=No Ack
            {
               if (mTxCount < MAX_TX_COUNT)
               {
                  IICD = mI2cTxBuf[mTxCount];
                  mTxCount++;

                  mTxRequestedHasBeenSent = TRUE;
               }
               else
               {
                  //send default
                  IICD = 0xFF;
               }
            }
            else
            {
               //no ACK, switch to RX mode
               IICC1 = IICC_REG_RX;
               //dummy read
               i2cDummyRead = IICD;            
            }
         }
         else //Slave RX
         {
            mI2cRxBuf[mRxCount] = IICD;
            mRxCount++;
            if (mRxCount >= MAX_RX_COUNT)
            {
               mRxCount = 0;
            }
         }
         return;
      }
   }
   PTBD |= 0x01;

   //we are addressed as a slave
   //check direction of transfer
   if (IICS & IICS_SRW_MASK)
   {
      //Master requesting us to TX
      IICC1 = IICC_REG_TX;
      IICD = mI2cTxBuf[0];
      mTxCount = 1;
      mTxRequestedHasBeenSent = TRUE;
   }
   else  //Master requesting us to RX
   {
      IICC1 = IICC_REG_RX;
      //reset received byte counter to 0
      mRxCount = 0;
      //dummy read
      i2cDummyRead = IICD;
   }
}

0 Kudos