Hello,
I'm trying to readout a sensor MMA7660FC with I2C on an cc430f5133. The I2c send commands seem to work alright, but when I want to receive i have to do the following:
send startcondition+write->send the byteaddress to read-> send repeated start+no_read -> receive byte from the sensor -> stop or read another byte. Now I've been looking at a lot of code allready and i've also scanned through some questions in this forum but I just cannot find out how to implement this correct in the cc430code. I checked the signals with a Oscilloscoop and something seems to go wrong. The code is partwise coppied from from the code examples of the cc430. I also noticed that transmission of the byte 0x00 (in case 12 in the code) doesn't work (It looks like the hardware doesn't notice that a byte is written into UCB0TXBUF how can i resolve this and what is the correct way to do a repeated start -> first write then read to/from a slave? Or does someone have some example code that i can studie?
My code looks as follows:
// I think setup of the I2c is correct because sending works and is acked by the slave.
//*********** the receiving function ********
unsigned char I2C_receive(unsigned char registernr,unsigned char nrof_bytes, unsigned char* RxBuffer )
{
data_to_send[0]=registernr; // register where the read is started
TXByteCtr=255; // special value
bytes_to_receive=nrof_bytes; // nr of bytes that should be received
PRxData = (unsigned char *)RxBuffer; // PRxData points to start of buffer
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTR + UCTXSTT; // first the start condition has to be sent
__bis_SR_register(GIE);
__no_operation();
return 1;
}
//*********** and the interrupt routing *******
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
switch(__even_in_range(UCB0IV,12))
{
case 0: break; // Vector 0: No interrupts
case 2: break; // Vector 2: ALIFG
case 4: break; // Vector 4: NACKIFG
case 6: break; // Vector 6: STTIFG
case 8: break; // Vector 8: STPIFG stop has been sent
case 10: // Vector 10: RXIFG
bytes_to_receive--; // Decrement RX byte counter
if (bytes_to_receive)
{
*PRxData++ = UCB0RXBUF; // Move RX data to prxdata and increase pointer
if (bytes_to_receive == 1) // Only one byte left?
UCB0CTL1 |= UCTXSTP; // Generate I2C stop condition
//UCB0CTL1 |= UCTXNACK; // cleared after nack is transmitter not needed because generating UCTSTP gives nack and stop page 647
}
else
{
*PRxData = UCB0RXBUF; // Move final RX data to PRxData
//__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
}
break;
case 12: // Vector 12: TXIFG
// check for busy transmission -> stop condition send?
if (TXByteCtr==255) // when special nr of bytes is received there is only one byte to send and no stop has to be sent
{
UCB0TXBUF = 0x00; //data_to_send[0]; // send one byte then go in receive mode
//UCB0CTL1 |= UCTXSTP;
TXByteCtr=0; // set TX byte counter to 0
__delay_cycles(100);
UCB0CTL1 &= ~UCTR; // activate receiving mode
UCB0CTL1 |= UCTXSTT;
}
else if (TXByteCtr) // Check TX byte counter
{
UCB0TXBUF = *PTxData++; // Load TX buffer with the data to send
TXByteCtr--; // Decrement TX byte counter
}
else
{
UCB0CTL1 |= UCTXSTP; // I2C stop condition after next acknowlege of slave
UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
//__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 (has not been entered hence commented)
}
break;
default: break;
}
}
Thank You,
Geert Verhaeg