Tool/software: Code Composer Studio
Hello,
What I thought would be a very simple task has now delayed a project by two weeks, and although I think that I have identified the problem, I would like expert advice.
The msp430 is used for a single task when the system is starting up. It delays 30 seconds, then sends 0x1F to an i2c slave at 0x33 at 400 kHz. That's it.
I have read the clock system and i2c sections of the user manual and don't believe that I am missing anything, and have looked through the code examples [here].
I tried to stay as close to the examples as possible. My approach was as follows:
1st, I followed one of the examples, msp430fr231x_CS_01.c "Configure MCLK for 8MHz sourced from DCO." to set DCO to 2.4 kHz (although I am not sure that it wan't taken as 2 kHz)
Then I used CSCTL5 to set MCLK to 2.4 MHz and SMCLK to 400 kHz. Next I configure the I2C pins, then for testing purposed transmit 0x1F to 0x33 every 3 seconds.
I copied-and pasted the interrupt handling and the trimming function from the examples and modified a few parameters.
I have verified that the scl signal exists with an oscilloscope, but I have used an "aardvark" i2c testing device from total phase in addition to a testing tool provided by the manufacturer of the slave device, and neither actually recognizes that information is being sent. Does the code below match the task? Is there anything in the description above that suggests another mistake?
Thanks in advance,
#include <msp430.h> void Software_Trim(); // Software Trim to get the best DCOFTRIM value unsigned char TXData =0x1F; unsigned char TXByteCtr; #define MCLK_FREQ_MHZ 2.4 // MCLK = 2.4MHz int main(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer __bis_SR_register(SCG0); // disable FLL CSCTL3 |= SELREF__REFOCLK; // Set REFO as FLL reference source CSCTL1 = DCOFTRIMEN_1 | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_3;// DCOFTRIM=3, DCO Range = 2.4MHz CSCTL2 = FLLD_0 + 243; // DCODIV = 2.4MHz __delay_cycles(3); __bic_SR_register(SCG0); // enable FLL Software_Trim(); // Software Trim to get the best DCOFTRIM value CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32768Hz) as ACLK source, ACLK = 32768Hz // default DCODIV as MCLK and SMCLK source CSCTL5 |= DIVM_0 | DIVS_3; // MCLK = XT1CLK = 2.4MHZ, // SMCLK = MCLK/2 = 0.4MHz = 400 kHz // Configure I2C Pins P1SEL0 |= BIT2 | BIT3; //I2C pins // Disable the GPIO power-on default high-impedance mode // to activate previously configured port settings PM5CTL0 &= ~LOCKLPM5; // Configure USCI_B0 for I2C mode UCB0CTLW0 |= UCSWRST; // put eUSCI_B in reset state UCB0CTLW0 |= UCMODE_3 | UCMST; // I2C master mode, SMCLK UCB0BRW = 0x8; // baudrate = SMCLK / 8 UCB0CTLW0 &=~ UCSWRST; // clear reset register UCB0IE |= UCTXIE0 | UCNACKIE; // transmit and NACK interrupt enable while(1){ //Delay for 3s __delay_cycles(300000); //30000000 //Deployment Algorithm 1 for all 4 antennas UCB0I2CSA = 0x33; // configure slave address to 0x33 TXByteCtr = 2; // Load TX byte counter while (UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent UCB0CTLW0 |= UCTR | UCTXSTT; // I2C TX, start condition __bis_SR_register(LPM0_bits | GIE); // Enter LPM0 w/ interrupts } //return 0; } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCI_B0_VECTOR __interrupt void USCIB0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void) #else #error Compiler not supported! #endif { switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG)) { case USCI_NONE: break; // Vector 0: No interrupts case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG case USCI_I2C_UCNACKIFG: break; // Vector 4: NACKIFG case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG case USCI_I2C_UCSTPIFG: // Vector 8: STPIFG TXData = 0; UCB0IFG &= ~UCSTPIFG; // Clear stop condition int flag break; case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3 case USCI_I2C_UCTXIFG3: break; // Vector 14: TXIFG3 case USCI_I2C_UCRXIFG2: break; // Vector 16: RXIFG2 case USCI_I2C_UCTXIFG2: break; // Vector 18: TXIFG2 case USCI_I2C_UCRXIFG1: break; // Vector 20: RXIFG1 case USCI_I2C_UCTXIFG1: break; // Vector 22: TXIFG1 case USCI_I2C_UCRXIFG0: break; // Vector 24: RXIFG0 case USCI_I2C_UCTXIFG0: UCB0TXBUF = TXData++; break; // Vector 26: TXIFG0 case USCI_I2C_UCBCNTIFG: break; // Vector 28: BCNTIFG case USCI_I2C_UCCLTOIFG: break; // Vector 30: clock low timeout case USCI_I2C_UCBIT9IFG: break; // Vector 32: 9th bit default: break; } } void Software_Trim() { unsigned int oldDcoTap = 0xffff; unsigned int newDcoTap = 0xffff; unsigned int newDcoDelta = 0xffff; unsigned int bestDcoDelta = 0xffff; unsigned int csCtl0Copy = 0; unsigned int csCtl1Copy = 0; unsigned int csCtl0Read = 0; unsigned int csCtl1Read = 0; unsigned int dcoFreqTrim = 3; unsigned char endLoop = 0; do { CSCTL0 = 0x100; // DCO Tap = 256 do { CSCTL7 &= ~DCOFFG; // Clear DCO fault flag }while (CSCTL7 & DCOFFG); // Test DCO fault flag __delay_cycles((unsigned int)3000 * MCLK_FREQ_MHZ);// Wait FLL lock status (FLLUNLOCK) to be stable // Suggest to wait 24 cycles of divided FLL reference clock while((CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)) && ((CSCTL7 & DCOFFG) == 0)); csCtl0Read = CSCTL0; // Read CSCTL0 csCtl1Read = CSCTL1; // Read CSCTL1 oldDcoTap = newDcoTap; // Record DCOTAP value of last time newDcoTap = csCtl0Read & 0x01ff; // Get DCOTAP value of this time dcoFreqTrim = (csCtl1Read & 0x0070)>>4;// Get DCOFTRIM value if(newDcoTap < 256) // DCOTAP < 256 { newDcoDelta = 256 - newDcoTap; // Delta value between DCPTAP and 256 if((oldDcoTap != 0xffff) && (oldDcoTap >= 256)) // DCOTAP cross 256 endLoop = 1; // Stop while loop else { dcoFreqTrim--; CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4); } } else // DCOTAP >= 256 { newDcoDelta = newDcoTap - 256; // Delta value between DCPTAP and 256 if(oldDcoTap < 256) // DCOTAP cross 256 endLoop = 1; // Stop while loop else { dcoFreqTrim++; CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4); } } if(newDcoDelta < bestDcoDelta) // Record DCOTAP closest to 256 { csCtl0Copy = csCtl0Read; csCtl1Copy = csCtl1Read; bestDcoDelta = newDcoDelta; } }while(endLoop == 0); // Poll until endLoop == 1 CSCTL0 = csCtl0Copy; // Reload locked DCOTAP CSCTL1 = csCtl1Copy; // Reload locked DCOFTRIM while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked }