使用ATtiny402进行24C32A EEPROM写入操作失败,求排查指导
ATtiny402 驱动24C32A EEPROM I2C写入故障排查
我基于ATtiny402编写了I2C驱动代码以实现24C32A EEPROM的写入操作,但该功能无法正常运行。正在使用Proteus软件进行仿真调试,运行时I2C调试工具始终显示问号,恳请帮助排查问题。
现有驱动代码
#define sda_on PORTA_DIRSET = PIN1_bm ; PORTA_OUTSET = PIN1_bm ; #define sda_read PORTA_DIRCLR = PIN1_bm ;while(PORTA_IN & (PIN1_bm));PORTA_DIRSET = PIN1_bm ; #define sda_off PORTA_DIRSET = PIN1_bm ;PORTA_OUTCLR = PIN1_bm ; #define scl_on PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ; #define scl_off PORTA_DIRSET = PIN2_bm ;PORTA_OUTCLR = PIN2_bm ; #include <xc.h> #include <util/delay.h> void i2c_start(void) { sda_on; scl_on; _delay_ms(10); sda_off; _delay_ms(10); scl_off; } void i2c_stop(void) { sda_off; scl_off; _delay_ms(10); scl_on; _delay_ms(10); sda_on; } void i2c_data_write(unsigned char data) { for(int i=0;i<8;i++) { if(data & 0x80) { sda_on; } else sda_off; _delay_ms(10); scl_on; _delay_ms(10); scl_off; data = data << 1; } scl_on; sda_on; _delay_ms(10); sda_read; _delay_ms(10); scl_off; _delay_ms(10); }
问题排查与修正建议
1. ACK读取逻辑致命错误
sda_read宏中的while(PORTA_IN & (PIN1_bm));是死等SDA拉低,一旦从机未响应ACK,程序会直接卡死,仿真中就会出现无有效信号的问号状态。同时ACK读取的时序顺序错误:正确流程是先释放SDA为输入,再拉高SCL读取状态,而非先拉SCL高再切换SDA方向。
修正后的ACK读取逻辑:
// 替换原有sda_read宏,改为仅切换输入方向 #define sda_release PORTA_DIRCLR = PIN1_bm; void i2c_data_write(unsigned char data) { for(int i=0;i<8;i++) { if(data & 0x80) { sda_on; } else sda_off; _delay_us(10); // 改用微秒延时,符合I2C标准速率 scl_on; _delay_us(10); scl_off; data = data << 1; } // 正确读取ACK流程 sda_release; // 释放SDA,让从机控制电平 _delay_us(10); scl_on; _delay_us(10); // 读取ACK状态(可选:判断是否收到响应) unsigned char ack = !(PORTA_IN & PIN1_bm); scl_off; _delay_us(10); sda_on; // 恢复SDA为输出高 }
2. 时序延时过长
原代码使用_delay_ms(10),相当于I2C速率仅100Hz,远低于标准的100kHz/400kHz,过长的延时会导致仿真工具无法识别有效I2C信号,建议改用_delay_us(10)级别的延时,匹配标准时序。
3. 缺少完整的EEPROM写入流程
24C32A的写入需要完整的I2C帧:起始信号→设备地址→2字节内存地址→写入数据→停止信号,现有代码仅实现底层操作,没有组装完整的写入流程。补充写入函数:
void eeprom_write(unsigned int addr, unsigned char data) { i2c_start(); i2c_data_write(0xA0); // 24C32A默认设备地址,需根据硬件A0-A2引脚调整 i2c_data_write(addr >> 8); // 内存地址高字节 i2c_data_write(addr & 0xFF); // 内存地址低字节 i2c_data_write(data); i2c_stop(); _delay_ms(5); // 等待EEPROM完成写入周期 }
并在主函数中调用测试,例如eeprom_write(0x0000, 0xAA);。
4. Proteus仿真硬件检查
- 确认ATtiny402的SDA(PIN1)、SCL(PIN2)与24C32A的对应引脚(SDA=5脚,SCL=6脚)正确连接
- 检查24C32A的A0-A2引脚配置,对应设备地址的最低三位,需与代码中
0xA0匹配 - 确认24C32A已正确接入VCC和GND,电压范围2.5V~5.5V
- 检查I2C调试工具是否正确绑定SDA/SCL引脚,速率设置为100kHz
内容的提问来源于stack exchange,提问作者user21170594
相关产品推荐
相关产品推荐

