Rei Vilo 695 Posted July 18, 2016 Share Posted July 18, 2016 I'm using an I Quote Link to post Share on other sites
terjeio 134 Posted July 18, 2016 Share Posted July 18, 2016 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); I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); while(bytes--) { while(I2CMasterBusy(I2C1_BASE)); *data++ = I2CMasterDataGet(I2C1_BASE); I2CMasterControl(I2C1_BASE, bytes ? I2C_MASTER_CMD_BURST_RECEIVE_CONT : I2C_MASTER_CMD_BURST_RECEIVE_FINISH); } 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". Rei Vilo 1 Quote Link to post Share on other sites
spirilis 1,265 Posted July 18, 2016 Share Posted July 18, 2016 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() Rei Vilo 1 Quote Link to post Share on other sites
B@tto 51 Posted July 20, 2016 Share Posted July 20, 2016 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. Quote Link to post Share on other sites
Rei Vilo 695 Posted July 24, 2016 Author Share Posted July 24, 2016 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. Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.