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.

MSP430F5659: Problems interfacing my processor with EEPROM 24LC16 via I2C

Part Number: MSP430F5659


Hi TI experts!

I was trying to establish a communication trough I2C protocol between my MSP430F5659 uP (MASTER) and 24LC16 EEPROM by Microchip.

My master has to write some data in the EEPROM and then all I want to do is to read these data previously written.

From what I can see on my scope it seems that the master and the slave are well linked and recognize each other (the slave ACKs when I send its address) but I notice some strange things:

  • as mentioned in 24LC16 EEPROM datasheet I have to send first the CONTROL BYTE (4 bits for device code, 3 bits for the blocks address and the R/W bit). If I write the control byte following this pattern I have to send 1010 000 0 --> device code, block 0, write operation but, if I do that the slave doesn't sent the ACK. So I tried to invert the address and if I send 0101 0000 the slave recognizes its address and sends the ACK. Why is this happen?
  • I read both MSP430F5659 and 24LC16 datasheets about reading operation but, even if I'm pretty sure to follow what these datasheets suggest to do, I'm not able to read my EEPROM at the desired address. I'm a bit confused about  where I have to put the specific memory address from which I want to read data.

So, to give you a better understanding of what I 'm talking about, I attach my I2C dedicated code.

Any advice and help would be really appreciated.

 Kind Regards,

Luigi

I2CBUS.H

//---------------- ROUTINE DI I2CBUS --------------
//BUFFER_I2C_TX	DS	32	// BUFFER DI TRASMISSIONE SU I2CBUS 
//BUFFER_I2C_RX	DS	32	// BUFFER DI RICEZIONE SU I2CBUS 



#define	I2SPEED_380KHZ		32	// INDIRIZZO DEL DISPOSITIVO + MODALIT� SCRITTURA 
#define	I2SPEED_100KHZ		153	// INDIRIZZO DEL DISPOSITIVO + MODALIT� SCRITTURA 
#define	I2SPEED_78KHZ		200	// INDIRIZZO DEL DISPOSITIVO + MODALIT� SCRITTURA 

// comunicazione i2c 
#define	DRV10983_ADDRESS	01010010B	// INDIRIZZO DEL DISPOSITIVO + MODALIT� SCRITTURA 
#define	SCRIVI_SPEED_CONTROL_1	0	// INDIRIZZO DELLO CONTROLLO DI VELOCIT� 1 
#define	SCRIVI_SPEED_CONTROL_2	1	// INDIRIZZO DELLO CONTROLLO DI VELOCIT� 1 
#define	SCRIVI_SPEED_OVERIDE	10000001B
#define	ADDRESS_EEPROM_CONTROL	03H	// INDIRIZZO EEPROM CONTROL
#define	ENABLE_SIDATA		01000000B	// 40 SIDATA PE ENABLE SCRITTURA REGISTRI 
#define	MotorSpeed1		011H
#define	MotorSpeed2		012H
#define	MotorPeriod1		013H
#define	MotorPeriod2		014H

//#define	SCRIVI_DRV10983	10100100B	// INDIRIZZO DEL DISPOSITIVO + MODALIT� SCRITTURA 
//#define	LEGGI_DRV10983	10100101B	// INDIRIZZO DEL DISPOSITIVO + MODALIT� SCRITTURA 

#define	SCRIVI_DRV10983	01010010B	// SBAGLIATO 
#define	LEGGI_DRV10983	01010011B	// SLAGLIATO

#define	LEGGI_SPEED_2		012H	// LEGGE LA VELOCIT� REGISTRO 2 
#define	LEGGI_SUPPLY_VOLTAGE	019H	//  
#define R_W_BIT 		00000001B	// IL BIT 0 HA LA FUNZIONE DI READ / WRITE BIT READ = 1 ; WRITE=0


//#define	READ_EEPROM	10100001B	// indirizzo eeprom e codice di lettura 
//#define	WRITE_EEPROM	10100000B	// indirizzo eeprom e codice di SCRITTURA
#define	ADDRESS_DEFAULT	00000010B	// indirizzo eeprom e codice di SCRITTURA

#define	WRITE_EEPROM	01010000B	// SBAGLIATI 
#define	READ_EEPROM	01010001B	// indirizzo eeprom e codice di lettura 

VAI_I2C	
	JSR	ANALOGICHE
	MOV.W	#13,BYTE_NUMBER								// number of write byte 
	MOV.W	#WRITE_EEPROM,SLAVE_ADDRESS	// slave address 
	MOV.W	#I2SPEED_100KHZ,I2C_SPEED	// PRESCALER  
	JSR	INIZIALIZZA_I2C	// inizialization of i2cbus 
	MOV.W	#0,INDIRIZZO_DATI	// index of pointer reading into the slave 
	MOV.B	#20,BUFFER_I2C_TX
  	MOV.B	#21,BUFFER_I2C_TX+1	    // some test writing byte 	
	MOV.B	#22,BUFFER_I2C_TX+2
  	MOV.B	#23,BUFFER_I2C_TX+3	    
  	MOV.B	#24,BUFFER_I2C_TX+4	  
  	MOV.B	#25,BUFFER_I2C_TX+5	  
	MOV.B	#26,BUFFER_I2C_TX+6
  	MOV.B	#27,BUFFER_I2C_TX+7	    
	MOV.B	#28,BUFFER_I2C_TX+8
  	MOV.B	#29,BUFFER_I2C_TX+9	    
  	MOV.B	#30,BUFFER_I2C_TX+10	  
  	
	JSR	SCRIVI_I2CBUS	// go to writing op on  i2c bus 
  
	JSR	DELAY_200mS 
	
	MOV.W	#13,BYTE_NUMBER	// number of  reading byte 
	MOV.W	#READ_EEPROM,SLAVE_ADDRESS	// slave address 
	MOV.W	#I2SPEED_100KHZ,I2C_SPEED	// PRESCALER 
	JSR	INIZIALIZZA_I2C	// VA AD INIZZAILIZZARE LA I2CBUS   
	MOV.W	#0,INDIRIZZO_DATI	// index of pointer reading into the slave 
	JSR	LEGGI_I2CBUS
  	
	JSR	DELAY_200mS   
	SALTA	VAI_I2C		// macro Br 
	

	    
INIZIALIZZA_I2C:
	BSET_W	UCSWRST,UCB0CTLW0	// BLOCCA LA I2C E PERMETTE I SETTAGGI 
	BSET_W	(UCMODE_3+UCMST+UCSYNC),UCB0CTLW0		// sincronizzato al timer b usync gi� settato 
	MOV.W	I2C_SPEED,UCB0BRW	  
	BSET_W	UCASTP_2,UCB0CTLW1	// GENERAZIONE AUTOMATICA DEL BIT DI STOP 
	MOV.W	BYTE_NUMBER,UCB0TBCNT	// NUMERO DI BYTE DA RICEVERE 
	MOV.W	SLAVE_ADDRESS,UCB0I2CSA	// INDIRIZZO DEL DISPOSITIVO SLAVE 
	BCLR_W	UCSWRST,UCB0CTLW0	// SBLOCCA LA TRASMISSIONE 
	RTS


// ***************** write on the slave 
SCRIVI_I2CBUS:	
  	BSET_W	UCTR,UCB0CTLW0	// TRANSMIT MODE
	NOP
	BSET_W	UCTXSTT,UCB0CTLW0	// START BIT 
WAIT_TRASM0:
  	NOP
	BRSET_W	UCTXSTT,UCB0CTLW0,WAIT_TRASM0	 
WAIT_TRASM:	
  	NOP
	BRCLR_W	UCTXIFG0,UCB0IFG,WAIT_TRASM	
	MOV.W	INDIRIZZO_DATI,UCB0TXBUF	// index of pointer reading into the slave  
	PUSH.W	R4
	PUSH.W	R5  
	PUSH.W	R6    
	MOV.W	#BUFFER_I2C_TX,R5
	ADD.W	BYTE_NUMBER,R5  
	MOV.W	#BUFFER_I2C_TX,R4
WAIT_TRASM1:	
	NOP
	BRSET_W	UCNACKIFG,UCB0IFG,END_COUNTER	// SE NON RICEVE L'ACK INVIA STOP_CONDITION 
	BRSET_W	UCBCNTIFG,UCB0IFG,END_COUNTER  	// SE ARRIVA ALLA FINE DELLA TRASMISSIONE 
  	BRCLR_W	UCTXIFG0,UCB0IFG,WAIT_TRASM1	
	NOP
	MOV.B	0(R4),R6
	MOV.W	R6,UCB0TXBUF	// NEXT SENDING 
	INC.W	R4
	CMP.W	R5,R4
	JLO	WAIT_TRASM1	  
	JEQ	WAIT_TRASM1
	SALTA	END_COUNTER   
	  

//*********** QUI VA A LEGGERE IL DISPOSITIVO *********************
LEGGI_I2CBUS:
  	BSET_W	UCTR,UCB0CTLW0	// TRANSMIT MODE
	NOP
	BSET_W	UCTXSTT,UCB0CTLW0	// START BIT 
WAIT_RECEIVE:	
  	NOP
	
WAIT_TRASM_01:	
	NOP
	BRSET_W	UCTXSTT,UCB0CTLW0,WAIT_RECEIVE  // WAIT FOR START BIT END 
	BRCLR_W	UCTXIFG0,UCB0IFG,WAIT_TRASM_01	// WAIT FOR BUFFER FREE 
   
	MOV.W	INDIRIZZO_DATI,UCB0TXBUF	// index of pointer reading into the slave   
	PUSH.W	R4
	PUSH.W	R5  
	PUSH.W	R6    
	MOV.W	#BUFFER_I2C_RX,R5	
	ADD.W	BYTE_NUMBER,R5  
	MOV.W	#BUFFER_I2C_RX,R4
WAIT_TRASM_0:	
	NOP
	BRCLR_W	UCTXIFG0,UCB0IFG,WAIT_TRASM_0	
	BCLR_W	UCTR,UCB0CTLW0	// RECIEVE MODE SETTING 
	NOP
	NOP  
	BSET_W	UCTXSTT,UCB0CTLW0	// START BIT FOR RECEIVING 
WAIT_RECEIVE_ST:	
	NOP
	BRSET_W	UCTXSTT,UCB0CTLW0,WAIT_RECEIVE_ST  // FINCH� LO START BIT NON � A ZERO 
WAIT_RECEIVE_1:	
	NOP
	BRSET_W	UCBCNTIFG,UCB0IFG,END_COUNTER  
	BRCLR_W	UCRXIFG0,UCB0IFG,WAIT_RECEIVE_1
	NOP
	MOV.W	UCB0RXBUF,R6	// NECT RECEIVING BYTE 
	MOV.B	R6,0(R4)
	INC.W	R4
	CMP.W	R5,R4
	JLO	WAIT_RECEIVE_1	  
	JEQ	WAIT_RECEIVE_1	  
END_COUNTER:
	POP.W	R6
	POP.W	R5
	POP.W	R4  
	BSET_W	UCTXSTP,UCB0CTLW0	  // FORCE A STOP BIT 
	RTS
	 
  • Hello Luigi,

    I don't really have a good explanation yet for why the slave responds to the inverted command. Also, I see that you're using assembly code, which is much more difficult to read through and debug than C code. Are you required to use assembly? If not, I would highly recommend switching to C code.

    That being said, I tried my best to look through your attached assembly code. By comparing it with our I2C master C code example, I noticed that:

    1. You're initializing the I2C module twice
    2. You're not enabling TX or RX interrupts and may be polling rather than using interrupts
    3. I didn't see any port/pin configuration for I2C functionality (assuming this code just wasn't included)
    4. I didn't see the watchdog timer (WDT) stopped or DCO/SMCLK/MCLK configured

    This was just my feedback, so please take some time to review or use the following code example.

    msp430f665x_usci_i2c_standard_master.c

    //******************************************************************************

    //   MSP430F665x 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.
    //
    //                                     /|\ /|\
    //                   MSP430F6659       4.7k |
    //                 -----------------    |  4.7k
    //            /|\ |             P2.1|---+---|-- I2C Clock (UCB0SCL)
    //             |  |                 |       |
    //             ---|RST          P2.0|-------+-- I2C Data (UCB0SDA)
    //                |                 |
    //                |                 |
    //                |                 |
    //                |                 |
    //                |                 |
    //                |                 |
    //
    //   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 LED_PIN     BIT0
    
    //******************************************************************************
    // Example Commands ************************************************************
    //******************************************************************************
    
    #define SLAVE_ADDR  0x48
    
    /* 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 */
        UCB0I2CSA = dev_addr;
        UCB0IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
        UCB0IE &= ~UCRXIE;                       // Disable RX interrupt
        UCB0IE |= UCTXIE;                        // Enable TX interrupt
    
        UCB0CTL1 |= 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 */
        UCB0I2CSA = dev_addr;
        UCB0IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
        UCB0IE &= ~UCRXIE;                       // Disable RX interrupt
        UCB0IE |= UCTXIE;                        // Enable TX interrupt
    
        UCB0CTL1 |= 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 initClockTo16MHz()
    {
        UCSCTL3 |= SELREF_2;                      // Set DCO FLL reference = REFO
        UCSCTL4 |= SELA_2;                        // Set ACLK = REFO
        __bis_SR_register(SCG0);                  // Disable the FLL control loop
        UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
        UCSCTL1 = DCORSEL_5;                      // Select DCO range 16MHz operation
        UCSCTL2 = FLLD_0 + 487;                   // Set DCO Multiplier for 16MHz
                                                  // (N + 1) * FLLRef = Fdco
                                                  // (487 + 1) * 32768 = 16MHz
                                                  // Set FLL Div = fDCOCLK
        __bic_SR_register(SCG0);                  // Enable the FLL control loop
    
        // Worst-case settling time for the DCO when the DCO range bits have been
        // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
        // UG for optimization.
        // 32 x 32 x 16 MHz / 32,768 Hz = 500000 = MCLK cycles for DCO to settle
        __delay_cycles(500000);//
        // Loop until XT1,XT2 & DCO fault flag is cleared
        do
        {
            UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags
            SFRIFG1 &= ~OFIFG;                          // Clear fault flags
        }while (SFRIFG1&OFIFG);                         // Test oscillator fault flag
    }
    
    uint16_t setVCoreUp(uint8_t level){
        uint32_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;
    
        //The code flow for increasing the Vcore has been altered to work around
        //the erratum FLASH37.
        //Please refer to the Errata sheet to know if a specific device is affected
        //DO NOT ALTER THIS FUNCTION
    
        //Open PMM registers for write access
        PMMCTL0_H = 0xA5;
    
        //Disable dedicated Interrupts
        //Backup all registers
        PMMRIE_backup = PMMRIE;
        PMMRIE &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE |
                    SVSLPE | SVMHVLRIE | SVMHIE |
                    SVSMHDLYIE | SVMLVLRIE | SVMLIE |
                    SVSMLDLYIE
                    );
        SVSMHCTL_backup = SVSMHCTL;
        SVSMLCTL_backup = SVSMLCTL;
    
        //Clear flags
        PMMIFG = 0;
    
        //Set SVM highside to new level and check if a VCore increase is possible
        SVSMHCTL = SVMHE | SVSHE | (SVSMHRRL0 * level);
    
        //Wait until SVM highside is settled
        while((PMMIFG & SVSMHDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        PMMIFG &= ~SVSMHDLYIFG;
    
        //Check if a VCore increase is possible
        if((PMMIFG & SVMHIFG) == SVMHIFG)
        {
            //-> Vcc is too low for a Vcore increase
            //recover the previous settings
            PMMIFG &= ~SVSMHDLYIFG;
            SVSMHCTL = SVSMHCTL_backup;
    
            //Wait until SVM highside is settled
            while((PMMIFG & SVSMHDLYIFG) == 0)
            {
                ;
            }
    
            //Clear all Flags
            PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
                         SVMLVLRIFG | SVMLIFG |
                         SVSMLDLYIFG
                         );
    
            //Restore PMM interrupt enable register
            PMMRIE = PMMRIE_backup;
            //Lock PMM registers for write access
            PMMCTL0_H = 0x00;
            //return: voltage not set
            return false;
        }
    
        //Set also SVS highside to new level
        //Vcc is high enough for a Vcore increase
        SVSMHCTL |= (SVSHRVL0 * level);
    
        //Wait until SVM highside is settled
        while((PMMIFG & SVSMHDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        PMMIFG &= ~SVSMHDLYIFG;
    
        //Set VCore to new level
        PMMCTL0_L = PMMCOREV0 * level;
    
        //Set SVM, SVS low side to new level
        SVSMLCTL = SVMLE | (SVSMLRRL0 * level) |
                   SVSLE | (SVSLRVL0 * level);
    
        //Wait until SVM, SVS low side is settled
        while((PMMIFG & SVSMLDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        PMMIFG &= ~SVSMLDLYIFG;
        //SVS, SVM core and high side are now set to protect for the new core level
    
        //Restore Low side settings
        //Clear all other bits _except_ level settings
        SVSMLCTL &= (SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 +
                     SVSMLRRL1 + SVSMLRRL2
                     );
    
        //Clear level settings in the backup register,keep all other bits
        SVSMLCTL_backup &=
            ~(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);
    
        //Restore low-side SVS monitor settings
        SVSMLCTL |= SVSMLCTL_backup;
    
        //Restore High side settings
        //Clear all other bits except level settings
        SVSMHCTL &= (SVSHRVL0 + SVSHRVL1 +
                     SVSMHRRL0 + SVSMHRRL1 +
                     SVSMHRRL2
                     );
    
        //Clear level settings in the backup register,keep all other bits
        SVSMHCTL_backup &=
            ~(SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);
    
        //Restore backup
        SVSMHCTL |= SVSMHCTL_backup;
    
        //Wait until high side, low side settled
        while(((PMMIFG & SVSMLDLYIFG) == 0) &&
              ((PMMIFG & SVSMHDLYIFG) == 0))
        {
            ;
        }
    
        //Clear all Flags
        PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
                    SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG
                    );
    
        //Restore PMM interrupt enable register
        PMMRIE = PMMRIE_backup;
    
        //Lock PMM registers for write access
        PMMCTL0_H = 0x00;
    
        return true;
    }
    
    bool increaseVCoreToLevel2()
    {
        uint8_t level = 2;
        uint8_t actlevel;
        bool status = true;
    
        //Set Mask for Max. level
        level &= PMMCOREV_3;
    
        //Get actual VCore
        actlevel = PMMCTL0 & PMMCOREV_3;
    
        //step by step increase or decrease
        while((level != actlevel) && (status == true))
        {
            if(level > actlevel)
            {
                status = setVCoreUp(++actlevel);
            }
        }
    
        return (status);
    }
    
    void initGPIO()
    {
        //LEDs
        LED_OUT &= ~LED_PIN; // P1 setup for LED & reset output
        LED_DIR |= LED_PIN;
    
        // Disable Interrupts before altering Port Mapping registers
        __disable_interrupt();
        // Enable Write-access to modify port mapping registers
        PMAPPWD = 0x02D52;
    
        //I2C Pins
        P2SEL |= BIT0 | BIT1;
        P2MAP0 = PM_UCB0SDA;
        P2MAP1 = PM_UCB0SCL;
    
        // Disable Write-Access to modify port mapping registers
        PMAPPWD = 0;
    }
    
    void initI2C()
    {
        UCB0CTL1 |= UCSWRST;                      // Enable SW reset
        UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
        UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
        UCB0BR0 = 160;                            // fSCL = SMCLK/160 = ~100kHz
        UCB0BR1 = 0;
        UCB0I2CSA = SLAVE_ADDR;                   // Slave Address is 048h
        UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
        UCB0IE |= UCNACKIE;
    }
    
    //******************************************************************************
    // Main ************************************************************************
    // Send and receive three messages containing the example commands *************
    //******************************************************************************
    
    int main(void) {
    
        WDTCTL = WDTPW | WDTHOLD;                 // Stop watchdog timer
    
        increaseVCoreToLevel2();
        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_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
    {
      //Must read from UCB0RXBUF
      uint8_t rx_val = 0;
    
      switch(__even_in_range(UCB0IV,0xC))
      {
        case USCI_NONE:break;                             // Vector 0 - no interrupt
        case USCI_I2C_UCALIFG:break;                      // Interrupt Vector: I2C Mode: UCALIFG
        case USCI_I2C_UCNACKIFG:break;                    // Interrupt Vector: I2C Mode: UCNACKIFG
        case USCI_I2C_UCSTTIFG:break;                     // Interrupt Vector: I2C Mode: UCSTTIFG
        case USCI_I2C_UCSTPIFG:break;                     // Interrupt Vector: I2C Mode: UCSTPIFG
        case USCI_I2C_UCRXIFG:
            rx_val = UCB0RXBUF;
            if (RXByteCtr)
            {
              ReceiveBuffer[ReceiveIndex++] = rx_val;
              RXByteCtr--;
            }
    
            if (RXByteCtr == 1)
            {
              UCB0CTL1 |= UCTXSTP;
            }
            else if (RXByteCtr == 0)
            {
              UCB0IE &= ~UCRXIE;
              MasterMode = IDLE_MODE;
              __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
            }
            break;                      // Interrupt Vector: I2C Mode: UCRXIFG
        case USCI_I2C_UCTXIFG:
            switch (MasterMode)
            {
              case TX_REG_ADDRESS_MODE:
                  UCB0TXBUF = TransmitRegAddr;
                  if (RXByteCtr)
                      MasterMode = SWITCH_TO_RX_MODE;   // Need to start receiving now
                  else
                      MasterMode = TX_DATA_MODE;        // Continue to transmission with the data in Transmit Buffer
                  break;
    
              case SWITCH_TO_RX_MODE:
                  UCB0IE |= UCRXIE;              // Enable RX interrupt
                  UCB0IE &= ~UCTXIE;             // Disable TX interrupt
                  UCB0CTL1 &= ~UCTR;            // Switch to receiver
                  MasterMode = RX_DATA_MODE;    // State state is to receive data
                  UCB0CTL1 |= UCTXSTT;          // Send repeated start
                  if (RXByteCtr == 1)
                  {
                      //Must send stop since this is the N-1 byte
                      while((UCB0CTL1 & UCTXSTT));
                      UCB0CTL1 |= UCTXSTP;      // Send stop condition
                  }
                  break;
    
              case TX_DATA_MODE:
                  if (TXByteCtr)
                  {
                      UCB0TXBUF = TransmitBuffer[TransmitIndex++];
                      TXByteCtr--;
                  }
                  else
                  {
                      //Done with transmission
                      UCB0CTL1 |= UCTXSTP;     // Send stop condition
                      MasterMode = IDLE_MODE;
                      UCB0IE &= ~UCTXIE;                       // disable TX interrupt
                      __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
                  }
                  break;
    
              default:
                  __no_operation();
                  break;
            }
            break;                      // Interrupt Vector: I2C Mode: UCTXIFG
        default: break;
      }
    }

  • > #define WRITE_EEPROM 01010000B // SBAGLIATI
    > #define READ_EEPROM 01010001B // indirizzo eeprom e codice di lettura

    The R/W bit is not part of the address in I2CSA, and I2CSA is stored right-justified (which is why it looks like 01010 rather than 1010). The R/W bit is appended by the I2C unit based on the UCTR setting.

    Corollary: you have to change I2CSA (low 3 bits) based on which 256-byte block you're referencing.
  • Hi James!

    Thank you very much for your precious feedback!

    As you highlight you couldn't see the initialization of port/pins and WDT/Clock System because I only attached the source file related with I2C routine. These configurations are in other files of my project.

    However it seems that the issue was related with the double initialization of I2C module... So thanks a lot for your comments, they really help us finding the problem!

    I will also take some time to study and analize your C example, and maybe switch this I2C routine to C language.

    Thank you also to Bruce McKenney for your simple and clear explanation.

    Kind Regards,

    Luigi

**Attention** This is a public forum