使用MPLAB X IDE在ATtiny 402中的I2C协议上进行EEPROM读写的C代码-寻求指导

iqxoj9l9  于 2023-03-17  发布在  其他
关注(0)|答案(1)|浏览(268)

问题:我正尝试使用MPLAB X IDE在ATtiny402微控制器中嵌入C代码,以便根据I2C协议执行EEPROM读写操作。但是,我在实现过程中遇到了一些问题,希望您能提供帮助。
上下文:我使用MPLAB X IDE版本6.0.5,并使用C语言对ATtiny402微控制器进行编程。我专门处理I2C协议上的EEPROM读写操作。
我尝试过的:我曾尝试使用Attiny402微控制器、MPLAB X IDE和Proteus软件对24c32存储器芯片执行简单的单字节读写操作。虽然写操作产生了I2C调试器中所见的准确输出,但读操作并未提供令人满意的结果。我之前已问过三次此问题,希望您能提供解决方案。谢谢您的帮助。

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

问题:
对于使用MPLAB X IDE的ATtiny402中I2C协议的EEPROM读写操作,此代码是否正确?如果不正确,我应该对代码进行哪些更改以确保其正常工作?使用MPLAB X IDE在ATtiny402中对I2C协议执行EEPROM读写操作时,我应该遵循哪些具体的指导原则或最佳实践?我将非常感谢有关此问题的任何帮助或指导。谢谢你。

yfjy0ee7

yfjy0ee71#

i2c_data_read中,SCK上升沿和下降沿之间有8μS延迟,但下降沿和下一个上升沿之间没有延迟:在PIN2变低之后,下一个周期立即开始,并且PIN2再次变高。
只需在循环体的末尾添加一些延迟。
此外,我建议您在处理I2C时使用开漏方法:将输出配置为low并仅切换DIR寄存器,强制线路变为低电平,或让上拉电阻将其升高。否则,可能会出现以下情况:当MCU输出高电平时,设备试图输出低电平,从而导致短路和输出门过载。

相关问题