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.
Hello,
I'm trying to control an I2C LED driver (IS31FL3199) as a slave using a MSP430F5529. I started by using one of the msp demos which continually sent bytes (MSP430F55xx_uscib0_i2c_07.c) and I was able to control the driver by changing the slave adress and the data to send without any problems. I also deactivated LPM0 and __no_operation) to have a better understanding of what's happening when the device stops responding. However, I'm struggling to convert this code from continually sending bytes to sending them on demand which requires me to stop transfers as the MSP is supposed to control another I2C device later on.
I've read the section about I2C in the MSP430Fx5xx family guide (slau208p) but I'm not sure where exactly I should put the STOP command during my transmission ISR. I've tried different possibilities but the results are always negative. I assume it has to do with the timing of the STOP command, whether it's set too early and a byte gets cut off during TX or the device hangs for too long before receiving the STOP.
Code is below. Everytime a start command is issued, 4 bytes which represent 2 commands are sent to the I2C device (first two bytes are for activating the device, other two is to power a LED). The data and slave address have been confirmed to be OK beforehand. After sending those 4 bytes, I want to stop the transfer and then restart it later. In the code below, I simply restart it a second later. In reality, I'll be using a GPIO interrupt or specific UART RX to send data to the I2C device. With this code, I manage to go thru the full TX ISR routine, jump back to main() and then restart the TX ISR routine without any problems. However, the LED stays shut down
Does anyone have an idea as to why I have this problem?
Thank you!
#include <msp430.h> const unsigned char TxData[] = { 0x00,0x01, // Start 0x0D,0xAF //OUT7 }; unsigned int i = 0; int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P3SEL |= 0x03; // Assign I2C pins to USCI_B0 UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz UCB0BR1 = 0; UCB0I2CSA = 0x64; // Slave Address is 054h UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation UCB0IE |= UCTXIE; // Enable TX interrupt __enable_interrupt(); while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition while (1) { __delay_cycles(1000000); while (UCB0CTL1 & UCTXSTP); UCB0CTL1 |= UCTR + UCTXSTT; // Restart TX } } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCI_B0_VECTOR __interrupt void USCI_B0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void) #else #error Compiler not supported! #endif { 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: // Vector 6: STTIFG { UCB0IFG &= ~UCSTTIFG; // Clear start condition int flag break; } case 8: // Vector 8: STPIFG UCB0IFG &= ~UCSTPIFG; // Clear stop condition int flag __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 if data was transmitted break; case 10: break; // Vector 10: RXIFG case 12: // Vector 12: TXIFG { for (i =0;i<4;i++) { if(i==0 ||i==2) __delay_cycles(20000); // Used to let the IS31FL3199 apply the command UCB0TXBUF = TxData[i]; __delay_cycles(10); // Delay between each byte sent if (i==3) UCB0CTL1 |= UCTXSTP; // Stop TX } break; } default: break; } }
Thank you for your quick answer. I've looked at the Driverlib code and tried to replicate it in my code (I'm trying to avoid using driverlib for the time being). I've replaced my wait cycle between each byte with the correct loop. I've also added the UCTXSTP command at the end of my ISR, but LEDs still stay off.
In this case, is it safe to assume that the problem isn't from the ISR? I've written my new ISR below. It still sends the same 4 bytes before sending a STOP command.
Thank you for your time.
#pragma vector = USCI_B0_VECTOR __interrupt void USCI_B0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void) #else #error Compiler not supported! #endif { 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: // Vector 6: STTIFG { UCB0IFG &= ~UCSTTIFG; // Clear start condition int flag break; } case 8: // Vector 8: STPIFG UCB0IFG &= ~UCSTPIFG; // Clear stop condition int flag __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 if data was transmitted break; case 10: break; // Vector 10: RXIFG case 12: // Vector 12: TXIFG { UCB0IE &= ~UCTXIE; for (i =0;i<4;i++) { if(i==0 ||i==2) __delay_cycles(10000); // Pause between byte groups to see LEDs flicker UCB0TXBUF = TxData[i]; while(!(UCB0IFG & UCTXIFG)); } UCB0CTL1 |= UCTXSTP; UCB0IFG &= ~UCTXIFG; UCB0IE |= UCTXIE; break; } default: break; } }
**Attention** This is a public forum