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 am new to msp430 technology and microcontroler programming. currently I am working on i2c but I am stuck with this problem. Please don't be harsh and correct me if i'm wrong but shoudn't __bis_SR_register(LPM3_bits + GIE); make the programm go into ISR? And what is the difference between LPM0 and LPM1(2,3,4)?
I added output commands so i could see in console where is my code getting stuck and it always stucks at shoudn't __bis_SR_register(LPM3_bits + GIE);
/* * main.c */ #include <msp430.h> #include <stdio.h> unsigned char SlaveAddress = 0x76; unsigned char TXByteCtr; unsigned char RXByteCtr; unsigned char *PTxData; unsigned char *PRxData; unsigned char RXData[6]; unsigned char TXDataArr[3]; void initI2C(void); void RXdata(unsigned char reg_addr, unsigned char RX_byte); void TXdata(unsigned char TX_byte); void iic_TX(void); void iic_RX(void); void start_TX(void); void start_RX(void); void init_slave(); void read_slave(); int main(void) { WDTCTL = WDTPW | WDTHOLD; //// I/O INIT // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; P1SEL1 |= BIT6 | BIT7; // I2C pins //// initI2C(); __bis_SR_register(GIE); init_slave(); read_slave(); while(1) { //read_slave(); } } /////////////////// I2C B0/////////////////// #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 { puts("interupt service routine entered\n"); switch(__even_in_range(UCB0IV,0x1E)) { case 0x00: break; // Vector 0: No interrupts break; case 0x02: break; case 0x04: UCB0CTLW0 |= UCTXSTT; //resend start if NACK break; // Vector 4: NACKIFG break; case 0x06: break; // Vector 6: STTIFG break; case 0x08: break; // Vector 8: STPIFG break; case 0x0a: break; // Vector 10: RXIFG3 break; case 0x0c: break; // Vector 14: TXIFG3 break; case 0x0e: break; // Vector 16: RXIFG2 break; case 0x10: break; // Vector 18: TXIFG2 break; case 0x12: break; // Vector 20: RXIFG1 break; case 0x14: break; // Vector 22: TXIFG1 break; case 0x16: // Vector 24: RXIFG0 break; *PRxData++ = UCB0RXBUF; // Get RX data RXByteCtr --; if (RXByteCtr == 0) { __delay_cycles(30); UCB0CTLW1 |= UCSWACK; UCB0CTLW0 |= UCTXACK; UCB0CTLW0 |= UCTXSTP; } else { UCB0IFG &= ~UCRXIFG0; __bic_SR_register_on_exit(LPM3_bits); } break; case 0x18: if (TXByteCtr){ // Check TX byte counter UCB0TXBUF = *PTxData++; // Load TX buffer TXByteCtr--; } else { UCB0CTLW0 |= UCTXSTP; // I2C stop condition UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag __bic_SR_register_on_exit(LPM3_bits);// Exit LPM0 } break; // Vector 26: TXIFG0 break; case 0x1A: UCB0IFG &= ~UCBCNTIFG; break; // Vector 28: BCNTIFG break; case 0x1c: break; // Vector 30: clock low timeout break; case 0x1e: break; // Vector 32: 9th bit break; default: break; } } void initI2C(void){ puts("initialising i2c"); UCB0CTLW0 |= UCSWRST; // put eUSCI_B in reset state UCB0CTLW0 |= UCMODE_3 | UCMST | UCSSEL_2 | UCSYNC;// I2C mode, master mode, SMCLk /// + UCSSEL_2 | UCSYNC UCB0CTLW1 |= UCASTP_2; //automatic stop generated //after UCB0TBCNT is reached UCB0BRW = 0x20; // 12 UCB0CTLW0 &=~ UCSWRST; //clear reset register UCB0IE |= UCNACKIE | UCBCNTIE; puts("initialising i2c successful"); } void TXdata(unsigned char TX_byte) { puts("calling iic_TX"); iic_TX(); puts("returned from iic_TX"); PTxData = (unsigned char *)&TXDataArr; // TX array start address printf("PTxData = %d", TXDataArr[0]); TXByteCtr = TX_byte; // Load TX byte counter printf("TXByteCtr = %d\n",TX_byte); puts("calling start_TX"); start_TX(); } void iic_TX(void) { puts("entered iic_TX \n"); printf("slave address = %d \n", SlaveAddress); UCB0I2CSA = SlaveAddress; puts("enabling tx interupt"); UCB0IE |= UCTXIE0; // Enable TX interrupt puts("TX interupt enabled \n"); puts("exiting iic_TX\n"); } void start_TX(void) { puts("entered start_TX \n"); while (UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent puts("stop condition sent \n"); puts("starting i2c TX\n"); UCB0CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition puts("start condition met\n"); puts("entering interupt service routine\n"); __bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupts puts("exiting start_TX\n"); } void init_slave(){ puts("initialising sensor"); TXDataArr[0] = 0xF4; TXDataArr[1] = BIT5 + BIT2 + BIT1; TXdata(2); puts("initialising sensor successful"); } void read_slave(){ puts("reading data from sensor.."); RXdata(0xFA, 2); puts("data read"); }
1) Shoudn't i enable UCRXIE0 if i wan't to use master as a receiver at later point?
2) If i wan't to just enter ISR shuld i use LPM if i don't need to save power.
3) I can't figure out what is wrong with my code if i enable LPM i get stuck in __bis_SR_register(LPM0_bits + GIE) - this time i enabled UCTXIE0 right before I want to enter ISR. And if i don't enable LPM the ISR is skipped
#include <msp430.h> #include <stdio.h> void initialize_master(void); void initialize_slave(void); void transmit_data(unsigned char tx_byte); void start_tx(void); const unsigned char SLAVE_ADDRESS = 0x76; unsigned char rx_byte_ctr = 0; unsigned char tx_byte_ctr = 0; unsigned char rx_data = 0; unsigned char tx_data[] = {}; unsigned char tx_byte = 0; //const unsigned char TXData[] = { 0xA1, 0xB1, 0xC1, 0xD1 }; //const unsigned char SlaveAddress[] = { 0x0A, 0x0B, 0x0C, 0x0D }; int main(void) { tx_data[0] = 0xF4; tx_data[1] = BIT5 + BIT2 + BIT1; WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer P1SEL1 |= BIT6 | BIT7; // set i2c pins // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; initialize_master(); while (1) { initialize_slave(); // __delay_cycles(2000); // UCB0I2CSA = SLAVE_ADDRESS; // tx_byte_ctr = 1; // while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent // UCB0CTLW0 |= UCTR | UCTXSTT; // I2C start condition // __bis_SR_register(GIE); // Enter LPM0 w/ interrupt } //return 0; } #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, USCI_I2C_UCBIT9IFG)) { case USCI_NONE: break; // Vector 0: No interrupts case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG UCB0CTL1 |= UCTXSTT; // I2C start condition break; case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3 case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3 case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2 case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2 case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1 case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1 case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0 rx_data = UCB0RXBUF; // Get RX data __bic_SR_register_on_exit(LPM0_bits | GIE); // Exit LPM0 break; case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0 if (tx_byte_ctr) // Check TX byte counter { int i = 0; UCB0TXBUF = &tx_data; // Load TX buffer tx_byte_ctr--; // Decrement TX byte counter i++; } else { UCB0CTLW0 |= UCTXSTP; // I2C stop condition UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag __bic_SR_register_on_exit(LPM0_bits | GIE); // Exit LPM0 } break; case USCI_I2C_UCBCNTIFG: // Vector 26: BCNTIFG P1OUT ^= BIT0; // Toggle LED on P1.0 break; case USCI_I2C_UCCLTOIFG: break; // Vector 28: clock low timeout case USCI_I2C_UCBIT9IFG: break; // Vector 30: 9th bit default: break; } } void initialize_master(void){ UCB0CTLW0 |= UCSWRST; // put eUSCI_B in reset state UCB0CTLW0 |= UCMODE_3 | UCMST | UCSSEL_2 | UCSYNC;// I2C mode, master mode, SMCLk /// + UCSSEL_2 | UCSYNC UCB0CTLW1 |= UCASTP_2; //automatic stop generated //after UCB0TBCNT is reached UCB0BRW = 0x20; // 12 UCB0CTLW0 &=~ UCSWRST; //clear reset register UCB0IE |= UCNACKIE | UCBCNTIE; } void initialize_slave(void){ tx_data[0] = 0xF4; tx_data[1] = BIT5 + BIT2 + BIT1; transmit_data(2); } void transmit_data(unsigned char tx_byte) { UCB0I2CSA = SLAVE_ADDRESS; tx_byte_ctr = tx_byte; // Load TX byte counter start_tx(); } void start_tx(void) { // while (UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent UCB0CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition UCB0IE |= UCTXIE0; // Enable TX interrupt __delay_cycles(2000); __bis_SR_register(LPM0_bits | GIE); __delay_cycles(2000); //__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts }
4) Does it matter how much delay I set?
I ask these questions because i look at the TI examples and don't get why the LPMs
5) Could there be something wrong with my project setup or hardware itself?
//* #include <msp430.h> //#include <stdio.h> void initialize_master(void); void initialize_slave(void); void transmit_data(unsigned char tx_byte); void start_tx(void); const unsigned char SLAVE_ADDRESS = 0x76;//works w/ 0x46 unsigned char rx_byte_ctr = 0; unsigned char tx_byte_ctr = 0; unsigned char rx_data = 0; unsigned char tx_data[] = {}; unsigned char tx_byte = 0; //const unsigned char TXData[] = { 0xA1, 0xB1, 0xC1, 0xD1 }; //const unsigned char SlaveAddress[] = { 0x0A, 0x0B, 0x0C, 0x0D }; int main(void) { tx_data[0] = 0xF4; tx_data[1] = BIT5 + BIT2 + BIT1; WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer P1SEL1 |= BIT6 | BIT7; // set i2c pins P1REN |= BIT6 | BIT7; //pull ups // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; while (1) { initialize_master(); initialize_slave(); //return 0; } #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, USCI_I2C_UCBIT9IFG)) { case USCI_NONE: break; // Vector 0: No interrupts case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG UCB0CTL1 |= UCTXSTT; //resend start if NACK break; case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3 case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3 case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2 case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2 case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1 case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1 case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0 rx_data = UCB0RXBUF; // Get RX data __bic_SR_register_on_exit(LPM0_bits | GIE); // Exit LPM0 break; case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0 if (tx_byte_ctr) // Check TX byte counter { int i = 0; UCB0TXBUF = tx_data[i]; // Load TX buffer tx_byte_ctr--; // Decrement TX byte counter i++; } else { UCB0CTLW0 |= UCTXSTP; // I2C stop condition UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag __bic_SR_register_on_exit(LPM0_bits | GIE); // Exit LPM0 } break; case USCI_I2C_UCBCNTIFG: // Vector 26: BCNTIFG P1OUT ^= BIT0; // Toggle LED on P1.0 break; case USCI_I2C_UCCLTOIFG: break; // Vector 28: clock low timeout case USCI_I2C_UCBIT9IFG: break; // Vector 30: 9th bit default: break; } } void initialize_master(void){ //printf("initialising i2c\n"); UCB0CTLW0 |= UCSWRST; // put eUSCI_B in reset state UCB0CTLW0 |= UCMODE_3 | UCMST | UCSSEL_2 | UCSYNC;// I2C mode, master mode, SMCLk /// + UCSSEL_2 | UCSYNC UCB0CTLW1 |= UCASTP_2; //automatic stop generated //after UCB0TBCNT is reached UCB0BRW = 0x20; // 12 UCB0CTLW0 &=~ UCSWRST; //clear reset register UCB0IE |= UCNACKIE | UCBCNTIE; //printf("initialising i2c successful\n"); } void initialize_slave(void){ UCB0I2CSA = SLAVE_ADDRESS; tx_data[0] = 0xF4; tx_data[1] = BIT5 + BIT2 + BIT1; transmit_data(2); } void transmit_data(unsigned char tx_byte) { tx_byte_ctr = tx_byte; start_tx(); } void start_tx(void) { while (UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent UCB0IE |= UCTXIE0; // Enable TX interrupt UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition __delay_cycles(2000); __bis_SR_register(LPM0_bits | GIE); }
I put TXIE0 before UCTXSTT like you suggested
I also enabled pull ups (i don't know if i did it correctly) P1REN |= BIT6 | BIT7; //pull ups
And I looked at osciloscope and i can see that slave is not acknowledged. by the way. i use msp-exp430fr5969 launchpad with sensor booster pack and my launchpad has asd and slc as P3.5 and P3.6 although the readings are from P1.6 and P1.7.
**Attention** This is a public forum