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.

[参考译文] MSP430FR2676:在地址"0xc2d0e&quot 处中断、没有可用的调试信息、或者在程序代码之外。

Guru**** 2383970 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1230449/msp430fr2676-break-at-address-0xc2d0e-with-no-debug-information-available-or-outside-of-program-code

器件型号:MSP430FR2676

我会定期收到标题中显示的错误、我不确定是为什么。 它发生在我通过 I2C 从主机与 MSP430进行通信时、看起来像一个随机时间。 I2C 通信通常运行良好、直到我连续发送多个命令、然后 MSP430崩溃并出现此错误。 我已附上一些展示 I2C 通信接口的代码。

main 函数

/* --COPYRIGHT--,BSD
 * Copyright (c) 2017, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/
//*****************************************************************************
// Development main.c for MSP430FR2676 CapTIvate devices.
//
// This starter application initializes the CapTIvate touch library
// for the touch panel specified by CAPT_UserConfig.c/.h via a call to
// CAPT_appStart(), which initializes and calibrates all sensors in the
// application, and starts the CapTIvate interval timer.
//
// Then, the capacitive touch interface is driven by calling the CapTIvate
// application handler, CAPT_appHandler().  The application handler manages
// whether the user interface (UI) is running in full active scan mode, or
// in a low-power wake-on-proximity mode.
//
// \version 1.83.00.05
// Released on May 15, 2020
//
//*****************************************************************************

#include <msp430.h>                         // Generic MSP430 Device Include
#include "driverlib.h"                      // MSPWare Driver Library
#include "captivate.h"                      // CapTIvate Touch Software Library
#include "CAPT_App.h"                       // CapTIvate Application Code
#include "CAPT_BSP.h"                       // CapTIvate EVM Board Support Package
#include "drivers/als.h"                    // Ambient Light Sensor Library
#include "drivers/leds.h"                   // LED Library
#include "drivers/trh.h"                    // Temperature/Relative Humidity Sensor Library
#include "host_interface/host_interface.h"  // Host Interface Library
#include "system/timer.h"                   // Timer Library

void main(void)
{
    // Disable watchdog
    WDTCTL = WDTPW | WDTHOLD;

    // Initialize MCU and enable global interrupts
    BSP_configureMCU();
    __bis_SR_register(GIE);

    // Start the keypad CapTIvate application
    CAPT_appStart();

    // Start the LED driver
    LEDs_initialize();

    // Initialize the temperature/relative humidity sensor
    TRH_initialize();

    // Initialize the ambient light sensor
    //ALS_initialize();

    // Initialize the host interface
    HostInterface_initialize();

    //
    // Background Loop
    //
    while(1)
    {
        // Run the captivate application handler.
        CAPT_appHandler();

        // Update the timers
        Timer_update();

        // Update the LEDs
        LEDs_update();

        // Update the temperature/relative humidity sensor
        TRH_update();

        // Update the ALS
        //ALS_update();

        // Go to sleep if there is nothing left to do
        CAPT_appSleep();

    } // End background loop
} // End main()

SPI 接口

/*
 * @file      host_interface.c
 * @brief     Source file for the Cerberus CV25 interface.
 * @author    Eric Smith <eric.smith@brivo.com>
 * @copyright Brivo, Inc.
 * @date      2023
 */

//*****************************************************************************
// Includes
//*****************************************************************************

#include "CAPT_App.h"
#include "driverlib.h"
#include "drivers/als.h"
#include "drivers/leds.h"
#include "drivers/trh.h"
#include "I2CSlave.h"
#include "host_interface.h"

//*****************************************************************************
// Definitions
//*****************************************************************************

//*****************************************************************************
//
//! \def HOSTINTERFACE_I2C_ADDRESS defines the I2C slave address.
//!      Note that this is defined in I2CSlave_Definitions.h.
//
//*****************************************************************************
#define HOSTINTERFACE_I2C_ADDRESS                           (I2CSLAVE__ADDRESS)

//*****************************************************************************
//
//! \def These definitions define the registers of the host interface LEDs.
//
//*****************************************************************************
#define HOSTINTERFACE_REG_LED_OPERATION_MODE                             (0x00)
#define HOSTINTERFACE_REG_LED_KEYPAD_MODE                                (0x01)

//*****************************************************************************
//
//! \def HOSTINTERFACE_BUFFER_SIZE defines the I2C register buffer size.
//
//*****************************************************************************
#define HOSTINTERFACE_BUFFER_SIZE                                          (32)

//*****************************************************************************
//
//! \def HOSTINTERFACE_OVRHD_LENGTH defines the I2C packet overhead length.
//!      Includes sync, blank, and length bytes.
//
//*****************************************************************************
#define HOSTINTERFACE_OVRHD_LENGTH                                          (3)

//*****************************************************************************
//
//! \def HOSTINTERFACE_DATA_LENGTH defines the I2C packet data length.
//
//*****************************************************************************
#define HOSTINTERFACE_DATA_LENGTH                                           (6)

//*****************************************************************************
//
//! \def HOSTINTERFACE_CHKSUM_LENGTH defines the I2C packet checksum length.
//
//*****************************************************************************
#define HOSTINTERFACE_CHKSUM_LENGTH                                         (2)

//*****************************************************************************
//
//! \def HOSTINTERFACE_REG_OFFSET defines the offset of the I2C register.
//
//*****************************************************************************
#define HOSTINTERFACE_REG_OFFSET                                            (3)

//*****************************************************************************
//
//! \def HOSTINTERFACE_CMD_OFFSET defines the offset of the I2C command.
//
//*****************************************************************************
#define HOSTINTERFACE_CMD_OFFSET                                            (4)

//*****************************************************************************
//
//! \def HOSTINTERFACE_BSL_CMD_SIZE defines the size of the BSL command.
//!      The BSL command allows for a firmware update over I2C.
//
//*****************************************************************************
#define HOSTINTERFACE_BSL_CMD_SIZE                                          (8)

//*****************************************************************************
// Function Declarations
//*****************************************************************************

//! \brief  I2C slave receive callback function
//! \param  count   count of I2C message
//! \return true=>function exits active in I2C mode; false=>CPU returns to prev state
static bool HostInterface_ReceiveCallback(uint16_t count);

//*****************************************************************************
// Global Variables
//*****************************************************************************

//! \brief I2C slave data buffer
static uint8_t HostInterface_i2cDataBuffer[HOSTINTERFACE_BUFFER_SIZE];

//! \brief I2C slave handler
static const tI2CSlavePort HostInterface_handle = {
    .pbReceiveCallback = HostInterface_ReceiveCallback,
    .pvErrorCallback = 0,
    .pReceiveBuffer = (HostInterface_i2cDataBuffer + HOSTINTERFACE_OVRHD_LENGTH),
    .ui16ReceiveBufferSize = (HOSTINTERFACE_DATA_LENGTH + HOSTINTERFACE_CHKSUM_LENGTH),
    .bSendReadLengthFirst = false,
};

//*****************************************************************************
// Function Implementations
//*****************************************************************************

void HostInterface_initialize(void)
{
    // Set the host interrupt pin as an output
    GPIO_setAsOutputPin(HOST_IRQ_PORT, HOST_IRQ_PIN);

    // Open & Initialize the I2C Slave port
    I2CSlave_openPort(&HostInterface_handle);
    I2CSlave_setTransmitBuffer(
            (HostInterface_i2cDataBuffer + HOSTINTERFACE_OVRHD_LENGTH),
            (HOSTINTERFACE_BUFFER_SIZE - HOSTINTERFACE_OVRHD_LENGTH)
        );
}

bool HostInterface_ReceiveCallback(uint16_t count)
{
    // If there is no data sent, don't do anything
    if (count == 0)
    {
        return false;
    }
    // Register read command
    else if (count == 1)
    {
        uint8_t buffer;
        switch (HostInterface_i2cDataBuffer[HOSTINTERFACE_REG_OFFSET])
        {
			// TODO: Add read functions
            default:
                break;
        }
        // Only send a value if something was read
        if (buffer != NULL)
        {
            MAP_EUSCI_B_I2C_slavePutData(I2CSLAVE__EUSCI_B_PERIPHERAL, buffer);
        }
    }
    // Register write command
    else
    {
        uint8_t buffer = HostInterface_i2cDataBuffer[HOSTINTERFACE_CMD_OFFSET];
        switch (HostInterface_i2cDataBuffer[HOSTINTERFACE_REG_OFFSET])
        {
            case HOSTINTERFACE_REG_LED_OPERATION_MODE:
                LEDs_setFlag(LEDS_FLAG_OPERATION_MODE, buffer);
                break;
            case HOSTINTERFACE_REG_LED_KEYPAD_MODE:
                LEDs_setFlag(LEDS_FLAG_KEYPAD_MODE, buffer);
                break;
            default:
                break;
        }
    }

    // Return false to exit with the CPU in its previous state.
    // Since the response packet generation was handled immediately here,
    // there is no need to exit active.
    return false;
}

SPI 从器件驱动器(由 TI 自动生成)

/* --COPYRIGHT--,BSD
 * Copyright (c) 2017, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/
//*****************************************************************************
// I2CSlave.c
//
// \version 1.83.00.05
// Released on May 15, 2020
//
//*****************************************************************************
//*****************************************************************************
//! \addtogroup I2CSlave
//! @{
//*****************************************************************************

#include "I2CSlave.h"

#if (I2CSLAVE__ENABLE==true)

#if (I2CSLAVE__TIMEOUT_ENABLE==true)
#include "FunctionTimer.h"
#endif /* I2CSLAVE__TIMEOUT_ENABLE==true */

//*****************************************************************************
//
//! var g_pI2CSlavePort stores a pointer to the I2C slave port configuration
//! structure that was passed to the I2CSlave_openPort function.  The I2C
//! slave driver does not modify this structure.
//
//*****************************************************************************
const tI2CSlavePort *g_pI2CSlavePort;

//*****************************************************************************
//
//! var g_I2CSlaveConfiguration stores the MSP430 DriverLib EUSCI_B_I2C
//! configuration parameters for the EUSCI_B_I2C_initSlave() function call.
//
//*****************************************************************************
const EUSCI_B_I2C_initSlaveParam g_I2CSlaveConfiguration =
{
	.slaveAddress = I2CSLAVE__ADDRESS,
	.slaveAddressOffset = EUSCI_B_I2C_OWN_ADDRESS_OFFSET0,
	.slaveOwnAddressEnable = EUSCI_B_I2C_OWN_ADDRESS_ENABLE
};

//*****************************************************************************
//
//! var g_pI2CTransmitBuffer stores a pointer to the current transmit buffer.
//
//*****************************************************************************
const uint8_t *g_pI2CTransmitBuffer;

//*****************************************************************************
//
//! var g_ui16I2CLength stores the valid data length of the data pointed
//! to by g_pI2CTransmitBuffer.
//
//*****************************************************************************
uint16_t g_ui16I2CLength;

//*****************************************************************************
//
//! var g_ui16I2CIndex stores the current transmit or receive buffer index.
//
//*****************************************************************************
volatile uint16_t g_ui16I2CIndex;

//*****************************************************************************
//
//! var g_I2CSlaveStatus stores the current status of the I2C slave port.
//! possible options are enumerated in tI2CSlaveStates.
//
//*****************************************************************************
volatile uint8_t g_I2CSlaveStatus = eI2CSlaveIsClosed;

//*****************************************************************************
//
//! var g_bI2CSlaveRequestPending indicates whether or not a read
//! operation is currently pending on the I2C bus master.
//
//*****************************************************************************
volatile bool g_bI2CSlaveRequestPending;

//*****************************************************************************
//
//! This function is for private use only.  This is called by the I2C Slave
//! ISR when a receive (I2C write to this slave) operation is completed,
//! which is indicated either by a stop condition or a repeated start
//! condition.  This function handles receiving the last byte of data (if
//! present) and calling the receive callback in the user's application,
//! if one is registered.
//
//!  \par Parameters
//!		none
//! \return true if the ISR should exit active (per the callback), else false.
//
//*****************************************************************************
static bool I2CSlave_handleEndOfReceive(void);

#if (I2CSLAVE__TIMEOUT_ENABLE==true)

static bool I2CSlave_requestTimeoutHandler(void)
{
	//
	// If this function is called, the slave request to the master
	// has timed out.  This function cancels the request here
	// and notifies the application via the error callback.
	//
	g_bI2CSlaveRequestPending = false;
	if (g_pI2CSlavePort->pvErrorCallback != 0)
	{
		g_pI2CSlavePort->pvErrorCallback(eI2CSlaveTransmitRequestTimeout);
	}
	return true;
}

static bool I2CSlave_transactionTimeoutHandler(void)
{
	//
	// If this function is called, an I2C transaction with the master
	// has timed out.  This function resets the I2C port,
	// and notifies the application via the error callback.
	//
	I2CSlave_openPort(g_pI2CSlavePort);
	if (g_pI2CSlavePort->pvErrorCallback != 0)
	{
		g_pI2CSlavePort->pvErrorCallback(eI2CSlaveTransactionTimeout);
	}
	return true;
}

//*****************************************************************************
//
//! var g_I2CSlaveFunctionTimer contains the function timer configuration
//! for the two I2C timeout events-  a slave request timeout (Fxn A)
//! and an I2C transaction timeout (Fxn B)
//
//*****************************************************************************
const tFunctionTimer g_I2CSlaveFunctionTimer =
{
	.pbFunction_A = &I2CSlave_requestTimeoutHandler,
	.pbFunction_B = &I2CSlave_transactionTimeoutHandler,
	.ui16FunctionDelay_A = I2CSLAVE__REQ_TIMEOUT_CYCLES,
	.ui16FunctionDelay_B = I2CSLAVE__TXFR_TIMEOUT_CYCLES
};

#endif /* I2CSLAVE__TIMEOUT_ENABLE==true */

void I2CSlave_openPort(const tI2CSlavePort *pPort)
{
	I2CSlave_closePort();
	g_pI2CSlavePort = pPort;
	g_bI2CSlaveRequestPending = false;

#if (I2CSLAVE__TIMEOUT_ENABLE==true)
	Timer_startDelayedFunctionTimer(&g_I2CSlaveFunctionTimer);
#endif /* I2CSLAVE__TIMEOUT_ENABLE==true */

	MAP_EUSCI_B_I2C_initSlave(
			I2CSLAVE__EUSCI_B_PERIPHERAL,
			(EUSCI_B_I2C_initSlaveParam*)&g_I2CSlaveConfiguration
		);
	MAP_EUSCI_B_I2C_enable(I2CSLAVE__EUSCI_B_PERIPHERAL);
	MAP_EUSCI_B_I2C_clearInterrupt(I2CSLAVE__EUSCI_B_PERIPHERAL,I2CSLAVE__INT_MASK);
	MAP_EUSCI_B_I2C_enableInterrupt(I2CSLAVE__EUSCI_B_PERIPHERAL, I2CSLAVE__INT_MASK);

	I2C__INIT_REQ_SIGNAL;

	g_I2CSlaveStatus = eI2CSlaveIsIdle;
}


void I2CSlave_closePort(void)
{
	MAP_EUSCI_B_I2C_disable(I2CSLAVE__EUSCI_B_PERIPHERAL);
	g_I2CSlaveStatus = eI2CSlaveIsClosed;
#if (I2CSLAVE__TIMEOUT_ENABLE==true)
	Timer_stopDelayedFunctionTimer();
#endif /* I2CSLAVE__TIMEOUT_ENABLE==true */
}

uint8_t I2CSlave_getPortStatus(void)
{
	return g_I2CSlaveStatus;
}

void I2CSlave_setTransmitBuffer(uint8_t *pBuffer, uint16_t ui16Length)
{
	//
	// Before setting the transmit buffer, safely wait for
	// current read operations to finish
	//
#if (I2CSLAVE__LPMx_bits>0)
	while (1)
	{
		__bic_SR_register(GIE);
		if ((g_I2CSlaveStatus == eI2CSlaveIsBeingRead)
					|| (g_bI2CSlaveRequestPending==true))
		{
			__bis_SR_register(I2CSLAVE__LPMx_bits | GIE);
		}
		else
		{
			__bis_SR_register(GIE);
			break;
		}
	};
#else
	{
		while((g_I2CSlaveStatus == eI2CSlaveIsBeingRead)|| (g_bI2CSlaveRequestPending==true));
	}
#endif

	//
	// Update the transmit buffer and length.
	//
	g_ui16I2CLength = ui16Length;
	g_pI2CTransmitBuffer = pBuffer;
}

void I2CSlave_setRequestFlag(void)
{
	g_bI2CSlaveRequestPending = true;
	I2C__PULL_REQ_SIGNAL;

	//
	// If the slave timeout feature is enabled,
	// schedule a request flag timeout function
	//
#if (I2CSLAVE__TIMEOUT_ENABLE==true)
	Timer_scheduleDelayedFunction(eTimerDelayedFunction_A);
#endif /* I2CSLAVE__TIMEOUT_ENABLE==true */

	//
	// Before exiting the fxn,
	// safely wait for read operation
	// to begin before exiting
	//
#if (I2CSLAVE__LPMx_bits>0)
	while(1)
	{
		__bic_SR_register(GIE);
		if (g_bI2CSlaveRequestPending==true)
		{
			__bis_SR_register(I2CSLAVE__LPMx_bits | GIE);
		}
		else
		{
			__bis_SR_register(GIE);
			break;
		}
	}
#else
	while(g_bI2CSlaveRequestPending==true);
#endif

	//
	// If the slave timeout feature is enabled,
	// cancel the request flag timeout function
	// as transmission has begun.
	//
#if (I2CSLAVE__TIMEOUT_ENABLE==true)
			Timer_cancelDelayedFunction(eTimerDelayedFunction_A);
#endif /* I2CSLAVE__TIMEOUT_ENABLE==true */
	I2C__RELEASE_REQ_SIGNAL;
}

static bool I2CSlave_handleEndOfReceive(void)
{
	uint8_t ui8Data;

	//
	// Check for final received data byte in case start/stop interrupt is being serviced
	// before last rx interrupt due to MSP430 I2C interrupt priority
	//
	if(MAP_EUSCI_B_I2C_getInterruptStatus(I2CSLAVE__EUSCI_B_PERIPHERAL, EUSCI_B_I2C_RECEIVE_INTERRUPT0))
	{
		ui8Data = MAP_EUSCI_B_I2C_slaveGetData(I2CSLAVE__EUSCI_B_PERIPHERAL);
		if (g_ui16I2CIndex < g_pI2CSlavePort->ui16ReceiveBufferSize)
		{
			g_pI2CSlavePort->pReceiveBuffer[g_ui16I2CIndex++] = ui8Data;
		}
		MAP_EUSCI_B_I2C_clearInterrupt(I2CSLAVE__EUSCI_B_PERIPHERAL, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
	}

	//
	// Call receive callback if it exists
	//
	if (g_pI2CSlavePort->pbReceiveCallback != 0)
	{
		return g_pI2CSlavePort->pbReceiveCallback(g_ui16I2CIndex);
	}
	else
	{
		return false;
	}
}

#pragma vector=I2CSLAVE__EUSCI_VECTOR
__interrupt void I2CSlave_ISR(void)
{
	uint8_t ui8Data;

	switch (__even_in_range(I2CSLAVE__EUSCI_IV, USCI_I2C_UCTXIFG0))
	{
		case USCI_I2C_UCSTTIFG:
			//
			// Check for the repeated start case.  If this is a repeated start
			// and the previous operation was a write to this device,
			// handle the written (received) data.  If this is a first-time stard,
			// the previous I2C state is eI2CSlaveIsIdle.
			//
			if (g_I2CSlaveStatus == eI2CSlaveIsBeingWrittenTo)
			{
				if (I2CSlave_handleEndOfReceive() == true)
				{
					__bic_SR_register_on_exit(I2CSLAVE__LPMx_bits);
				}
			}

			//
			// Reset the I2C Index to zero to begin the new transaction.
			// Then check the I2C mode (read/write) to determine
			// the transaction mode.
			//
			g_ui16I2CIndex = 0;
			if (MAP_EUSCI_B_I2C_getMode(I2CSLAVE__EUSCI_B_PERIPHERAL)
					== EUSCI_B_I2C_TRANSMIT_MODE)
			{
				//
				// If this is a read operation (read from this device),
				// cancel the slave request flag and trigger and active
				// exit to alert the application that the flag has changed.
				//
				g_I2CSlaveStatus = eI2CSlaveIsBeingRead;
				g_bI2CSlaveRequestPending = false;
				__bic_SR_register_on_exit(I2CSLAVE__LPMx_bits);

				//
				// If the driver is set up to send the number of bytes to be read
				// before the rest of the buffer, load the number as the first data byte.
				// Otherwise, load the first byte of the transmit buffer into the peripheral.
				//
				if (g_pI2CSlavePort->bSendReadLengthFirst == true)
				{
					ui8Data = g_ui16I2CLength;
				}
				else
				{
					ui8Data = g_pI2CTransmitBuffer[g_ui16I2CIndex++];
				}
				MAP_EUSCI_B_I2C_slavePutData(
						I2CSLAVE__EUSCI_B_PERIPHERAL,
						ui8Data
					);
			}
			else
			{
				//
				// If this is a write operation (write from master to this device),
				// update the status accordingly and continue (no additional action is necessary).
				//
				g_I2CSlaveStatus = eI2CSlaveIsBeingWrittenTo;
			}

			//
			// If the slave timeout feature is enabled, schedule a
			// transaction timeout.
			//
#if (I2CSLAVE__TIMEOUT_ENABLE==true)
			Timer_scheduleDelayedFunction(eTimerDelayedFunction_B);
#endif /* I2CSLAVE__TIMEOUT_ENABLE==true */
			break;

		case USCI_I2C_UCSTPIFG:
			//
			// If the timeout feature is enabled, cancel
			// the transaction timeout as the operation
			// has finished successfully.
			//
#if (I2CSLAVE__TIMEOUT_ENABLE==true)
			Timer_cancelDelayedFunction(eTimerDelayedFunction_B);
#endif /* I2CSLAVE__TIMEOUT_ENABLE==true */


			if (g_I2CSlaveStatus == eI2CSlaveIsBeingWrittenTo)
			{
				//
				// If the operation that is ending was a write to this
				// device, handle the written (received) data, and exit
				// active if the callback function requested it.
				//
				if (I2CSlave_handleEndOfReceive() == true)
				{
					__bic_SR_register_on_exit(I2CSLAVE__LPMx_bits);
				}
			}
			else if (g_I2CSlaveStatus == eI2CSlaveIsBeingRead)
			{
				//
				// If the opreation that is ending was a read from this device,
				// exit active in case a transmit (read) buffer pointer update
				// was pending upon this read.
				//
				__bic_SR_register_on_exit(I2CSLAVE__LPMx_bits);
			}

			//
			// Set new status to idle, as the I2C transaction has stopped.
			//
			g_I2CSlaveStatus = eI2CSlaveIsIdle;
			break;

		case USCI_I2C_UCRXIFG0:
			//
			// Grab the received (written) byte from the I2C peripheral.
			// If there is receive buffer space left, store the received
			// byte in the receive buffer.  Otherwise, discard it and call
			// the error callback fxn if one is registered.
			//
			ui8Data = ROM_EUSCI_B_I2C_slaveGetData(I2CSLAVE__EUSCI_B_PERIPHERAL);
			if (g_ui16I2CIndex < g_pI2CSlavePort->ui16ReceiveBufferSize)
			{
				g_pI2CSlavePort->pReceiveBuffer[g_ui16I2CIndex++] = ui8Data;
			}
			else
			{
				if (g_pI2CSlavePort->pvErrorCallback != 0)
				{
					g_pI2CSlavePort->pvErrorCallback(eI2CSlaveReceiveBufferFull);
				}
			}
			break;

		case USCI_I2C_UCTXIFG0:
			//
			// If the transmit index is less than the length, there is still
			// valid data in the buffer.  Load the next byte.
			// Else, there is no valid data left in the buffer, so transmit
			// the invalid byte.
			//
			if (g_ui16I2CIndex<g_ui16I2CLength)
			{
				ui8Data = g_pI2CTransmitBuffer[g_ui16I2CIndex++];
			}
			else
			{
				ui8Data = I2CSLAVE__INVALID_BYTE;
				if (g_pI2CSlavePort->pvErrorCallback != 0)
				{
					g_pI2CSlavePort->pvErrorCallback(eI2CSlaveWasReadBeyondTransmitBuffer);
				}
			}
			MAP_EUSCI_B_I2C_slavePutData(I2CSLAVE__EUSCI_B_PERIPHERAL, ui8Data);
			break;
	}
}

#endif /* I2CSLAVE__ENABLE==true */

//*****************************************************************************
//! Close the doxygen group
//! @}
//*****************************************************************************

当我使用这段代码从主机向 MSP430发送"0x01 0x03"命令时、它会调用 HOSTINTERFACE_REG_LED_KEYPAD _MODE 情况。 它会更新标志以更改 LED、然后通过 main 中的 LEDS_UPDATE ()函数将其打开。 除非我连续发送多个命令、否则这通常效果很好。 当我连续发送多个命令时、会崩溃。 我是否不能很好地处理回调?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    除非我连续发送多个命令,否则这通常效果很好。

    我想看看你在这种情况下能说些什么。 您是否能够调试代码并检查从器件在 MCU 崩溃之前接收到多少数据。  

    此致、

    现金豪

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很抱歉这么晚才回复。 感谢您的答复。 经过更多的测试、它似乎是随机发生的。 有时、它仅发送一条命令后会崩溃。 有时、它会在连续发送多个命令后崩溃。 命令看起来没有区别。 我发送了很多不同的命令、但这始终会导致相同的问题。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    嗯、我现在没有更多线索。 您能否在调试模式下运行工程、尝试重现此问题并找出问题的原因? 您也可以在调试期间使用 View->Disassembly 函数来帮助您找到该函数。

    此致、

    现金豪

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    通过查看该器件的数据表、我发现此地址(0xC2D0E)位于 CapTIvate 库代码 ROM 中。 因此没有调试信息。

    通常、当此类错误弹出时、它是代码空间之外的地址、并且是由损坏的栈引起的。 在这种情况下、地址在已知代码内。 因此、这可能是您对库的使用中的一个问题。