คลาส I2C -- โปรโตคอลอนุกรมแบบสองสาย¶
I2C เป็นโปรโตคอลแบบสองสายสำหรับการสื่อสารระหว่างอุปกรณ์ ในระดับฟิสิกส์ประกอบด้วยสาย 2 เส้น ได้แก่ SCL และ SDA ซึ่งเป็นสายสัญญาณนาฬิกาและสายข้อมูลตามลำดับ
ออบเจ็กต์ I2C ถูกสร้างขึ้นโดยผูกกับบัสที่ระบุ สามารถกำหนดค่าได้ในขณะสร้าง หรือกำหนดค่าในภายหลังก็ได้
การพิมพ์ออบเจ็กต์ I2C จะแสดงข้อมูลการกำหนดค่าของมัน
มีการใช้งาน I2C ทั้งแบบฮาร์ดแวร์และซอฟต์แวร์ผ่านคลาส I2C และ SoftI2C โดย I2C ฮาร์ดแวร์ใช้การสนับสนุนฮาร์ดแวร์พื้นฐานของระบบในการอ่าน/เขียน ซึ่งโดยทั่วไปจะมีประสิทธิภาพและรวดเร็ว แต่อาจมีข้อจำกัดเกี่ยวกับพินที่สามารถใช้ได้ ส่วน I2C ซอฟต์แวร์ถูกใช้งานผ่านการ bit-banging และสามารถใช้กับพินใดก็ได้แต่มีประสิทธิภาพน้อยกว่า คลาสเหล่านี้มีเมธอดเหมือนกันและต่างกันหลักในวิธีสร้าง
Note
บัส I2C ต้องการวงจร pull-up ทั้งบน SDA และ SCL เพื่อการทำงาน โดยทั่วไปจะเป็นตัวต้านทานในช่วง 1 - 10 kOhm ที่ต่อจากแต่ละ SDA/SCL ไปยัง Vcc หากไม่มีสิ่งเหล่านี้ พฤติกรรมจะไม่ถูกกำหนดและอาจตั้งแต่การบล็อก การรีเซ็ต watchdog ที่ไม่คาดคิด ไปจนถึงค่าที่ผิดพลาด บ่อยครั้งวงจร pull-up นี้จะถูกสร้างไว้ในบอร์ด MCU หรือบอร์ด sensor breakout แล้ว แต่ไม่มีกฎตายตัว ดังนั้นโปรดตรวจสอบหากมีปัญหา ดูเพิ่มเติมที่ คู่มือการเรียนรู้ที่ยอดเยี่ยมนี้ โดย 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เท่านั้น- readinto(buf: bytearray, nack: bool = True, /) None¶
อ่านไบต์จากบัสและเก็บลงใน buf จำนวนไบต์ที่อ่านเท่ากับความยาวของ buf จะส่ง ACK บนบัสหลังจากรับทุกไบต์ยกเว้นไบต์สุดท้าย หลังจากรับไบต์สุดท้าย ถ้า nack เป็น true จะส่ง NACK ไม่เช่นนั้นจะส่ง ACK (และในกรณีนี้อุปกรณ์ปลายทางจะถือว่าจะมีการอ่านไบต์เพิ่มเติมในการเรียกครั้งถัดไป)
การดำเนินการบัสมาตรฐาน¶
เมธอดต่อไปนี้ใช้งานการอ่านและเขียนคอนโทรลเลอร์ I2C มาตรฐานที่กำหนดเป้าหมายอุปกรณ์ปลายทางที่ระบุ
- readfrom(addr: int, nbytes: int, stop: bool = True, /) bytes¶
อ่าน nbytes จากอุปกรณ์ปลายทางที่ระบุโดย addr ถ้า stop เป็น true จะสร้างเงื่อนไข STOP ที่ท้ายการถ่ายโอน คืนค่าออบเจ็กต์
bytesพร้อมข้อมูลที่อ่าน
- readfrom_into(addr: int, buf: bytearray, stop: bool = True, /) None¶
อ่านลงใน buf จากอุปกรณ์ปลายทางที่ระบุโดย addr จำนวนไบต์ที่อ่านจะเท่ากับความยาวของ buf ถ้า stop เป็น true จะสร้างเงื่อนไข STOP ที่ท้ายการถ่ายโอน
เมธอดคืนค่า
None
- writeto(addr: int, buf: bytes, stop: bool = True, /) int¶
เขียนไบต์จาก buf ไปยังอุปกรณ์ปลายทางที่ระบุโดย addr ถ้าได้รับ NACK หลังจากเขียนไบต์จาก buf แล้ว ไบต์ที่เหลือจะไม่ถูกส่ง ถ้า stop เป็น true จะสร้างเงื่อนไข STOP ที่ท้ายการถ่ายโอน แม้ว่าจะได้รับ NACK ฟังก์ชันคืนค่าจำนวน ACK ที่ได้รับ
- writevto(addr: int, vector: tuple | list, stop: bool = True, /) int¶
เขียนไบต์ที่อยู่ใน vector ไปยังอุปกรณ์ปลายทางที่ระบุโดย addr vector ควรเป็น tuple หรือรายการของออบเจ็กต์ที่มีโปรโตคอลบัฟเฟอร์ addr จะถูกส่งเพียงครั้งเดียว จากนั้นไบต์จากแต่ละออบเจ็กต์ใน vector จะถูกเขียนออกตามลำดับ ออบเจ็กต์ใน vector อาจมีความยาวศูนย์ไบต์ ซึ่งในกรณีนั้นจะไม่มีส่วนร่วมในเอาต์พุต
ถ้าได้รับ NACK หลังจากเขียนไบต์จากออบเจ็กต์ใน vector ไบต์ที่เหลือและออบเจ็กต์ที่เหลือจะไม่ถูกส่ง ถ้า stop เป็น true จะสร้างเงื่อนไข 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 โดยการ bit-banging พิน GPIO ใดก็ได้ มันเปิดเผยเมธอดเหมือนกับ I2C บวกกับการดำเนินการบัสพื้นฐานระดับต่ำ (start(), stop(), readinto(), write()) สำหรับผู้เรียกที่ต้องการประกอบธุรกรรมที่ไม่ใช่มาตรฐาน ใช้เมื่อพินที่คุณต้องการไม่ได้ต่อกับบล็อก I2C ฮาร์ดแวร์ เมื่อคุณต้องการบัสมากกว่าที่ฮาร์ดแวร์รองรับ หรือเพื่อสื่อสารกับอุปกรณ์ที่ต้องการลำดับที่ผิดปกติ (สัญญาณนาฬิกาพิเศษ การเริ่มซ้ำหลังจากการเขียน เป็นต้น)
ตัวสร้าง¶
- class machine.SoftI2C(scl: Pin, sda: Pin, *, freq: int = 400000, timeout: int = 50000)¶
สร้างบัส I2C ซอฟต์แวร์ที่ขับเคลื่อนโดย
scl/sdafreqคืออัตราสัญญาณนาฬิกา SCL เป้าหมายในหน่วย Hz (อัตราจริงมักจะต่ำกว่าเนื่องจากค่าใช้จ่ายของลูป bit-bang)timeoutคือเวลาสูงสุดในหน่วยไมโครวินาทีที่รอสำหรับการยืด clock (SCL ถูกดึงต่ำโดยอุปกรณ์อื่นบนบัส) เมื่อหมดเวลาจะเกิดOSError(ETIMEDOUT)เมธอดทั่วไป¶
การดำเนินการ I2C พื้นฐาน¶
เมธอดต่อไปนี้ใช้งานการดำเนินการบัสคอนโทรลเลอร์ I2C พื้นฐานและสามารถนำมารวมกันเพื่อสร้างธุรกรรม I2C ใดก็ได้ เมธอดเหล่านี้มีเฉพาะใน SoftI2C -- คลาส
I2Cฮาร์ดแวร์ไม่เปิดเผย- 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จากอุปกรณ์ที่ที่อยู่ 7 บิตaddrถ้าstopเป็น true จะสร้างเงื่อนไข STOP ที่ท้ายการถ่ายโอน
- readfrom_into(addr: int, buf: bytearray, stop: bool = True, /) None¶
อ่าน
len(buf)ไบต์จากอุปกรณ์ที่addrลงในbufถ้าstopเป็น true จะสร้างเงื่อนไข STOP ที่ท้ายการถ่ายโอน
การดำเนินการหน่วยความจำ¶
อุปกรณ์ I2C บางตัวทำงานเหมือนอุปกรณ์หน่วยความจำ (หรือชุดรีจิสเตอร์) ที่สามารถอ่านและเขียนได้ ในกรณีนี้มีที่อยู่สองแห่งที่เกี่ยวข้องกับธุรกรรม I2C ได้แก่ ที่อยู่อุปกรณ์ปลายทางและที่อยู่หน่วยความจำ เมธอดต่อไปนี้เป็นตัวช่วยความสะดวกสำหรับการสื่อสารกับอุปกรณ์ดังกล่าว
- readfrom_mem(addr: int, memaddr: int, nbytes: int, *, addrsize: int = 8) bytes¶
อ่าน
nbytesจากอุปกรณ์ที่addrโดยเริ่มจากรีจิสเตอร์memaddrโดยaddrsizeคือความกว้างของที่อยู่รีจิสเตอร์เป็นบิต (โดยทั่วไปคือ8หรือ16)