Hello,
I work with processor msp430f5438A.
And with IDE CCS 5.3.
My question is regarding the operation of the I2C.
The processor is the master and the slave is serial ADC (ADS).
The master read the from one of the serial ADC (ADS).
The data length is 16 bit. Therefore after the address is set the
Processor reading 16 bit ( of data ) .
But the problem was that I pay attention that In the first transaction ONLY that I read from the ADS I get 3 bytes ( instead of 2) .
Like in the next picture. Last byte (0xFF) should not be appear.
I understand that the problem is that :
when the processor send the START (start the transaction) , it send the address and (aotumaticaly Without an explicit request) bring the first byte from the ADS. And due to the fact that the processor has to read 2 more bytes, the total
data from the ADS is 3 ( insted of 2) .
as I say, this problem apear just in the first transaction,
in all the other transction the problem disapear.
I have aguss than due to the fact that the last byte is not been read, therefore the flag (UCRXIFG) is still set , and that is the reason the in the secong transation
the processor read just 2 bytes.
I try to solve the problem by setting UCB1IFG |= UCRXIFG before I read the data ( see below, (in the code) in function I2cRdMng () in the 3 code line, i mark the line ) , and that solve the problem.
Like in the second picture.
This is the normal reading that I expected for.
the code that I use is bellow.
In main I config the i2c with
I2cCnfg();
I2C_ADDRESS(0x48);
And then call the function:
I2cRdMng(2, buf);// the number of reading is 2 ( bytes).
My question is
- Is it obligate that after sending the address , the first data will be read/requsted ?
- In case that I want to assure always that my initial conditions will start from clean , how I do it? If I clear the UCRXIFG flag before I start reading , or after I end to read all my data , it not work (I don’t get data , something stuck ) I see just the read address with out any afterwards data.
thanks.
--- code
#define I2C_ADDRESS(address) (UCB1I2CSA = (unsigned char)(address))
void I2cCnfg (void)
{
UCB1CTL1 |= UCSWRST;// Enable SW reset
UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C, Master, synchronous mode
UCB1CTL1 = UCSSEL__SMCLK + UCSWRST;// Use SMCLK, keep SW reset
UCB1BR0 = 160; // fSCL = SMCLK/160 = ~100kHz
UCB1BR1 = 0;
UCB1CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
// UCB1IE |= UCRXIE; // Enable RX interrupt
}
Uint16 I2cRdMng (Uint16 numRd, unsigned char * I2cRdbuf)
{
Uint16 rslt;
// UCB1IFG &= ~UCRXIFG;
// UCB1IFG |= UCRXIFG;// <<<< HERE IN THE CODE i set the flag in order to solve the problem of extra reading.<<<!!!!!!!!!!
UCB1CTL1 &= ~UCTR;// config as read.
I2CWaitToStop ();
UCB1CTL1 |= UCTXSTT;// transmit the address with the start condition.
I2CWaitToStart ();
/* after the start condition ( the transmitted with the address)
* the master need to wait for the ack from the slave.
* ( after that neck, the master receive the data and send ack,
* therefore the only ack that the master received is after sending
* the address.
*/
rslt = I2CCheckNack ();/* if nack then the transaction is end here
* the address need to be ack.
*/
if (rslt == TEST_FAIL)// receive nack, and stop the transaction.
{
return FAIL;
}
I2CRdData( numRd, I2cRdbuf);
I2CEndTrns ();
return OK;
}
Uint16 I2CWaitToStop (void)
{
Uint32 I2CWatchCounter = I2C_BUSY_CYCLES;
I2CWatchCounter = I2C_BUSY_CYCLES;
while (((UCB1CTL1 & UCTXSTP))&& (--I2CWatchCounter));
if (I2CWatchCounter==0)// then error
{
I2CErrNum = SET;
return FAIL;
}
return OK;
}
Uint16 I2CWaitToStart (void)
{
Uint32 I2CWatchCounter = I2C_BUSY_CYCLES;
// UCB1CTL1 |= UCTXSTT; // I2C Set Start condition/transaction.
// __no_operation();
//------------------------------------------
I2CWatchCounter = I2C_BUSY_CYCLES;
while (((UCB1CTL1 & UCTXSTT))&& (--I2CWatchCounter));// Start condition sent?
if (I2CWatchCounter==0)// then error
{
I2CErrNum = SET;
// return FAIL;
}
return OK;
}
Uint16 I2CRdData(Uint16 numRd, unsigned char * I2cRdbuf)
{
Uint16 I2cRdIndx = 0;
Uint16 NumOfRd = numRd;
Uint32 I2CWatchCounter = I2C_BUSY_CYCLES;
while (NumOfRd--){// number of reading, without repeated start
// while (!(UCB1IFG & UCRXIFG));//UCRXIFG is automatically reset when UCxRXBUF is read
/* wait for the data to receive.
* the slave transmit the data and the master put the ack,
* that the reason that no need to wait for ack from the slave.
*/
I2CWatchCounter = 10*I2C_BUSY_CYCLES;
//UCRXIFG is automatically reset when UCxRXBUF is read
while ((((UCB1IFG & UCRXIFG)==0))&& (--I2CWatchCounter));
if (I2CWatchCounter==0)// then error
{
I2CErrNum = SET;
// return FAIL;
}
//-----------------------------
I2cRdbuf [I2cRdIndx] = UCB1RXBUF;////UCRXIFG is automatically reset when UCxRXBUF is read
// UCB1IFG &= ~UCRXIFG;// //UCRXIFG is automatically reset when UCxRXBUF is read
I2cRdIndx++;
//I2cRdIndx%=I2C_RX_BUF_SIZE;
}
return OK;
}
Uint16 I2CEndTrns (void)// end transaction.
{
UCB1CTL1 |= UCTXSTP;// I2C stop transaction
// while ((UCB1CTL1 & UCTXSTP));// wait until the bit is cleared.
// instead of repeated start.
//UCTXSTP is automatically cleared after STOP is generated.
//----------------------
I2CWaitToStop ();
//-----------------------------
__delay_cycles(I2C_STANDARD_DLY_BETWEEN_TRNSC); // for debug,
return OK;
}