مشکل رو بالاخره تونستم حل کنم. الحمدلله.
ایراد اینجاست که در تابع e2p_read_byte و همین طور تابع e2p_read_buf، موقعی که قصد داریم آدرس دیتا رو به eeprom بفرستیم، لازمه A0 رو بنویسیم و بعد موقع خوندن، A1 رو بنویسیم. یعنی:
کد:
char e2p_read_byte(unsigned short adr){
char data;
i2csw_start();
i2csw_write(0xA0);
i2csw_write( (adr >> 8) & 0x00FF );
i2csw_write( adr & 0x00FF );
i2csw_start();
i2csw_write(0xA1);
data=i2csw_read(NACK);
i2csw_stop();
return data;
}
void e2p_read_buf(char *buf,unsigned short adr,char cnut){
char i;
if(adr+cnut>256)
cnut=256-adr;
i2csw_start();
i2csw_write(0xA0);
i2csw_write( (adr >> 8) & 0x00FF );
i2csw_write( adr & 0x00FF );
i2csw_start();
i2csw_write(0xA1);
for(i=0;i<cnut;i++)
buf[i]=i2csw_read(ACK);
i2csw_read(NACK);
i2csw_stop();
}
این کد الان برای من کار می کنه. نسخه جدید رو ضمیمه می کنم شاید به درد دوستان بخوره.
علاوه بر منابعی که در پست اول اشاره کردم، این چند روزه از منابع زیر هم استفاده کردم:
http://www.atmel.com/Images/doc6327.pdf
I2C 101
و فصل 6 کتاب آقایان شکری و سلطانیان (PIO)
یه چند تا نکته هم حیفه نگم: کد این پروژه، یک شبیه سازی نرم افزاری از پروتکل TWI = I2c هست که با زحمت شما دوستان در همین فروم آماده شده. پروژه دیگه ای که در پست اول اشاره کردم (basic-twi-eeprom-project-at91sam7x-ek) از پیاده سازی سخت افزاری موجود در at91sam7x استفاده می کنه. در حالت نرم افزاری، می شه از هر دو پورت General I/O دیگه ای هم استفاده کرد، برای این کار کافیه خطوط 10 تا 13 فایل I2CSW.h رو تغییر بدید:
کد:
#define I2cSW_PORT AT91C_BASE_PIOA // or AT91C_BASE_PIOB
#define I2cSW_SDA 10
#define I2cSW_SCL 11
#define I2cSW_PMC_PORT AT91C_ID_PIOA // or AT91C_ID_PIOB
اما اگه از کنترلر TWI موجود در برد استفاده کنید، لازمه حتماً از دو پایه PA10 و PA11 استفاده کنید. ضمناً در پروژه (basic-twi-eeprom-project-at91sam7x-ek) لازمه آدرس آیسی رو به صورت 7 بیتی مشخص کنید، یعنی مثلاً 0xA0 رو یک بیت به راست شیفت بدید و به صورت 0x50 ذخیره کنید:
کد:
#define AT24C_ADDRESS 0x50
بعداً کنترلر TWI یا درایور نرم افزاری اون، آدرس رو یک بیت به چپ شیفت می ده و بیت mode of operation رو در کم ارزش ترین بیتش قرار می ده که به 0xA0 یا 0xA1 تبدیل خواهد شد.
و بالاخره علت این که آدرس این eeprom برابر 0xA0 هست اینه که:
طبق دیتاشیت چهار بیت پرارزش آدرس به صورت hardcoded در خود آیسی عبارت اند از: 0b1010 که معادل A در مبنای شونزده هست. سه بیت بعدی عبارت اند از مقادیر پایه های A0 و A1 و A2 که من به زمین وصل کردم و لذا معادل صفر هستند. پس تا الان شد: 0b1010000. کم ارزش ترین بیت، بیت حالت عملیات هست که برای عملیات خواندن معادل 1 و برای نوشتن معادل صفر هست. یعنی میشه 0b1010000m که اگه m مساوی صفر یا 1 باشه، به ترتیب آدرس 0xA0 یا 0xA1 رو خواهیم داشت. البته دقت کنید مستقل از خوندن یا نوشتن دیتا -همون طور که در ابتدای این پست گفتم- موقع نوشتن آدرس باید حالت عملیات رو صفر قرار بدید. بعد اگر قصد خواندن دارید مجدداً با تحویل دادن آدرس آیسی (این بار با m=1)، حالت اصلی مد نظرتون که خوندن هست رو به آیسی بگید، مثل کد توابع e2p_write_byte و e2p_read_byte.
امیدوارم در آینده مفید واقع بشه. یادآوری کنم که فایل جدید پروژه رو ضمیمه کردم.