我正尝试将 MCU 用作数字发现的从器件、数字发现向 MCU 发送命令0x08 (VOLTAGE_CMD)并在 VoltageBuffer 中接收数据进行响应。 然而,我的代码被卡在 main ()中的_ bis_SR_register(LPM0_bits + GIE)行,不能超过这个范围,即使命令是由数字发现发送. 我的代码基于 MSP430FR599x 演示- eUSCI_B2、I2C 从器件多字节 TX/RX 代码。 在我的下面的代码中、是否有任何突出的问题?
//****************************************************************************** // MSP430FR599x Demo - eUSCI_B2, I2C Slave multiple byte TX/RX // // Description: I2C master communicates to I2C slave sending and receiving // 3 different messages of different length. (This is the slave code). The // slave will be in LPM0 mode, waiting for the master to initiate the // communication. The slave will send/receive bytes based on the master's // request. The slave will handle I2C bytes sent/received using the // I2C interrupt. // ACLK = NA, MCLK = SMCLK = DCO 16MHz. // // /|\ /|\ // MSP430FR5994 4.7k | // ----------------- | 4.7k // /|\ | P7.1|---+---|-- I2C Clock (UCB1SCL) // | | | | // ---|RST P7.0|-------+-- I2C Data (UCB1SDA) // | | // | | // | | // | | // | | // | | // // Nima Eskandari and Ryan Meredith // Texas Instruments Inc. // November 2017 // Built with CCS V7.3 //****************************************************************************** #include <msp430.h> #include <stdint.h> //****************************************************************************** // Pin Config ****************************************************************** //****************************************************************************** #define LED_OUT P1OUT #define LED_DIR P1DIR #define LED0_PIN BIT0 #define LED1_PIN BIT1 //****************************************************************************** // Example Commands ************************************************************ //****************************************************************************** #define SLAVE_ADDR 0x0B /* CMD_TYPE_X_SLAVE are example commands the master sends to the slave. * The slave will send example SlaveTypeX buffers in response. * * CMD_TYPE_X_MASTER are example commands the master sends to the slave. * The slave will initialize itself to receive MasterTypeX example buffers. * */ #define VOLTAGE_CMD 0x08 #define VOLTAGE_BUFFER_LENGTH 1 #define MAX_BUFFER_SIZE 20 /* MasterTypeX are example buffers initialized in the master, they will be * sent by the master to the slave. * SlaveTypeX are example buffers initialized in the slave, they will be * sent by the slave to the master. * */ uint8_t VoltageBuffer [VOLTAGE_BUFFER_LENGTH] = {8}; //****************************************************************************** // General I2C State Machine *************************************************** //****************************************************************************** typedef enum I2C_ModeEnum{ IDLE_MODE, NACK_MODE, TX_REG_ADDRESS_MODE, RX_REG_ADDRESS_MODE, TX_DATA_MODE, RX_DATA_MODE, SWITCH_TO_RX_MODE, SWITCH_TO_TX_MODE, TIMEOUT_MODE } I2C_Mode; /* Used to track the state of the software state machine*/ I2C_Mode SlaveMode = RX_REG_ADDRESS_MODE; /* The Register Address/Command to use*/ uint8_t ReceiveRegAddr = 0; /* ReceiveBuffer: Buffer used to receive data in the ISR * RXByteCtr: Number of bytes left to receive * ReceiveIndex: The index of the next byte to be received in ReceiveBuffer * TransmitBuffer: Buffer used to transmit data in the ISR * TXByteCtr: Number of bytes left to transfer * TransmitIndex: The index of the next byte to be transmitted in TransmitBuffer * */ uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t RXByteCtr = 0; uint8_t ReceiveIndex = 0; uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t TXByteCtr = 0; uint8_t TransmitIndex = 0; /* Initialized the software state machine according to the received cmd * * cmd: The command/register address received * */ void I2C_Slave_ProcessCMD(uint8_t cmd); /* The transaction between the slave and master is completed. Uses cmd * to do post transaction operations. (Place data from ReceiveBuffer * to the corresponding buffer based in the last received cmd) * * cmd: The command/register address corresponding to the completed * transaction */ void I2C_Slave_TransactionDone(uint8_t cmd); void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count); void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count) { uint8_t copyIndex = 0; for (copyIndex = 0; copyIndex < count; copyIndex++) { dest[copyIndex] = source[copyIndex]; } } void I2C_Slave_ProcessCMD(uint8_t cmd) { ReceiveIndex = 0; TransmitIndex = 0; RXByteCtr = 0; TXByteCtr = 0; switch (cmd) { case (VOLTAGE_CMD): SlaveMode = TX_DATA_MODE; TXByteCtr = VOLTAGE_BUFFER_LENGTH; //Fill out the TransmitBuffer CopyArray(VoltageBuffer, TransmitBuffer, VOLTAGE_BUFFER_LENGTH); UCB1IE &= ~UCRXIE; // Disable RX interrupt UCB1IE |= UCTXIE; // Enable TX interrupt break; default: __no_operation(); break; } } void I2C_Slave_TransactionDone(uint8_t cmd) { switch (cmd) { case (0x08): break; default: __no_operation(); break; } } //****************************************************************************** // Device Initialization ******************************************************* //****************************************************************************** void initGPIO() { //LEDs LED_DIR |= LED0_PIN | LED1_PIN; LED_OUT &= ~(LED0_PIN | LED1_PIN); // P1 setup for LED & reset output // I2C pins P5SEL0 |= BIT0 | BIT1; P5SEL1 &= ~(BIT0 | BIT1); // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; } void initI2C() { UCB1CTLW0 = UCSWRST; // Software reset enabled UCB1CTLW0 |= UCMODE_3 | UCSYNC; // I2C mode, sync mode UCB1I2COA0 = SLAVE_ADDR | UCOAEN; // Own Address and enable UCB1CTLW0 &= ~UCSWRST; // clear reset register UCB1IE |= UCRXIE + UCSTPIE; } void initClockTo16MHz() { // Configure one FRAM waitstate as required by the device datasheet for MCLK // operation beyond 8MHz _before_ configuring the clock system. FRCTL0 = FRCTLPW | NWAITS_1; // Clock System Setup CSCTL0_H = CSKEY_H; // Unlock CS registers CSCTL1 = DCOFSEL_0; // Set DCO to 1MHz // Set SMCLK = MCLK = DCO, ACLK = LFXTCLK (VLOCLK if unavailable) CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK; // Per Device Errata set divider to 4 before changing frequency to // prevent out of spec operation from overshoot transient CSCTL3 = DIVA__4 | DIVS__4 | DIVM__4; // Set all corresponding clk sources to divide by 4 for errata CSCTL1 = DCOFSEL_4 | DCORSEL; // Set DCO to 16MHz // Delay by ~10us to let DCO settle. 60 cycles = 20 cycles buffer + (10us / (1/4MHz)) __delay_cycles(60); CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // Set all dividers to 1 for 16MHz operation CSCTL0_H = 0; // Lock CS registers } //****************************************************************************** // Main ************************************************************************ // Enters LPM0 and waits for I2C interrupts. The data sent from the master is * // then interpreted and the device will respond accordingly * //****************************************************************************** int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer initClockTo16MHz(); initGPIO(); initI2C(); __bis_SR_register(LPM0_bits + GIE); return 0; } //****************************************************************************** // I2C Interrupt *************************************************************** //****************************************************************************** #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCI_B1_VECTOR __interrupt void USCI_B1_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_B1_VECTOR))) USCI_B1_ISR (void) #else #error Compiler not supported! #endif { //Must read from UCB1RXBUF uint8_t rx_val = 0; switch(__even_in_range(UCB1IV, 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 break; case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG case USCI_I2C_UCSTPIFG: UCB1IFG &= ~(UCTXIFG0); 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_val = UCB1RXBUF; switch (SlaveMode) { case (RX_REG_ADDRESS_MODE): ReceiveRegAddr = rx_val; I2C_Slave_ProcessCMD(ReceiveRegAddr); break; case (RX_DATA_MODE): ReceiveBuffer[ReceiveIndex++] = rx_val; RXByteCtr--; if (RXByteCtr == 0) { //Done Receiving MSG SlaveMode = RX_REG_ADDRESS_MODE; UCB1IE &= ~(UCTXIE); UCB1IE |= UCRXIE; // Enable RX interrupt I2C_Slave_TransactionDone(ReceiveRegAddr); } break; default: __no_operation(); break; } break; case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0 switch (SlaveMode) { case (TX_DATA_MODE): UCB1TXBUF = TransmitBuffer[TransmitIndex++]; TXByteCtr--; if (TXByteCtr == 0) { //Done Transmitting MSG SlaveMode = RX_REG_ADDRESS_MODE; UCB1IE &= ~(UCTXIE); UCB1IE |= UCRXIE; // Enable RX interrupt I2C_Slave_TransactionDone(ReceiveRegAddr); } break; default: __no_operation(); break; } break; // Interrupt Vector: I2C Mode: UCTXIFG default: break; } }
TIA!