我正尝试将 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!