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.

MSP430FR6928: AT24C256 interfacing with MSP430FR6928

Part Number: MSP430FR6928
Other Parts Discussed in Thread: MSP430FR6989

Hi,unable to generate the I2C interrupt while interfacing with at24c256 eeprom.

i refer the below code:

//******************************************************************************
// MSP430FR69xx Demo - eUSCI_B0, I2C Master multiple byte TX/RX
//
// Description: I2C master communicates to I2C slave sending and receiving
// 3 different messages of different length. I2C master will enter LPM0 mode
// while waiting for the messages to be sent/receiving using I2C interrupt.
// ACLK = NA, MCLK = SMCLK = DCO 16MHz.
//
// /|\ /|\
// MSP430FR6989 4.7k |
// ----------------- | 4.7k
// /|\ | P1.7|---+---|-- I2C Clock (UCB1SCL)
// | | | |
// ---|RST P1.6|-------+-- I2C Data (UCB1SDA)
// | |
// | |
// | |
// | |
// | |
// | |
//
// Nima Eskandari and Ryan Meredith
// Texas Instruments Inc.
// January 2018
// Built with CCS V7.3
//******************************************************************************

#include <msp430.h>
#include <stdint.h>
#include <stdbool.h>

//******************************************************************************
// Pin Config ******************************************************************
//******************************************************************************

#define LED_OUT P1OUT
#define LED_DIR P1DIR
#define LED0_PIN BIT0
#define LED1_PIN BIT1

//******************************************************************************
// Example Commands ************************************************************
//******************************************************************************

#define SLAVE_ADDR 0x05

/* 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 CMD_TYPE_0_SLAVE 0
#define CMD_TYPE_1_SLAVE 1
#define CMD_TYPE_2_SLAVE 2

#define CMD_TYPE_0_MASTER 3
#define CMD_TYPE_1_MASTER 4
#define CMD_TYPE_2_MASTER 5

#define TYPE_0_LENGTH 1
#define TYPE_1_LENGTH 2
#define TYPE_2_LENGTH 6

#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 MasterType2 [TYPE_2_LENGTH] = {'F', '4', '1', '9', '2', 'B'};
uint8_t MasterType1 [TYPE_1_LENGTH] = { 8, 9};
uint8_t MasterType0 [TYPE_0_LENGTH] = { 11};


uint8_t SlaveType2 [TYPE_2_LENGTH] = {0};
uint8_t SlaveType1 [TYPE_1_LENGTH] = {0};
uint8_t SlaveType0 [TYPE_0_LENGTH] = {0};

//******************************************************************************
// 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,
SWITHC_TO_TX_MODE,
TIMEOUT_MODE
} I2C_Mode;


/* Used to track the state of the software state machine*/
I2C_Mode MasterMode = IDLE_MODE;

/* The Register Address/Command to use*/
uint8_t TransmitRegAddr = 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;

/* I2C Write and Read Functions */

/* For slave device with dev_addr, writes the data specified in *reg_data
*
* dev_addr: The slave device address.
* Example: SLAVE_ADDR
* reg_addr: The register or command to send to the slave.
* Example: CMD_TYPE_0_MASTER
* *reg_data: The buffer to write
* Example: MasterType0
* count: The length of *reg_data
* Example: TYPE_0_LENGTH
* */
I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count);

/* For slave device with dev_addr, read the data specified in slaves reg_addr.
* The received data is available in ReceiveBuffer
*
* dev_addr: The slave device address.
* Example: SLAVE_ADDR
* reg_addr: The register or command to send to the slave.
* Example: CMD_TYPE_0_SLAVE
* count: The length of data to read
* Example: TYPE_0_LENGTH
* */
I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count);
void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);


I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count)
{
/* Initialize state machine */
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
RXByteCtr = count;
TXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;

/* Initialize slave address and interrupts */
UCB1I2CSA = dev_addr;
UCB1IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts
UCB1IE &= ~UCRXIE; // Disable RX interrupt
UCB1IE |= UCTXIE; // Enable TX interrupt

UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
//__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts

return MasterMode;

}


I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
{
/* Initialize state machine */
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;

//Copy register data to TransmitBuffer
CopyArray(reg_data, TransmitBuffer, count);

TXByteCtr = count;
RXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;

/* Initialize slave address and interrupts */
UCB1I2CSA = dev_addr;
UCB1IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts
UCB1IE &= ~UCRXIE; // Disable RX interrupt
UCB1IE |= UCTXIE; // Enable TX interrupt

UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition
//__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts

return MasterMode;
}

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];
}
}


//******************************************************************************
// Device Initialization *******************************************************
//******************************************************************************


void initGPIO()
{
// Configure GPIO
LED_OUT &= ~(LED0_PIN | LED1_PIN); // P1 setup for LED & reset output
LED_DIR |= (LED0_PIN | LED1_PIN);

// I2C pins
P3SEL0 |= BIT1 | BIT2;
P3SEL1 &= ~(BIT1 | BIT2);
P3DIR |=BIT0;
P3OUT &=~(BIT0);
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
}

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
}

void initI2C()
{
UCB1CTLW0 = UCSWRST; // Enable SW reset
UCB1CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSYNC; // I2C master mode, SMCLK
UCB1BRW = 160; // fSCL = SMCLK/160 = ~100kHz
UCB1I2CSA = SLAVE_ADDR; // Slave Address
UCB1CTLW0 &= ~UCSWRST; // Clear SW reset, resume operation
UCB1IE |= UCNACKIE;
}


//******************************************************************************
// Main ************************************************************************
// Send and receive three messages containing the example commands *************
//******************************************************************************

int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
initClockTo16MHz();
initGPIO();
initI2C();

I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_0_MASTER, MasterType0, TYPE_0_LENGTH);
I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_1_MASTER, MasterType1, TYPE_1_LENGTH);
I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_2_MASTER, MasterType2, TYPE_2_LENGTH);

I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_0_SLAVE, TYPE_0_LENGTH);
CopyArray(ReceiveBuffer, SlaveType0, TYPE_0_LENGTH);

I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_1_SLAVE, TYPE_1_LENGTH);
CopyArray(ReceiveBuffer, SlaveType1, TYPE_1_LENGTH);

I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_2_SLAVE, TYPE_2_LENGTH);
CopyArray(ReceiveBuffer, SlaveType2, TYPE_2_LENGTH);

//__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_B0_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: 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;
if (RXByteCtr)
{
ReceiveBuffer[ReceiveIndex++] = rx_val;
RXByteCtr--;
}

if (RXByteCtr == 1)
{
UCB1CTLW0 |= UCTXSTP;
}
else if (RXByteCtr == 0)
{
UCB1IE &= ~UCRXIE;
MasterMode = IDLE_MODE;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
break;
case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0
switch (MasterMode)
{
case TX_REG_ADDRESS_MODE:
UCB1TXBUF = TransmitRegAddr;
if (RXByteCtr)
MasterMode = SWITCH_TO_RX_MODE; // Need to start receiving now
else
MasterMode = TX_DATA_MODE; // Continue to transmision with the data in Transmit Buffer
break;

case SWITCH_TO_RX_MODE:
UCB1IE |= UCRXIE; // Enable RX interrupt
UCB1IE &= ~UCTXIE; // Disable TX interrupt
UCB1CTLW0 &= ~UCTR; // Switch to receiver
MasterMode = RX_DATA_MODE; // State state is to receive data
UCB1CTLW0 |= UCTXSTT; // Send repeated start
if (RXByteCtr == 1)
{
//Must send stop since this is the N-1 byte
while((UCB1CTLW0 & UCTXSTT));
UCB1CTLW0 |= UCTXSTP; // Send stop condition
}
break;

case TX_DATA_MODE:
if (TXByteCtr)
{
UCB1TXBUF = TransmitBuffer[TransmitIndex++];
TXByteCtr--;
}
else
{
//Done with transmission
UCB1CTLW0 |= UCTXSTP; // Send stop condition
MasterMode = IDLE_MODE;
UCB1IE &= ~UCTXIE; // disable TX interrupt
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
break;

default:
__no_operation();
break;
}
break;
default: break;
}
}

  • > //__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts

    This line enables your CPU for interrupts, so removing it (and the other two) means you'll never see any interrupts.

    The other thing it does is wait for completion of the transaction. If you don't do this, you'll circle back and (try to) start another transaction while the first is still running.

    I suggest you un-comment these lines.

    ----------------

    > #define SLAVE_ADDR 0x05

    As I read the data sheet (DOC0670 Rev T) Fig 7, this should be:

    > #define SLAVE_ADDR 0x50

    Depending on the board you're using, it could also be 0x51/0x52/0x53 [Ref Fig 7 again], but try this one first.

    ---------------

    > I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)

    More generally, read over data sheet p. 10 -- you'll need a uint16_t reg_addr, and you'll need to change the code to deal with this. The person in this other discussion seems to have figured it out (there are a few code versions in the thread):

    https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1172339/msp430fr5994-interfacing-issue/4417244

**Attention** This is a public forum