S mani
S mani

Reputation: 1

C code for EEPROM read and write on I2C protocol in ATtiny402 using MPLAB X IDE - seeking guidance

Problem: I'm trying to embed C code in an ATtiny402 microcontroller using MPLAB X IDE for EEPROM read and write operations on the I2C protocol. However, I'm facing some issues with the implementation and would appreciate some assistance.

Context: I'm using MPLAB X IDE version 6.0.5 and programming the ATtiny402 microcontroller in C language. I'm specifically working with EEPROM read and write operations on the I2C protocol.

What I've tried: I have attempted a simple one-byte write and read operation from a 24c32 memory chip using an Attiny402 microcontroller, MPLAB X IDE, and Proteus software. While the write operation produced accurate output as seen in the I2C debugger, the read operation did not provide satisfactory results. I have previously asked this question three times and would appreciate a solution.Thank you for your assistance.

#include <xc.h>
#include <util/delay.h>
#define SDA_PIN 1
#define SCL_PIN 2
void i2c_addr_write(uint16_t);
void i2c_data_write(uint8_t);

int main(void) 
{
  main_init()  ;
  while(1)
  {
      main_loop();
  }
  return 0;  
}
void main_init(void)
{
    PORTA.DIRSET = (1 << SDA_PIN) | (1 << SCL_PIN);
    PORTA.PIN1CTRL &= ~PORT_PULLUPEN_bm;
    PORTA.PIN2CTRL &= ~PORT_PULLUPEN_bm;
    
    i2c_start();
    i2c_stop();
    i2c_start();
    i2c_data_write(0x00A0);
    i2c_addr_write(0x0001);
    i2c_data_write('C');
    i2c_stop();
    _delay_ms(1000);
      i2c_start();
      i2c_data_write(0x00A0);
      i2c_addr_write(0x0001);
      i2c_start();
      i2c_data_write(0x00A1); // send read command
      uint8_t data = i2c_data_read(); // read data
      data = data;
}
void main_loop(void)
{
    
}

void i2c_start(void)
{
    PORTA_OUT |= (1 << PIN1);
    _delay_us(4);
    PORTA_OUT |= (1 << PIN2);
        _delay_us(4);
     PORTA_OUT &= ~(1 << PIN1);
        _delay_us(4);
    PORTA_OUT &= ~(1 << PIN2) ;;
}
void i2c_stop(void)
{
    PORTA_OUT &= ~(1 << PIN2) ;
        _delay_us(4);
     PORTA_OUT &= ~(1 << PIN1);
        _delay_us(4);
    PORTA_OUT |= (1 << PIN2);
        _delay_us(4);
    PORTA_OUT |= (1 << PIN1); 
        _delay_us(4);
}
void i2c_addr_write(uint16_t addr)
{
    i2c_data_write((uint8_t)(addr >> 8));
    i2c_data_write((uint8_t)(addr & 0xFF));
}
void i2c_data_write(uint8_t data)
{
    for(uint8_t i=0;i<8;i++)
    {
        if(data & 0x80) 
        {
            PORTA_OUT |= (1 << PIN1);
        }
        else  PORTA_OUT &= ~(1 << PIN1);
        _delay_us(2);
        PORTA_OUT |= (1 << PIN2);
        _delay_us(2);
        PORTA_OUT &= ~(1 << PIN2) ;;
        data =data << 1;
    }
   PORTA_OUT |= (1 << PIN2) ;
   _delay_us(4); PORTA_DIRCLR =(1 << PIN1);
   while(PORTA_IN & (1 << PIN1));
   PORTA_DIRSET = (1 << PIN1);
   _delay_us(4);PORTA_OUT &= ~(1 << PIN2);
}
uint8_t i2c_data_read(void)
{
  uint8_t data = 0;
  
  PORTA_DIR &= ~(1 << PIN1);
  for (uint8_t i = 0; i < 8; i++) // read 8 bits
  {
    PORTA_OUT |= (1 << PIN2);
    _delay_us(8);
    data <<= 1;
    if (PORTA_IN & (1 << PIN1)) 
    { 
      data |= 0x01;
    }
    else  data |= 0x00;
     PORTA_OUT &= ~(1 << PIN2) ;
  }
  // Send ACK bit to EEPROM
    PORTA_DIR |= (1 << PIN1);
    PORTA_OUT &= ~(1 << PIN1);
    _delay_us(2);
    PORTA_OUT |= (1 << PIN2);
    _delay_us(2);
    PORTA_OUT &= ~(1 << PIN2) ;
    PORTA_OUT |= (1 << PIN1);
    _delay_us(2);
  // Send STOP bit to complete the read operation
  i2c_stop();
  return data;
}

Questions:

Is this code correct for EEPROM read and write operations on I2C protocol in ATtiny402 using MPLAB X IDE? If not, what changes should I make to the code to ensure it works correctly? Are there any specific guidelines or best practices I should follow when implementing EEPROM read and write operations on I2C protocol in ATtiny402 using MPLAB X IDE? I would appreciate any help or guidance on this issue. Thank you.

Upvotes: 0

Views: 1012

Answers (1)

AterLux
AterLux

Reputation: 4654

In i2c_data_read there is 8μS delay between SCK raising edge and falling edge, but no delay between falling and next rising edge: after PIN2 goes low, next cycle starts immediately and PIN2 goes high again.

Just add some delay in the end of the loop body.

Also I advice you to use open-drain approach, when dealing with I2C: configure output as low and only toggle DIR register, forcing line to go low, or letting pull-up resistor to rise it high. Otherwise there could be a situation, when the device trying to output low level, while MCU outputs high, causing short circuit and output gates overload.

Upvotes: 0

Related Questions