الصنف I2C -- بروتوكول تسلسلي ثنائي الأسلاك¶
I2C هو بروتوكول ثنائي الأسلاك للاتصال بين الأجهزة. على المستوى الفيزيائي يتألف من سلكين: SCL و SDA، وهما خط الساعة وخط البيانات على التوالي.
تُنشأ كائنات I2C وهي مرتبطة بناقل محدد. يمكن تهيئتها عند الإنشاء، أو تهيئتها لاحقاً.
طباعة كائن I2C تمنحك معلومات حول تكوينه.
توجد تطبيقات I2C على مستوى العتاد والبرمجيات عبر الصنفين I2C و SoftI2C. يستخدم I2C العتادي الدعم العتادي الأساسي للنظام لإجراء عمليات القراءة/الكتابة وهو عادةً فعّال وسريع لكنه قد يفرض قيوداً على الدبابيس التي يمكن استخدامها. أما I2C البرمجي فيُطبّق عن طريق التبديل المباشر للبتات ويمكن استخدامه على أي دبوس لكنه ليس بالفعالية ذاتها. يمتلك هذان الصنفان الطرق نفسها المتاحة ويختلفان بشكل أساسي في طريقة إنشائهما.
ملاحظة
يتطلب ناقل I2C دائرة سحب لأعلى (pull-up) على كل من SDA و SCL لكي يعمل. عادةً ما تكون هذه مقاومات في النطاق 1 - 10 كيلو أوم، موصولة من كل من SDA/SCL إلى Vcc. بدونها يكون السلوك غير محدد وقد يتراوح من التعليق، أو إعادة ضبط غير متوقعة من المؤقت الرقيب (watchdog)، إلى مجرد قيم خاطئة. غالباً ما تكون دائرة السحب لأعلى هذه مدمجة بالفعل في لوحة MCU أو لوحات تفريع المستشعرات، لكن لا توجد قاعدة لذلك. لذا يرجى التحقق في حال حدوث مشكلة. راجع أيضاً هذا الدليل التعليمي الممتاز من Adafruit حول توصيل أسلاك I2C.
مثال على الاستخدام:
from machine import I2C
i2c = I2C(freq=400000) # create I2C peripheral at frequency of 400kHz
# depending on the port, extra parameters may be required
# to select the peripheral and/or pins to use
i2c.scan() # scan for peripherals, returning a list of 7-bit addresses
i2c.writeto(42, b'123') # write 3 bytes to peripheral with 7-bit address 42
i2c.readfrom(42, 4) # read 4 bytes from peripheral with 7-bit address 42
i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of peripheral 42,
# starting at memory-address 8 in the peripheral
i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of peripheral 42
# starting at address 2 in the peripheral
المُنشئات¶
- class machine.I2C(id: int, *, scl: Pin | None = None, sda: Pin | None = None, freq: int = 400000, timeout: int = 50000)¶
أنشئ وأعد كائن I2C جديداً باستخدام المعاملات التالية:
id يحدد طرفية I2C معينة. تعتمد القيم المسموح بها على المنفذ/اللوحة المحددة
scl ينبغي أن يكون كائن دبوس يحدد الدبوس المستخدم لـ SCL.
sda ينبغي أن يكون كائن دبوس يحدد الدبوس المستخدم لـ SDA.
freq ينبغي أن يكون عدداً صحيحاً يحدد التردد الأقصى لـ SCL.
timeout هو الزمن الأقصى بالميكروثانية المسموح به لمعاملات I2C. هذا المعامل غير مسموح به على بعض المنافذ.
لاحظ أن بعض المنافذ/اللوحات سيكون لها قيم افتراضية لـ scl و sda يمكن تغييرها في هذا المُنشئ. وسيكون لأخرى قيم ثابتة لـ scl و sda لا يمكن تغييرها.
الطرق العامة¶
- init(scl: Pin, sda: Pin, *, freq: int = 400000) None¶
تهيئة ناقل I2C بالوسائط المعطاة:
scl هو كائن دبوس لخط SCL
sda هو كائن دبوس لخط SDA
freq هو معدل ساعة SCL
في حالة I2C العتادي قد يكون تردد الساعة الفعلي أقل من التردد المطلوب. ويعتمد ذلك على عتاد المنصة. يمكن تحديد المعدل الفعلي عن طريق طباعة كائن I2C.
عمليات I2C الأولية¶
تطبّق الطرق التالية عمليات ناقل المتحكم I2C الأولية ويمكن دمجها لتكوين أي معاملة I2C. وهي متوفرة إذا كنت بحاجة إلى تحكم أكبر في الناقل، وإلا فيمكن استخدام الطرق القياسية (انظر أدناه).
هذه الطرق متاحة فقط على الصنف
SoftI2C.- start() None¶
توليد حالة بدء (START) على الناقل (ينتقل SDA إلى المستوى المنخفض بينما يكون SCL مرتفعاً).
- stop() None¶
توليد حالة إيقاف (STOP) على الناقل (ينتقل SDA إلى المستوى المرتفع بينما يكون SCL مرتفعاً).
- readinto(buf: bytearray, nack: bool = True, /) None¶
يقرأ بايتات من الناقل ويخزنها في buf. عدد البايتات المقروءة هو طول buf. سيُرسل إقرار (ACK) على الناقل بعد استقبال جميع البايتات عدا الأخيرة. بعد استقبال البايت الأخير، إذا كان nack صحيحاً فسيُرسل عدم إقرار (NACK)، وإلا فسيُرسل إقرار (ACK) (وفي هذه الحالة تفترض الطرفية أنه سيتم قراءة المزيد من البايتات في استدعاء لاحق).
عمليات الناقل القياسية¶
تطبّق الطرق التالية عمليات القراءة والكتابة القياسية لمتحكم I2C التي تستهدف جهازاً طرفياً معطى.
- readfrom(addr: int, nbytes: int, stop: bool = True, /) bytes¶
اقرأ nbytes من الطرفية المحددة بـ addr. إذا كان stop صحيحاً فسيتم توليد حالة إيقاف (STOP) في نهاية النقل. تُعيد كائن
bytesيحتوي على البيانات المقروءة.
- readfrom_into(addr: int, buf: bytearray, stop: bool = True, /) None¶
اقرأ إلى buf من الطرفية المحددة بـ addr. سيكون عدد البايتات المقروءة هو طول buf. إذا كان stop صحيحاً فسيتم توليد حالة إيقاف (STOP) في نهاية النقل.
تُعيد الطريقة
None.
- writeto(addr: int, buf: bytes, stop: bool = True, /) int¶
اكتب البايتات من buf إلى الطرفية المحددة بـ addr. إذا استُقبل عدم إقرار (NACK) بعد كتابة بايت من buf فلن تُرسل البايتات المتبقية. إذا كان stop صحيحاً فسيتم توليد حالة إيقاف (STOP) في نهاية النقل، حتى إذا استُقبل عدم إقرار (NACK). تُعيد الدالة عدد الإقرارات (ACK) التي استُقبلت.
- writevto(addr: int, vector: tuple | list, stop: bool = True, /) int¶
اكتب البايتات الموجودة في vector إلى الطرفية المحددة بـ addr. ينبغي أن يكون vector صفاً (tuple) أو قائمة من الكائنات التي تدعم بروتوكول المخزن المؤقت. يُرسل addr مرة واحدة ثم تُكتب البايتات من كل كائن في vector بالتتابع. قد تكون الكائنات في vector بطول صفر بايت وفي هذه الحالة لا تساهم في المخرجات.
إذا استُقبل عدم إقرار (NACK) بعد كتابة بايت من أحد الكائنات في vector فلن تُرسل البايتات المتبقية، ولا أي كائنات متبقية. إذا كان stop صحيحاً فسيتم توليد حالة إيقاف (STOP) في نهاية النقل، حتى إذا استُقبل عدم إقرار (NACK). تُعيد الدالة عدد الإقرارات (ACK) التي استُقبلت.
عمليات الذاكرة¶
تعمل بعض أجهزة I2C كجهاز ذاكرة (أو مجموعة سجلات) يمكن القراءة منه والكتابة إليه. في هذه الحالة يرتبط عنوانان بمعاملة I2C: عنوان الطرفية وعنوان الذاكرة. الطرق التالية هي دوال مساعدة للتواصل مع مثل هذه الأجهزة.
- readfrom_mem(addr: int, memaddr: int, nbytes: int, *, addrsize: int = 8) bytes¶
اقرأ nbytes من الطرفية المحددة بـ addr بدءاً من عنوان الذاكرة المحدد بـ memaddr. يحدد الوسيط addrsize حجم العنوان بالبتات. تُعيد كائن
bytesيحتوي على البيانات المقروءة.
الصنف SoftI2C -- ناقل I2C مُحاكى برمجياً¶
يطبّق الصنف SoftI2C بروتوكول I2C عن طريق التبديل المباشر للبتات على دبابيس GPIO اعتباطية. وهو يكشف سطح الطرق نفسه الذي يكشفه I2C بالإضافة إلى عمليات الناقل الأولية منخفضة المستوى (start()، stop()، readinto()، write()) للمستدعين الذين يحتاجون إلى تجميع معاملات غير قياسية. استخدمه عندما لا تكون الدبابيس التي تحتاجها موصولة بكتلة I2C عتادية، أو عندما تحتاج إلى عدد من النواقل أكبر مما يوفره العتاد، أو للتواصل مع أجهزة تتطلب تسلسلات غير معتادة (نبضات ساعة إضافية، بدايات متكررة بعد الكتابات، إلخ).
المُنشئات¶
- class machine.SoftI2C(scl: Pin, sda: Pin, *, freq: int = 400000, timeout: int = 50000)¶
أنشئ ناقل I2C برمجياً مُشغّلاً بواسطة
scl/sda.freqهو معدل ساعة SCL المستهدف بالهرتز (المعدل الفعلي يكون عادةً أقل بسبب الحمل الإضافي لحلقة التبديل المباشر للبتات).timeoutهو الزمن الأقصى بالميكروثانية للانتظار من أجل تمديد الساعة (clock stretching) (احتفاظ جهاز آخر على الناقل بـ SCL منخفضاً)؛ وعند انتهائه يُطلقOSError(ETIMEDOUT).الطرق العامة¶
عمليات I2C الأولية¶
تطبّق الطرق التالية عمليات ناقل المتحكم I2C الأولية ويمكن دمجها لتكوين أي معاملة I2C. وهي خاصة بـ SoftI2C فقط -- الصنف العتادي
I2Cلا يكشفها.- start() None¶
توليد حالة بدء (START) على الناقل (ينتقل SDA إلى المستوى المنخفض بينما يكون SCL مرتفعاً).
- stop() None¶
توليد حالة إيقاف (STOP) على الناقل (ينتقل SDA إلى المستوى المرتفع بينما يكون SCL مرتفعاً).
- readinto(buf: bytearray, nack: bool = True, /) None¶
اقرأ بايتات من الناقل إلى
buf. تُقرأlen(buf)بايتات؛ ويُرسل إقرار (ACK) بعد كل بايت عدا الأخير. بعد البايت الأخير، يرسلnack=True(الافتراضي) عدم إقرار (NACK) لإنهاء النقل؛ ويرسلnack=Falseإقراراً (ACK) ليبقى الجهاز محدداً من أجلreadinto()لاحقة.
عمليات الناقل القياسية¶
تطبّق الطرق التالية عمليات القراءة والكتابة القياسية لمتحكم I2C التي تستهدف جهازاً طرفياً معطى.
- readfrom(addr: int, nbytes: int, stop: bool = True, /) bytes¶
اقرأ
nbytesمن الجهاز الموجود على العنوانaddrذي 7 بتات. إذا كانstopصحيحاً فسيتم توليد حالة إيقاف (STOP) في نهاية النقل.
- readfrom_into(addr: int, buf: bytearray, stop: bool = True, /) None¶
اقرأ
len(buf)بايتات من الجهاز الموجود على العنوانaddrإلىbuf. إذا كانstopصحيحاً فسيتم توليد حالة إيقاف (STOP) في نهاية النقل.
عمليات الذاكرة¶
تعمل بعض أجهزة I2C كجهاز ذاكرة (أو مجموعة سجلات) يمكن القراءة منه والكتابة إليه. في هذه الحالة يرتبط عنوانان بمعاملة I2C: عنوان الطرفية وعنوان الذاكرة. الطرق التالية هي مساعدات ملائمة للتواصل مع مثل هذه الأجهزة.
- readfrom_mem(addr: int, memaddr: int, nbytes: int, *, addrsize: int = 8) bytes¶
اقرأ
nbytesمن الجهاز الموجود على العنوانaddrبدءاً من السجلmemaddr.addrsizeهو عرض عنوان السجل بالبتات (عادةً8أو16).