I2C در FPGA

ارتباط از طریق پروتکل I2C پیچیده تر از UART یا SPI است. فرستادن سیگنال‌ها باید از پروتکل خاصی پیروی کند تا به عنوان ارتباط I2C معتبر شناخته شوند. 

پیام‌ها به دو دسته فریم تقسیم می‌شوند: یک فریم آدرس، که در آن master مشخص می‌کند به کدام slave پیام می‌فرستد، و یک فریم یا بیشتر برای داده، که پیام‌های 8 بیتی هستند که از master به slave یا برعکس منتقل می‌شوند. داده بعد از اینکه SCL پایین می‌رود روی خط SDA قرار می‌گیرد، و بعد از اینکه SCL بالا می‌رود نمونه برداری می‌شود. زمان بین لبه کلاک و خواندن/نوشتن داده توسط دستگاه‌ها تعیین می‌شود و بسته به چیپ متفاوت است.

وضعیت شروع

برای شروع ارسال فریم آدرس، دستگاه master خط SCL را بالا نگه داشته و SDA را پایین می‌کشد. این کار به تمامی دستگاه‌های slave روی باس اعلام می‌کند که یک ارسال به زودی انجام می‌شود. اگر دو master در یک زمان قصد ارسال داده را داشته باشند، دستگاهی که اول SDA را پایین می‌کشد برنده است و کنترل باس را در اختیار می‌گیرد. فرستادن چندین دستور شروع توسط یک master پشت سر هم بدون اینکه کنترل باس را به master دیگری بدهد نیز ممکن است که در ادامه در مورد آن صحبت می‌کنیم.

فریم آدرس

فریم آدرس همیشه در هر مرتبه ارتباط جدید ابتدا ارسال می‌شود. برای یک آدرس 7بیتی، آدرس به صورت MSB ارسال می‌شود و بعد از آن یک بیت R/W ارسال می‌شود که تعیین می‌کند این عمل خواندن (1) یا نوشتن (0) است.

نهمین بیت این فریم بیت NACK/ACK است. این بیت در همه‌ی فریم‌ها وجود دارد، چه داده چه آدرس. بعد از اینکه هشت بیت اول فریم ارسال می‌شود، کنترل SDA به دست دستگاه دریافت کننده داده می‌شود. اگر این دستگاه قبل از نهمین پالس کلاک SDA را پایین نکشد، این طور برداشت می‌شود که دستگاه گیرنده داده را دریافت نکرده است یا نتوانسته است آن را رمزگشایی کند. در این صورت، انتقال داده متوقف شده و تصمیم این که چه کاری انجام شود با master سیستم است.

فریم داده

بعد از این که فریم آدرس ارسال شد، ارسال داده می‌تواند شروع شود. Master به تولید پالس کلاک با وقفه‌های منظم ادامه می‌دهد، و بسته به بیت R/W داده توسط slave یا master روی SDA قرار داده‌ می‌شود. تعداد فریم‌های داده دلخواه است، و بیشتر دستگاه‌های slave به طور خودکار رجیستر داخلی را افزایش می‌دهند، به این معنی که خواندن یا نوشتن‌های پشت سر هم بع ترتیب از رجیسترهای بعدی انجام می‌شود.

وضعیت توقف

هنگامی که تمامی فریم‌های داده ارسال شدند، master یک وضعیت توقف ایجاد می‌کند. وضعیت توقف با یک تغیر وضعیت از (low به high) روی SDA بعد از یک تغیر وضعیت از 0به1 روی SCL و ثابت ماندن SCL تعریف می‌شود. در طی نوشتن معمولی ،هنگامی که SCL بالاست مقدار SDA نباید تغیر کند تا از وضعیت توقف اشتباهی جلوگیری شود.

آدرس های 10 بیتی در پروتکل I2C

در یک سیستم آدرس دهی 10بیتی، به دو فریم برای ارسال آدرس slave نیاز است. اولین فریم از کد b11110xyz تشکیل می‌شود، که در آن ‘x’ بیت MSB آدرس slave، y بیت 8 آدرس slave، و z بیت R/W که در بالا توضیح داده شد می‌باشد.بیت ACK اولین فریم توسط تمامی slave هایی که دو بیت اول آدرس آن‌ها با بیت‌های ارسال شده یکسان است فرستاده می‌شود. مانند انتقال 7بیتی معمولی، یک فریم دیگر بلافاصله ارسال می‌شود که شامل بیت‌های 7:0 آدرس می‌باشد. در این مرحله، slave فراخوانی شده باید با یک بیت ACK پاسخ دهد. در غیر اینصورت حالت خطا دقیقا مانند یک سیستم 7بیتی می‌باشد.

توجه داشته باشید که دستگاه‌های با آدرس 10بیتی می‌توانند به همراه دستگاه‌های 7بیتی روی یک باس وجود داشته باشند، زیرا بخش ‘11110’ آدرس در هیچ قسمتی از یک آدرس 7بیتی معتبر وجود ندارد.

وضعیت های شروع مکرر

بعضی اوقات، لازم است به یک دستگاه master اجازه داده شود تا چندین پیام را پشت سرهم و بدون اجازه دادن به دیگر دستگاه‌های master روی باس ارسال کند. برای این کار، وضعیت شروع مکرر تعریف شده است.

برای انجام شروع‌های مکرر، در حالی که SCL پایین است SDA بالا می‌رود، SCL بالا می‌رود، و سپس هنگامی که SCL بالاست SDA مجددا پایین کشیده می‌شود. بخاطر اینکه هیچ وضعیت توقفی روی باس وجود نداشت، ارتباط قبلی تکمیل نشده بود و بنابراین master کنونی به در دست گرفتن کنترل باس ادامه می‌دهد.

در این مرحله، ارسال پیام بعدی می‌تواند شروع شود. نحوه چینش این پیام جدید نیز مانند هر پیام دیگری است یک فریم آدرس و سپس فریم‌های داده. هر تعداد شروع‌های مکرر مجاز است، و master تا زمان ارسال وضعیت توقف کنترل باس را به دست دارد.

تعریض کلاک پروتکل I2C

گاهی اوقات، نرخ تبادل داده‌‌ی master از توانایی slave برای تامین آن داده تجاوز می‌کند. این مشکل می‌تواند به دلیل آماده نبودن داده(برای مثال، هنوز یک تبدیل آنالوگ به دیجیتال را انجام نداده است) یا بخاطر کامل نشدن عملیات قبلی(برای مثال، یک EEPROM که نوشتن روی حافظه non-volatile را تمام نکرده است و نمی‌تواند قبل از اتمام آن به دیگر درخواست‌ها پاسخ دهد) باشد.

در این شرایط، بعضی از دستگاه‌های slave عملی به نام “clock stretching” یا تعریض کلاک را انجام می‌دهند. به طور کلی، تمامی کلاک‌ها توسط master زده می‌شود و slave ها با توجه به پالس‌های کلاک master فقط داده را از روی باس برداشته یا آن را روی باس می‌گذارند. در هر لحظه از فرآیند انتقال داده، slave فراخوانی شده می‌تواند بعد از اینکه master خط SCL را آزاد کرد آن را پایین نگه دارد. در این صورت master ادامه کلاک زنی و انتقال داده را متوقف کرده تا زمانی که Slave خط SCL را آزاد کند.