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;
}
}
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.
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 & IICS_SRW_MASK)
{
IICC1 = IICC_REG_TX;
if ((IICS & 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 & IICC_TX_MASK)
{
if ((IICS & 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;
}
}