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.

RM48 I2C to EEPROM interface

Other Parts Discussed in Thread: HALCOGEN

Hello,

I need help with I2C interface on my Hercules RM48. Im trying to communicate with microchips 24LC64 EEPROM IC but I have no luck. For start Im tryng to write to I2C
I configured I2C in HALcoGen like:

  • add_mode-> 10bit
  • transmiter
  • bit count -> 8
  • data count -> 8


This is my write function:

uint32_t ee_i2c_write (uint16_t reg_adr, uint8_t * reg_data,
		uint16_t length)
{
	uint16_t delay;
	uint8_t data[40];
	data[0] = reg_adr >> 8;
	data[1] = reg_adr & 0xFF;
	uint8_t slave_addr = EEPROM_I2C_ADDR & 0xFE;

	if (EEPROM_PAGE_SIZE < length)
		return 0;

	memcpy(&data[2], reg_data, length);

	/* Configure address of Slave to talk to */
	i2cSetSlaveAdd(i2cREG1, slave_addr);

	/* Set direction to Transmitter */
	/* Note: Optional - It is done in Init */
	i2cSetDirection(i2cREG1, I2C_TRANSMITTER);

	/* Data Count + 1 ( Word Address) */
	i2cSetCount(i2cREG1, length + 1);

	/* Set mode as Master */
	i2cSetMode(i2cREG1, I2C_MASTER);

	/* Set Stop after programmed Count */
	i2cSetStop(i2cREG1);

	/* Transmit Start Condition */
    i2cSetStart(i2cREG1);

    /* Saw this in TI example */
    i2cSendByte(i2cREG1, 0x00);

	/* Set Stop after programmed Count */
    i2cSetStop(i2cREG1);

    /* Transmit Start Condition */
    i2cSetStart(i2cREG1);

	/* Tranmit DATA_COUNT number of data in Polling mode */
	i2cSend(i2cREG1, length, reg_data);

	/* Wait until Bus Busy is cleared */
	while(i2cIsBusBusy(i2cREG1) == true);

	/* Wait until Stop is detected */
	while(i2cIsStopDetected(i2cREG1) == 0);

	/* Clear the Stop condition */
	i2cClearSCD(i2cREG1);

	/* Depends on how quick the Slave gets ready */
	for(delay=0;delay<100000;delay++);

	return 1;
}


      
This are SDA and SCL signals that i get:

  • Hi Ivan,

    The SDA signal does not look ideal, but it should work. What is the value of the pull-up resistor on SCL and SDA lines? Below is the app note about calculating the pull-up resistor for I2C bus:

    https://www.ti.com/lit/pdf/slva689

  • Here is an example I developed for reading and writing RTC. Hope this is helpful to you:

    /** @file sys_main.c 
    *   @brief Application main file
    *   @date 28.Aug.2015
    *   @version 04.05.01
    *
    *   This file contains an empty main function,
    *   which can be used for the application.
    */
    
    /* 
    * Copyright (C) 2009-2015 Texas Instruments Incorporated - www.ti.com 
    * 
    * 
    *  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.
    *
    */
    
    
    /* USER CODE BEGIN (0) */
    /* USER CODE END */
    
    /* Include Files */
    
    #include "sys_common.h"
    
    /* USER CODE BEGIN (1) */
    #include "spi.h"
    #include "i2c.h"
    /* USER CODE END */
    
    /** @fn void main(void)
    *   @brief Application main function
    *   @note This function is empty by default.
    *
    *   This function is called after startup.
    *   The user can use this function to implement the application.
    */
    
    /* USER CODE BEGIN (2) */
    /* Variables for I2C Communication*/
    unsigned int pstatus=0x001;
    
    int I2C_Read_M(short Slave_Add, short Read_Add,
                   short Count,     uint8 *buff );
    
    int I2C_Write_M(short Slave_Add, short Read_Add,
                    short Count,     uint8 *buff );
    
    void delay(void) {
    	  static volatile uint32_t delayval;
    	  delayval = 10000;                     //100000 are about 10ms
    	  while(delayval--);
    }
    
    /* USER CODE END */
    
    void main(void)
    {
    	 int error,  Count, Register;
    
    	 short Slave_Addr  = 0x32;        // 0-1-1-0-0-1-0-R/W-A
    	 short Own_Addr    = 0x26;        // Define Master Own Address
    	 uint8 TxData[10]  = {
    	 	    		    	 0x18,
    	 					     0x26,
    		 				     0x12,
    	 					     0x10,
    	 					     0x14,
    							 0x04,
    							 0x16
    	 					 };
    	 uint8 RxData[10]  = {
    	                         0
    	                     };
    	 uint8 RxData1[10]  = {
    	                         0
    	                     };
    	 uint8 RxData2[10]  = {
    	                         0
    	                     };
    	 uint8 RxData3[10]  = {
    	                         0
    	                     };
    
    	 error = 0x00;
    
    	/* I2C Init as per GUI
    	 *  Mode = Master - Transmitter
    	 *  baud rate = 100KHz
    	 *  Count = 10
    	 *  Bit Count = 8bit
    	 */
    	 i2cInit();
    
    	 i2cSetOwnAdd(i2cREG1, Own_Addr);
    
    	 Register = 0x00;          // Select Configuration Register
    	 Count    = 0x07;
         delay();  //at least 61uS delay is required by RTC datasheet
    	 error = I2C_Write_M(Slave_Addr, Register, Count, TxData);
    
    	 Register = 0x00;         // 0x00/01//02//03 "second/min/hour/week/day/month/year" register
    	 Count    = 0x7;          // 4 bytes for week, day, month, year
         delay();  //at least 61uS delay is required by RTC datasheet
    	 error = I2C_Read_M(Slave_Addr, Register, Count, RxData);
    
         delay();  //at least 61uS delay is required by RTC datasheet
    	 error = I2C_Read_M(Slave_Addr, Register, Count, RxData1);
    
         delay();  //at least 61uS delay is required by RTC datasheet
    	 error = I2C_Read_M(Slave_Addr, Register, Count, RxData2);
    
         delay();  //at least 61uS delay is required by RTC datasheet
    	 error = I2C_Read_M(Slave_Addr, Register, Count, RxData3);
    
    	 if (error==0)
    		pstatus=0x000;
    	 else
    	 	pstatus=0x001;
    
    /* USER CODE END */
    }
    
    /* USER CODE BEGIN (4) */
    
    /* Read from a slave device */
    int I2C_Read_M(short Slave_Add, short Read_Add, short Count, uint8 *buff)
    {
    	int i, error, dummy;
    	error = 0;
    
        if((i2cREG1->STR & I2C_BUSBUSY ) == 0) //test if Busy is busy
        {
            /* Clear Stop bit */
            i2cREG1->MDR &= ~(I2C_STOP_COND);
            /* Clear Start bit */
            i2cREG1->MDR &= ~(I2C_START_COND);
            /* Clear Repeat mode bit */
            i2cREG1->MDR &= ~(I2C_REPEATMODE);
    
            /* Set direction to Transmitter */
            i2cSetDirection(i2cREG1, I2C_TRANSMITTER);
            /* Set mode as Master */
            i2cSetMode(i2cREG1, I2C_MASTER);
            /* Configure Data count */
            i2cSetCount(i2cREG1, 0x01);  //for 1-byte read address
    
            /* Configure address of Slave to talk to */
            i2cSetSlaveAdd(i2cREG1, Slave_Add);
    
            /* send the read address */
            i2cSendByte(i2cREG1, Read_Add);
    
            /* Start transmit*/
            i2cSetStart(i2cREG1);   //Start the transmission:
                                    //I2C Bus: Start--Slave Addr--Read Addr
    
            while( ((i2cREG1->STR & I2C_NACK) == 0) && ((i2cREG1->STR & I2C_ARDY) == 0) );
    
            if((i2cREG1->STR & I2C_NACK) == 0)  // Check for Positive Acknoledge
            {                                      // Application can continue
                /* Set mode as Master, and Receiver */
                i2cSetMode(i2cREG1, I2C_MASTER);         // Switch to Master Receiver
                i2cSetDirection(i2cREG1, I2C_RECEIVER);
                /* Set Repeat start mode */
                i2cREG1->MDR |= I2C_REPEATMODE;
    
                /* Start transmit*/
                i2cSetStart(i2cREG1);   //I2C BUS: Start--Slave Addr
    
                for (i=0; i<Count; i++)
                {
                     buff[i] = i2cReceiveByte(i2cREG1);  // Read incoming data and store in array
                     if (i == Count-2){
                        i2cSetStop(i2cREG1); //to generate a STOP
                     }
                }
            }
            else
            {
                dummy = i2cREG1->IVR;   // Clear nack flag
            	i2cSetStop(i2cREG1);    // to generate a STOP
            	error=-2;               // Set error as NoAck
            }
        }
        else{
        	error = -1; // Set error as Bus Busy
        }
    
        while((i2cREG1->MDR & I2C_STOP_COND) ==1);
    
        return error;
    }
    
    
    /* Write to a slave device */
    int I2C_Write_M(short Slave_Add, short Write_Add, short Count, uint8 *buff )
    {
    	int error, dummy;                 // Return code
        error = 0x00;                               // Default, no error
    
        if((i2cREG1->STR & I2C_BUSBUSY ) == 0) //test if Busy is busy
        {
            /* Set direction to Transmitter */
            i2cSetDirection(i2cREG1, I2C_TRANSMITTER);
            /* Set mode as Master */
            i2cSetMode(i2cREG1, I2C_MASTER);
    
            /* Clear Start bit */
            i2cREG1->MDR &= ~(I2C_START_COND);
    		/* Set Stop after programmed Count */
    		i2cSetStop(i2cREG1);
    
    		/* Clear RM bit */
    	    i2cREG1->MDR &= ~(I2C_REPEATMODE);   // Not in Repeat Mode
    
    	    /* Configure Data count */
    	    i2cSetCount(i2cREG1, Count+1);
    
            /* Configure address of Slave to talk to */
            i2cSetSlaveAdd(i2cREG1, Slave_Add);
    
    		/* Transmit Start Condition */
    		i2cSetStart(i2cREG1);         //I2C Bus: Start--Slave Addr
    
    	    /* send the write address */
    	    i2cSendByte(i2cREG1, Write_Add);  // Transmit data to Select Destination Register
    
    	    if((i2cREG1->STR & I2C_NACK) == 0)  // Check for Positive Acknoledge
    	    {
    			/* Tranmit DATA_COUNT number of data in Polling mode */
    			i2cSend(i2cREG1, Count, buff);
    	    }
    	    else{
                dummy = i2cREG1->IVR;   // Clear nack flag
            	i2cSetStop(i2cREG1);    // to generate a STOP
            	error=-2;               // Set error as NoAck
            }
        }
        else{
        	error = -1; // Set error as Bus Busy
        }
    
        while((i2cREG1->MDR & I2C_STOP_COND) ==1);
    
        return error;
    }
    
    /* USER CODE END */