Reputation: 1
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
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