บทความนี้เป็นการอธิบายเมธอดต่าง ๆ ของ Wire.h ซึ่งเป็นคลาสสำหรับสื่อสารกับอุปกรณ์ผ่านบัสประเภท I2C ที่ใช้สายสัญญาณ 2 เส้นเรียกว่า SDA และ SCL สำหรับรับส่งข้อมูลระหว่างกัน ศึ่งพวกเรามีบทความเกี่ยวกับการสื่อสารประเภทนี้ค่อนข้างเยอะ และใช้เป็นบัสหลักในการพัฒนาอุปกรณ์ขึ้นมาเองแล้วเรียกใช้งานผ่านบัส เข่น บทความการใช้ esp8266 เชื่อมต่อกัย Arduino Uno หรือ การใช้ esp8266 กับ stm32f030f4p6 เป็นต้น
ขาสำหรับ I2C
ในหัวข้อนี้ขอกล่าวถึงขาที่เป็นขาทำหน้าที่ SCL และ SDA ที่ฮาร์ดแวร์ไมโครคอนโทรลเลอร์รองรับการทำงาน ซึ่งทำให้การทำงานของการสื่อสารนั้นรวดเร็วกว่าการใช้ซอฟต์แวร์เขียนจำลองการทำงาน
STM32F030F4P6
ขาสำหรับทำหน้าที่ SCL และ SDA เป็นดังภาพที่ 1 จะภพบว่ามี I2C เพียงชุดเดียว ใช้ PA10 เป็นขา SDA และ PA9 เป็น SCL
STM32F103C8
สำหรับ STM32F103C8 วึ่งเป็น Cortex-M3 รองรับ I2C จำนวน 2 ชุด คือ I2C1 และ I2C2 ดังภาพที่ 2 โดยขา SCL ของแต่ละชุด คือ PB6 และ PB10 ส่วนขา SDA คือ PB7 และ PB11
STM32F401CC
สำหรับ STM32F401CC รองรับ I2C จำนวน 3 ชุด โดยการเลือกให้ชุดที่ 2 ทำงานจะทำให้ SPI3 ไม้สามารถใช้งานได้เนื่องจากใช้ขาร่วมกัน และการเปิดการทำงาน I2C ชุดที่ 3 จะกระทบกับการใช้ USART1 โดยขา SCL ของแต่ละชุดได้แก่ PB6, PB10 และ PA8 สำหรับ SDA ใช้ขาดังนี้ PB7, PB3 และ PB4 ดังภาพที่ 3
ESP8266
สำหรับ ESP8266 ไม่มีขาที่สนับสนุนโดยฮาร์ดแวร์ แต่สามารถใช้ขาทุกขาที่ใช้ได้เป็นตัวทำงานแบบซอฟต์แวร์
ESP32
ชิพ ESP32 รองรับฮาร์ดแวร์ I2C จำนวน 2 ชุดดังนี้ ซึ่งขาในชุดที่ 2 นั้นใช้ร่วมกับการทำ DAC
- I2C id=0
- SCL เป็นขา GPIO18
- SDA เป็นขา GPIO19
- I2C id=1
- SCL เป็นขา 25
- SDA เป็นขา 26
การใช้งาน
การใช้บัส I2C ของ Arduino ต้องเรียกผ่าน Wire.h โดยเมธอดสำหรับใช้งานมีดังนี้
คำสั่งสำหรับเริ่มต้นให้บัสทำงานเป็นดังนี้
Wire.begin()
คำสั่งสำหรับขอเข้าถึงอุปกรณ์ ณ ตำแหน่งที่กำหนดเป็นดังนี้
Wire.beginTransmission( ตำแหน่งของอุปกรณ์ )
การยกเลิกการเข้าถึงอุปกรณ์ที่ขอเข้าถึงไว้มีรูปแบบดังนี้ โดยเมธอดคืนค่า 0 ถ้าการเข้าถึงถูกยกเลิก
Wire.endTransmission()
กรณีที่ต้องการส่งข้อมูลไปยังอุปกรณ์ผ่านบัสสามารถทำได้ 3 วิธี คือ ส่งไบต์ข้อมูล ส่งสตริงและส่งก้อนข้อมูลพร้อมระบุจำนวนข้อมูลดังนี้
Wire.write( ไบต์ข้อมูล )
Wire.write( สตริง )
Wire.write( ก้อนข้อมูล, จำนวนไบต์ของข้อมูล )
เมื่อมีการร้อขอข้อมูล่านบัส ระบบจะนำข้อมูลที่ได้มาเก็บในบัฟเฟอร์ ซึ่งคำสั่งที่ทำหน้าที่ตรวจสอบจำนวนข้อมูลในบัฟเฟอร์มีรูปแบบดังนี้
จำนวนข้อมูลในบัฟเฟอร์ = Wire.available()
วิธีการนำข้อมูลจำนวน 1 ไบต์ออกจากบัฟเฟอร์ใช้คำสั่งดังนี้
byteData = Wire.read()
ตำสั่งร้องขออ่านข้อมูลจากอุปกรณ์เพื่อนำมาเก็บในบัฟเฟอร์ต้องระบุตำแหน่งของอุปกรณ์และจำนวนไบต์ที่ต้องการอ่านดังนี้
Wire.requestFrom( ตำแหน่งอุปกรณ์, จำนวนไบต์ที่ต้องการอ่าน )
การปรับความเร็วในการสื่อสารของบัส I2C ใช้คำสั่งกำหนดค่าดังนี้
Wire.SetClock( ความถี่ในการสื่อสาร )
คำสั่งสำหรับกำหนดฟังก์ชันตอบสนองเมื่อได้รับข้อมูลจากอุปกรณ์ภายนอก
Wire.onReceive( ชื่อฟังก์ชัน )
กำหนดฟังก์ชันตอบสนองเมื่อมีการร้องขอ
Wire.onRequest( ชื่อฟังก์ชัน )
ตัวอย่างการใช้งาน
ตัวอย่างการตรวจสอบอุปกรณ์
ตัวอย่างการตรวจสอบว่ามีอุปกรณ์ I2C_DEVICE หรือไม่เขียนได้ดังนี้
Wire.beginTransmission( I2C_DEVICE );
if (Wire.endTransmission() == 0) {
// พบอุปกรณ์
} else {
// ไม่พบอุปกรณ์
}
ตัวอย่างการเขียนข้อมูลไปยังอุปกรณ์
การเขียนข้อมูลไปยังอุปกรณ์มีขั้นตอน คือ เชื่อมต่อ ส่งข้อมูลลำดับไบต์ และปิดการเชื่อมต่อ ดังโค้ดต่อไปนี้
Wire.beginTransmission( I2C_DEVICE ); // (1)
Wire.write( ไบตข้อมูล1 ); // (2) ถ้ามีหลายไบต์ให้เขียนคำสั่งเรียงกันไป
Wire.endTransmission(); // (3)
ตัวอย่างการอ่านข้อมูลจากอุปกรณ์
การอ่านข้อมูลจากอุปกรณ์ประกอบไปด้วย 3 ขั้นตอนหลัก คือ ขอเข้าถึงตำแหน่งข้อมูลของอุปกรณ์ การอ่านมาเก็บในบัฟเฟอร์ และการเข้าถึงบัฟเฟอร์เพื่อนำข้อมูลออก ดังนี้
ขั้นตอน 1
Wire.beginTransmission( I2C_DEVICE );
Wire.write( ตำแหน่งของข้อมูล );
Wire.endTransmission();
ขั้นตอน 2
Wire.requestFrom( I2C_DEVICE, จำนวนไบต์ที่ต้องการอ่าน );
ขั้นตอน 3
while (Wire.available( ) ) {
ข้อมูล = Wire.read( );
}
สรุป
จากบทความนี้จะพบว่า หลักการเขียนโปรแกรมเพื่อใช้งานอุปกรณ์ I2C ผ่านคลาส Wire นั้นต้องอาศัยความเข้าใจโปรโทคอล (Protocol) หรือรูปแบบการสื่อสารกับอุปกรณ์เป็นสำคัญ เนื่องจาก คำสั่งช่วยเหลือเพียงส่งข้อมูลไบต์ไปยังอุปกรณ์ และอ่านข้อมูลปริมาณหนึ่งจากอุปกรณ์เท่านั้น ทางทีมงานเราหวังว่าคงเป็นแนวทางสำหรับผู้สนใจเขียนโปรแกรมเพื่อสื่อสารกับอุปกรณ์บนบัส I2C หรือสร้างอุปกรณ์เพื่อใช้งานเองที่สื่อสารกับอุปกรณ์บนบัส สุดท้าย ขอให้สนุกกับการเขียนโปรแกรม
ท่านใดต้องการพูดคุยสามารถคอมเมนท์ไว้ได้เลยครับ
แหล่งอ้างอิง
(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-07-05, 2021-07-29, 2021-11-02