I am very new to embedded programming and I2C protocol. I would like to develop a command "CMD_READ_V" which will eventually read an analog voltage from the MSP430 A0 and report it back to the Arduino. However, the part that I am stuck on is that the ADC output is 2 bytes long, which cannot all be fit into the UCB0TXBUF at once, and I would like to develop a structure for the MSP430 to slave transmit "n" bytes for any future commands.
I started with the following for the MSP430, where txIndex was the number of bytes to be sent (not including itself, so for the voltage problem txIndex = 2) followed by the "n" number of bytes in txBuffer, for which I used txBuffer[0] = 0xFA and txBuffer[1] = 0x1B (random numbers). The result of this is that the MSP immediately gets stuck in the while (~(UCB0IFG & UCTXIFG)); loop and transmits nothing to the Arduino. Removing the while (~(UCB0IFG & UCTXIFG)); check results in txIndex being properly transmitted, and the Arduino looping over twice then to read the "actual data", but it only receives the second value 0x1B twice, as 0xFA is (likely, as far as I understand) overwritten in UCB0TXBUF.
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
switch (__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
{
case USCI_I2C_UCSTTIFG: // Start condition
rxIndex = 0;
bytesReceived = 0;
break;
case USCI_I2C_UCSTPIFG: // Stop condition
bytesReceived = rxIndex;
__low_power_mode_off_on_exit(); // Wake main loop
break;
case USCI_I2C_UCRXIFG0: // Data received
rxBuffer[rxIndex++] = UCB0RXBUF;
break;
case USCI_I2C_UCTXIFG0:
UCB0TXBUF = txIndex;
for (i = 0; i < txIndex; i++) {
while (~(UCB0IFG & UCTXIFG));
UCB0TXBUF = txBuffer[i];
}
break;
default:
break;
}
}
The following is the Arduino's master code corresponding to the above program:
void loop() {
Wire.beginTransmission(SLAVE_ADDRESS);
Wire.write(CMD_READ_V);
Wire.endTransmission();
Wire.requestFrom(SLAVE_ADDRESS,3);
rxSize = Wire.read();
Serial.print("Data Size: ");
Serial.println(rxSize);
for (int i = 0; i < rxSize; i++) {
Serial.print(Wire.read(),HEX);
Serial.print(" ");
}
Serial.println();
delay(500);
}
The other attempt I made was for the Arduino to send the command, and then read one byte from the MSP which would be the size of the message again. The Arduino would then loop through Wire.requestFrom(SLAVE_ADDRESS,1); and Wire.read() until the full message was delivered, as shown below.
void loop() {
Wire.beginTransmission(SLAVE_ADDRESS);
Wire.write(CMD_READ_V);
Wire.endTransmission();
Wire.requestFrom(SLAVE_ADDRESS,1);
rxSize = Wire.read();
Serial.print("Data Size: ");
Serial.println(rxSize);
for (int i = 0; i < rxSize; i++) {
Wire.requestFrom(SLAVE_ADDRESS,1);
Serial.print(Wire.read(),HEX);
Serial.print(" ");
}
Serial.println();
delay(500);
}
To which the MSP would then have the txBuffer filled with [0]: the size, [1]: the first byte, [2]: the second byte. Upon receiving the initial command CMD_READ_V, txBuffer would be made. Following that, each read request from the Arduino would have the MSP transmit txBuffer[txIndex] then increment txIndex for the size of the package. That looked like this:
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
switch (__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
{
case USCI_I2C_UCSTTIFG: // Start condition
rxIndex = 0;
bytesReceived = 0;
break;
case USCI_I2C_UCSTPIFG: // Stop condition
bytesReceived = rxIndex;
__low_power_mode_off_on_exit(); // Wake main loop
break;
case USCI_I2C_UCRXIFG0: // Data received
rxBuffer[rxIndex++] = UCB0RXBUF;
break;
case USCI_I2C_UCTXIFG0:
UCB0TXBUF = txBuffer[txIndex++];
break;
default:
break;
}
}
This results in the Arduino correctly receiving 2 as the package size (txBuffer[0]=2;), but the following byte is also received as 2 despite txBuffer[1]=0xFA;. The last byte is correctly received as 0x1B. The especially weird thing is that the following cycle, the Arduino receives a package size of 0 (first byte sent in this cycle) and thus skips the cycle. The entire thing then repeats. Adding while (~(UCB0IFG & UCTXIFG)); once again immediately hangs the entire system.