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.
Tool/software:
Main Code:
void main(void) { //Init similiar to receive example for MSP430 FR5969 init_I2C(); while(1){ cmd_process(); } }
Init_I2C():
void init_I2C(){ WDT_A_hold(WDT_A_BASE); // Configure Pins for I2C //Set P1.6 and P1.7 as Secondary Module Function Input. /* * Select Port 1 * Set Pin 6, 7 to input Secondary Module Function, (UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL). */ GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_P1, GPIO_PIN6 + GPIO_PIN7, GPIO_SECONDARY_MODULE_FUNCTION ); /* * Disable the GPIO power-on default high-impedance mode to activate * previously configured port settings */ PMM_unlockLPM5(); // eUSCI configuration EUSCI_B_I2C_initSlaveParam param = {0}; param.slaveAddress = SLAVE_ADDRESS; param.slaveAddressOffset = EUSCI_B_I2C_OWN_ADDRESS_OFFSET0; param.slaveOwnAddressEnable = EUSCI_B_I2C_OWN_ADDRESS_ENABLE; EUSCI_B_I2C_initSlave(EUSCI_B0_BASE, ¶m); EUSCI_B_I2C_enable(EUSCI_B0_BASE); EUSCI_B_I2C_clearInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 + EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_STOP_INTERRUPT ); EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 + EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_STOP_INTERRUPT ); // __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts // __no_operation(); }
cmd_process():
void cmd_process() { switch(current_Statemachine) { case IDLE: resumeI2CInterrupts(); break; case HEALTH_CHECK: // Simply Returns the received data TXData = myPayload; current_Statemachine = IDLE; break; ... Rest of the code
Master Arduino Code(TEENSY):
#include <Wire.h> byte arrToSend[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; void test_health_check(int numofBytes) { Wire.beginTransmission(0x08); // Address of the MSP430 slave Wire.write(0x22); int i; for(i = 0; i<numofBytes; i++) { Wire.write(arrToSend[i]); } Wire.endTransmission(); delay(1000); Wire.requestFrom(0x08, ++numofBytes); Serial.write("Receiving "); Serial.print(numofBytes); Serial.write(" byte(s):"); while(Wire.available()) { char c = Wire.read(); // Receive a byte Serial.write(" "); Serial.write(c); // Print the character numofBytes--; if(numofBytes == 0) break; } Serial.write("\n"); } void setup() { Wire.begin(); // Join the I2C bus as a master Serial.begin(9600); int i; for(i = 0; i < 10; i++) test_health_check(i); } void loop() { int i; for(i = 0; i < 10; i++) { delay(2000); test_health_check(i); } }
Where the issue is happening
The ISR:
void suspendI2CInterrupts() { EUSCI_B_I2C_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 + EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_STOP_INTERRUPT ); } void resumeI2CInterrupts() { EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 + EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_STOP_INTERRUPT ); __bis_SR_register(CPUOFF + GIE); // Enter LPM with interrupts } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCI_B0_VECTOR __interrupt #elif defined(__GNUC__) __attribute__((interrupt(USCI_B0_VECTOR))) #endif void USCIB0_ISR(void) { // static uint8_t * incoming_Data = myPayload; static uint8_t incoming_data_index = 0; static uint8_t rcving_Data = 0; switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG)) { case USCI_NONE: // No interrupts break; break; case USCI_I2C_UCALIFG: // Arbitration lost break; case USCI_I2C_UCNACKIFG: // NAK received (master only) break; case USCI_I2C_UCSTTIFG: // START condition detected with own address (slave mode only) break; case USCI_I2C_UCSTPIFG: // STOP condition detected (master & slave mode) incoming_data_index = 0; if (rcving_Data==1){ rcving_Data = 0; cmd_receive(); } break; case USCI_I2C_UCRXIFG3: // RXIFG3 break; case USCI_I2C_UCTXIFG3: // TXIFG3 break; case USCI_I2C_UCRXIFG2: // RXIFG2 break; case USCI_I2C_UCTXIFG2: // TXIFG2 break; case USCI_I2C_UCRXIFG1: // RXIFG1 break; case USCI_I2C_UCTXIFG1: // TXIFG1 break; case USCI_I2C_UCRXIFG0: // RXIFG0 // suspendI2CInterrupts(); // Commenting this allowed us to send data the case "USCI_I2C_UCTXIFG0" __bic_SR_register_on_exit(CPUOFF); RXData = EUSCI_B_I2C_slaveGetData(EUSCI_B0_BASE); // if (RXData == 0x01){ // GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0); // // GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN0); // }else if (RXData == 0x02){ // GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0); // // GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0); // } // *incoming_Data = RXData; // incoming_Data++; myPayload[incoming_data_index++] = RXData; rcving_Data = 1; break; case USCI_I2C_UCTXIFG0: // TXIFG0 __bic_SR_register_on_exit(CPUOFF); EUSCI_B_I2C_slavePutData(EUSCI_B0_BASE, *TXData ); TXData++; break; case USCI_I2C_UCBCNTIFG: // Byte count limit reached (UCBxTBCNT) break; case USCI_I2C_UCCLTOIFG: // Clock low timeout - clock held low too long break; case USCI_I2C_UCBIT9IFG: // Generated on 9th bit of a transmit (for debugging) break; default: break; } }
For the first three bytes the "USCI_I2C_UCRXIFG0" case is run,
then the stop condition case "USCI_I2C_UCSTPIFG" is run
then the last byte is processed and the "USCI_I2C_UCRXIFG0" case is ran even though its supposed to happen before the stop condition.
ignore the first run in the serial output, The subsequent ones rewrite the first index because the stop condition is always executed before the last byte is processed, the first byte printed should be "0x22".
I am Using 5.5K Ohms pullups and the MSP430 provides a VCC of 3.6V.
MSP430 is slave and Arduino Teensy is Master.
STPIFG has higher priority (in the IV) than RXIFG, so there is a race. If the Stop is recognized before the ISR reads the IV (for the RXIFG), the Stop is presented first. There's only one I2C clock between the Rx completion and the Stop completion, so this is highly probable.
I (personally) try to avoid using UCSTPIFG at all, for this reason. Alternatively you can check the RXIFG bit directly, but I found that fairly messy to unwind.
**Attention** This is a public forum