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: Code Composer Studio
Hi everyone
I have a board which communicates with a Sensor but I want to use the MSP430F5529 instead of the board. I am communicating via I2C between the MSP430 (Master) and the Sensor (Slave). I have written the code for the Master, which does not work fully.
This is how it should work with delays between the transactions. The first delay is about 15us and the second one about 60us. SMCLK is 200kHz.
The Master first sends a Start condition, then the Register Adress(0). After this, he makes a Restart and the Slave transmits the Data(15).
This is how it is at the moment. The problem is that there are no delays between the transactions so the slave can't transmitt the Data. The Master always receives a '0' instead of '15'.
Here is my Code:
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P3SEL |= 0x03; // Assign I2C pins to USCI_B0
P8DIR |= BIT1; // Set P8.1 to output direction
P8OUT |= BIT1;
for(x=100;x>0;x--);
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK
UCB0BR0 = 6; // fSCL = SMCLK/6 = ~200kHz
UCB0BR1 = 0;
UCB0I2CSA = 0x55; // Slave Address is 055h
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
UCB0IE |= UCRXIE; // Enable RX interrupt
UCB0CTL1 |= UCTR+UCTXSTT; // I2C start condition, write
while (!(UCB0CTL1 & UCTXSTT)); // Ensure start condition got sent
while (!(UCB0IFG & UCTXIFG)); // wait until data can be written
UCB0IFG &= ~UCTXIFG; // reset Tx interrupt flag
UCB0TXBUF = 0x00; // transmit data
while (!(UCB0IFG & UCTXIFG)); // wait until data can be written
UCB0IFG &= ~UCTXIFG; // reset Tx interrupt flag
UCB0CTL1 &= ~UCTR; // set receiver mode
UCB0CTL1 |= UCTXSTT; // send restart
while(UCB0CTL1 & UCTXSTT); // wait until start condition reset
UCB0IFG &= ~UCRXIFG; // reset Rx interrupt flag
while(!(UCB0IFG & UCRXIFG)); // wait until Receive flag is reset
__no_operation(); // For debugger
}
// USCI_B0 Data ISR
#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: break; // Vector 6: STTIFG
case 8: break; // Vector 8: STPIFG
case 10: // Vector 10: RXIFG
RXData = UCB0RXBUF; // Get RX data
break;
case 12: break; // Vector 12: TXIFG
default: break;
}
}
Does anybody know what I am doing wrong or how I can fix this?
Thanks for Help
Fabian
Hi Ryan
I don't use the interrupt function at the moment.
Here are the images
When I use the demoboard with the sensor it looks like this with delays between the bytes. The first delay is about 15us and the second one about 60us. The Master first sends a Start condition with slave address, then the Register Address(0). After this, he makes a Restart with slave address and the Slave transmits the Data(15).
This is how it looks at the moment with the MSP430. I think the problem is that there are no delays between the bytes so the slave can't transmit the Data. Is it normally that there are delays between the bytes and how can i do them? The Master always receives a '0' instead of '15'.
Once I set a breakpoint after the Master sent the start condition with the slave address and the Master received to correct Data('15'). That's why I think the delays are the problem.
Here is my code:
#include <msp430.h> unsigned char RXData; int x; int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P3SEL |= 0x03; // Assign I2C pins to USCI_B0 P8DIR |= BIT1; // Set P8.1 to output direction P8OUT |= BIT1; for(x=100;x>0;x--); UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK UCB0BR0 = 6; // fSCL = SMCLK/6 = ~200kHz UCB0BR1 = 0; UCB0I2CSA = 0x55; // Slave Address is 055h UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation UCB0IE |= UCTXIE; // Enable TX interrupt UCB0IE |= UCRXIE; // Enable RX interrupt UCB0CTL1 |= UCTR+UCTXSTT; // I2C start condition, write while (!(UCB0CTL1 & UCTXSTT)); // Ensure start condition got sent while (!(UCB0IFG & UCTXIFG)); // wait until data can be written UCB0TXBUF = 0x00; // transmit data while (!(UCB0IFG & UCTXIFG)); // wait until data can be written UCB0CTL1 &= ~UCTR; // set receiver mode UCB0CTL1 |= UCTXSTT; // send restart while(UCB0CTL1 & UCTXSTT); // wait until start condition reset while(!(UCB0IFG & UCRXIFG)); // wait until Receive flag is reset __no_operation(); // For debugger } // USCI_B0 Data ISR #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: break; // Vector 6: STTIFG case 8: break; // Vector 8: STPIFG case 10: // Vector 10: RXIFG RXData = UCB0RXBUF; // Get RX data break; case 12: break; // Vector 12: TXIFG default: break; } }
Thanks for your help
Fabian
This is not what clock stretching means; the slave would automatically use it if it supported it.
You could try to add __delay_cycles(...) after the wait loops in your code.
Before sending the restart instruction, you can use a UCBUSY while loop to confirm that the master is done transmitting. This way the __delay_cycles function will appear at the proper time during the communication sequence.
You should put a forever while loop at the end of your code so that it doesn't complete main, that way you are not dependent on the debugger to halt at a breakpoint.
Regards,
Ryan
This is the result, when I add the UCBUSY while loop. The Master transmits the Register adress ('0') but I don't do a Stop. The UCBUSY is only cleared after a Stop.
Here is the part of the code that I have changed:
UCB0CTL1 |= UCTR+UCTXSTT; // I2C start condition, write while (!(UCB0CTL1 & UCTXSTT)); // Ensure start condition got sent while (!(UCB0IFG & UCTXIFG)); // wait until data can be written UCB0TXBUF = 0x00; // transmit data while (!(UCB0IFG & UCTXIFG)); // wait until data can be written while (UCB0STAT & UCBBUSY); // wait until bus isn't busy UCB0CTL1 &= ~UCTR; // set receiver mode UCB0CTL1 |= UCTXSTT; // send restart while(UCB0CTL1 & UCTXSTT); // wait until start condition reset while(!(UCB0IFG & UCRXIFG)); // wait until Receive flag is reset __no_operation(); // For debugger while(1);
To Clemens Ladisch:
There is a rising edge on EN 1ms befor the Master sends the first Start condition and the EN remains high to the end.
**Attention** This is a public forum