Jump to content

Recommended Posts

This is how I implemented (blocking) multi byte read on Tiva, could easily be adapted for variable length frames:

uint8_t* I2CReceiveMany(uint32_t i2cAddr, uint32_t bytes) { // many bytes (min 2, max 8)

	uint8_t *data = I2CBuffer;

	I2CMasterSlaveAddrSet(I2C1_BASE, i2cAddr, true);


	while(bytes--) {


		*data++ = I2CMasterDataGet(I2C1_BASE);



  	return I2CBuffer;

For MSP I did this - still blocking but by sleeping, again could be adapted:

unsigned char* I2CReceiveMany(const unsigned int bytes) { // many bytes (min 2, max 8)
	I2CBCount = bytes;
	pI2CBuffer = I2CBuffer;  		// TX buffer start address
    while (UCB0CTL1 & UCTXSTP);		// Ensure stop condition got sent
    UCB0CTL1 &= ~UCTR;			// I2C start condition
    UCB0CTL1 |= UCTXSTT;			// I2C start condition
 	IFG2 &= ~UCB0RXIE;
 	IE2 |= UCB0RXIE;
    LPM0;							// Enter LPM0 w/ interrupts

    IE2 &= ~UCB0RXIE;				// Disable interrupt and
  	return I2CBuffer;				// return result

#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void) {

	unsigned int tail, intr = IFG2 & IE2;		// Local variables and masked interrupt flags

	...some irrelevant code...

	} else if(intr & UCB0RXIFG) { // I2C RX
		if(--I2CBCount) {
			*pI2CBuffer++ = UCB0RXBUF;
			if(I2CBCount == 1) 					// Only one byte left?
				UCB0CTL1 |= UCTXSTP;				// Generate I2C stop condition
		} else {				// Finished?
			*pI2CBuffer = UCB0RXBUF;
			LPM0_EXIT;							// Exit LPM0


I believe your problem is that you end the transaction by generating a stop condition by reading the first byte separately, I do not know if that is possible to avoid in the Energia framework by somehow modifying a multibyte read "on-the-fly".

Link to post
Share on other sites

Yeah my memory is rusty but from past deconstruction and reconstruction of the Energia Wire framework, what you're trying to do isn't possible since the handling of the reads happens within the ISR.  Obviously this is the case since there is no specific method within Wire to "end" the transfer, i.e. requestFrom is sufficient all by itself to execute the read operation, and it takes an upfront count argument for how many bytes to read, so it must handle the entire transfer from start to stop by itself, putting it in a temporary buffer that you read when you use Wire.read()

Link to post
Share on other sites

I don't understand exactly where is the problem to start a new frame ?


And as I understand Wire for this case, you can ask the max length possible, when slave transmit buffer will be empty he will send a NACK. So in master buffer you will have all the possible bytes.

Link to post
Share on other sites

On the MSP432, calling Wire.requestFrom(I2C_SLAVE, 48); gets all the bytes available, i.e. sent by the device, up to the STOP.


Then, Wire.available() provides the exact number of bytes.


?Unfortunately, the source code for the MSP432 is rather hidden and cryptic.


I don't know whether the same solution applies for other MCUs.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...