This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
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
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;
}
Hi Asher,
On the bottom of the post, there is a button marked "More" - I think when you click this one of your options should be delete. I'm a moderator so I can delete these duplicates for you though - just letting you know how to do it in the future.
Before I delete them however, I am thinking this could be a bug with our forum that should be reported. Can you please let me know:
-Katie
Hi asher,
If you go to the post at this link: http://e2e.ti.com/support/microcontrollers/msp430/f/166/p/398264/1410324
You should be able to scroll to directly below your first post and see a button that says "More" (I've marked it in green here):
When you click on this button More, then there should be a list that pops up that shows options including "Edit" - click that option and you should be able to edit the post.
Regards,
Katie
**Attention** This is a public forum