- I2C Communication Protocol คืออะไร?
- I2C Communication ทำงานอย่างไร?
- จะใช้การสื่อสาร I2C ได้ที่ไหน?
- I2C ใน Arduino
- ส่วนประกอบที่จำเป็น
- แผนภูมิวงจรรวม
- คำอธิบายการทำงาน
- การเขียนโปรแกรม I2C ใน Arduino
- คำอธิบายการเขียนโปรแกรม Master Arduino
- คำอธิบายการเขียนโปรแกรม Slave Arduino
ในบทช่วยสอนก่อนหน้านี้ของเราได้เรียนรู้เกี่ยวกับการสื่อสาร SPI ใน Arduino วันนี้เราจะมาเรียนรู้เกี่ยวกับ Serial Communication Protocol: I2C (Inter Integrated Circuits) การเปรียบเทียบ I2C กับ SPI นั้น I2C มีเพียงสองสายในขณะที่ SPI ใช้สี่สายและ I2C สามารถมี Master และ Slave ได้หลายตัวในขณะที่ SPI สามารถมี Master และ Slave ได้หลายตัวเท่านั้น ดังนั้นจึงมีไมโครคอนโทรลเลอร์มากกว่าหนึ่งตัวในโครงการที่ต้องเป็นผู้เชี่ยวชาญจากนั้นจึงใช้ I2C โดยทั่วไปการสื่อสาร I2C จะใช้ในการสื่อสารกับ Gyroscope, accelerometer, เซ็นเซอร์ความดันบรรยากาศ, จอ LED เป็นต้น
ในบทช่วยสอน Arduino I2Cนี้เราจะใช้การสื่อสาร I2C ระหว่างบอร์ด Arduino สองตัวและส่งค่า (0 ถึง 127) ซึ่งกันและกันโดยใช้โพเทนชิออมิเตอร์ ค่าจะแสดงบนจอ LCD 16x2 ที่เชื่อมต่อกับ Arduino แต่ละตัว ที่นี่ Arduino หนึ่งตัวจะทำหน้าที่เป็น Master และอีกตัวหนึ่งจะทำหน้าที่เป็น Slave เริ่มจากการแนะนำเกี่ยวกับการสื่อสาร I2C กันก่อน
I2C Communication Protocol คืออะไร?
ระยะ IIC ย่อมาจาก“ วงจรอินเตอร์แบบบูรณาการ ” โดยปกติจะแสดงเป็น I2C หรือ I กำลังสอง C หรือแม้กระทั่งเป็นโปรโตคอลอินเทอร์เฟซ 2 สาย (TWI) ในบางแห่ง แต่ก็มีความหมายเหมือนกัน I2C เป็นโปรโตคอลการสื่อสารแบบซิงโครนัสซึ่งหมายความว่าอุปกรณ์ทั้งสองที่ใช้ข้อมูลร่วมกันจะต้องใช้สัญญาณนาฬิการ่วมกัน มีสายไฟเพียงสองสายในการแบ่งปันข้อมูลซึ่งสายหนึ่งใช้สำหรับสัญญาณไก่และอีกสายหนึ่งใช้สำหรับการส่งและรับข้อมูล
I2C Communication ทำงานอย่างไร?
การสื่อสาร I2C เป็นครั้งแรกโดย Phillips ดังที่ได้กล่าวไว้ก่อนหน้านี้ว่ามีสายไฟสองเส้นสายไฟทั้งสองนี้จะเชื่อมต่อกับอุปกรณ์สองเครื่อง นี่คืออุปกรณ์หนึ่งที่เรียกว่า ต้นแบบ และอุปกรณ์อื่น ๆ จะเรียกว่าเป็น ทาสการสื่อสารควรจะเกิดขึ้นระหว่างสอง นายและทาสเสมอ ข้อดีของการสื่อสารแบบ I2C คือสามารถเชื่อมต่อกับ Master ได้มากกว่าหนึ่ง Slave
การสื่อสารที่สมบูรณ์เกิดขึ้นผ่านสายไฟทั้งสองนี้คือ Serial Clock (SCL) และ Serial Data (SDA)
Serial Clock (SCL): แชร์สัญญาณนาฬิกาที่สร้างโดยต้นแบบกับทาส
Serial Data (SDA): ส่งข้อมูลไปและกลับระหว่าง Master และ Slave
ในช่วงเวลาที่กำหนดมีเพียงผู้เชี่ยวชาญเท่านั้นที่จะสามารถเริ่มการสื่อสาร เนื่องจากมีทาสมากกว่าหนึ่งคนในรถบัสนายจึงต้องอ้างถึงทาสแต่ละคนโดยใช้ที่อยู่ต่างกัน เมื่อระบุเฉพาะทาสที่มีที่อยู่นั้นจะตอบกลับพร้อมข้อมูลในขณะที่คนอื่น ๆ ยังคงเลิกใช้ วิธีนี้เราสามารถใช้บัสเดียวกันเพื่อสื่อสารกับอุปกรณ์หลายเครื่อง
ระดับแรงดันไฟฟ้าของ I2C ยังไม่ได้กำหนดไว้ล่วงหน้า การสื่อสาร I2C มีความยืดหยุ่นหมายถึงอุปกรณ์ที่ใช้พลังงาน 5v โวลต์สามารถใช้ 5v สำหรับ I2C และอุปกรณ์ 3.3v สามารถใช้ 3v สำหรับการสื่อสาร I2C แต่จะเกิดอะไรขึ้นหากอุปกรณ์สองเครื่องที่ใช้แรงดันไฟฟ้าต่างกันจำเป็นต้องสื่อสารโดยใช้ I2C? รถบัส I2C 5V ไม่สามารถเชื่อมต่อกับอุปกรณ์ ในกรณีนี้ตัวปรับแรงดันไฟฟ้าใช้เพื่อจับคู่ระดับแรงดันไฟฟ้าระหว่างบัส I2C สองตัว
มีเงื่อนไขบางอย่างที่กำหนดกรอบธุรกรรม การเริ่มต้นการส่งข้อมูลเริ่มต้นด้วยขอบที่ลดลงของ SDA ซึ่งกำหนดเป็นเงื่อนไข 'เริ่มต้น' ในแผนภาพด้านล่างโดยที่ต้นแบบปล่อยให้ SCL สูงในขณะที่ตั้งค่า SDA ให้ต่ำ
ดังแสดงในแผนภาพด้านบนด้านล่าง
ขอบที่ตกลงมาของ SDA เป็นตัวกระตุ้นฮาร์ดแวร์สำหรับสภาวะเริ่มต้น หลังจากนี้อุปกรณ์ทั้งหมดบนบัสเดียวกันจะเข้าสู่โหมดการฟัง
ในทำนองเดียวกันขอบที่เพิ่มขึ้นของ SDA จะหยุดการส่งข้อมูลซึ่งแสดงเป็นเงื่อนไข 'STOP' ในแผนภาพด้านบนโดยที่ต้นแบบจะปล่อยให้ SCL สูงและปล่อย SDA เพื่อไปที่สูง ขอบที่เพิ่มขึ้นของ SDA จึงหยุดการส่งผ่าน
บิต R / W ระบุทิศทางของการส่งของไบต์ต่อไปนี้ถ้าเป็น HIGH หมายความว่าทาสจะส่งและถ้ามันต่ำหมายความว่ามาสเตอร์จะส่ง
แต่ละบิตจะถูกส่งไปในแต่ละรอบนาฬิกาดังนั้นจึงใช้เวลา 8 รอบนาฬิกาในการส่งไบต์ หลังจากแต่ละไบต์ส่งหรือรับรอบนาฬิกาที่เก้าจะถูกระงับไว้สำหรับ ACK / NACK (รับทราบ / ไม่รับทราบ) บิต ACK นี้สร้างขึ้นโดยทาสหรือมาสเตอร์ขึ้นอยู่กับสถานการณ์ สำหรับ ACK บิต SDA ถูกตั้งไว้ที่ระดับต่ำโดยต้นแบบหรือทาสที่ 9 THรอบสัญญาณนาฬิกา ดังนั้นจึงถือว่าต่ำเป็น ACK อย่างอื่น NACK
จะใช้การสื่อสาร I2C ได้ที่ไหน?
การสื่อสาร I2C ใช้สำหรับ การสื่อสารระยะสั้นเท่านั้น แน่นอนว่าเชื่อถือได้ในระดับหนึ่งเนื่องจากมีพัลส์นาฬิกาที่ซิงโครไนซ์เพื่อให้สมาร์ท โปรโตคอลนี้ส่วนใหญ่ใช้ในการสื่อสารกับเซ็นเซอร์หรืออุปกรณ์อื่น ๆ ที่ต้องส่งข้อมูลไปยังผู้เชี่ยวชาญ มีประโยชน์มากเมื่อไมโครคอนโทรลเลอร์ต้องสื่อสารกับโมดูลทาสอื่น ๆ จำนวนมากโดยใช้สายไฟขั้นต่ำเท่านั้น หากคุณกำลังมองหาการสื่อสารระยะไกลคุณควรลองใช้ RS232 และหากคุณกำลังมองหาการสื่อสารที่เชื่อถือได้มากขึ้นคุณควรลองใช้โปรโตคอล SPI
I2C ใน Arduino
ภาพด้านล่างแสดงพิน I2C ที่มีอยู่ใน Arduino UNO
สาย I2C | ปักหมุดใน Arduino |
SDA | A4 |
SCL | A5 |
ก่อนที่เราจะเริ่มเขียนโปรแกรม I2C โดยใช้ Arduino สองตัว เราจำเป็นต้องเรียนรู้เกี่ยวกับไลบรารี Wire ที่ใช้ใน Arduino IDE
ห้องสมุด
1. Wire.begin (ที่อยู่):
ใช้: ไลบรารีนี้ใช้สำหรับการสื่อสารกับอุปกรณ์ I2C สิ่งนี้เริ่มต้นไลบรารี Wire และเข้าร่วมบัส I2C ในฐานะมาสเตอร์หรือทาส
แอดเดรส: แอดเดรสทาส 7 บิตเป็นทางเลือกและหากไม่ได้ระบุแอดเดรสก็จะรวมบัสเป็นมาสเตอร์เช่นนี้
2. Wire.read ():
ใช้:ฟังก์ชั่นนี้ใช้เพื่ออ่านไบต์ที่ได้รับจากอุปกรณ์หลักหรืออุปกรณ์ทาสไม่ว่าจะถูกส่งจากอุปกรณ์ทาสไปยังอุปกรณ์หลักหลังจากเรียกไปยัง requestFrom () หรือถูกส่งจากต้นแบบไปยังทาส
3. Wire.write ():
ใช้:ฟังก์ชั่นนี้ใช้เพื่อเขียนข้อมูลไปยังอุปกรณ์ทาสหรืออุปกรณ์หลัก
Slave to Master: Slave เขียนข้อมูลไปยัง Master เมื่อใช้ Wire.RequestFrom () ใน master
Master to Slave:สำหรับการส่งจากอุปกรณ์ต้นแบบไปยังอุปกรณ์ Slave Wire.write () ใช้ระหว่างการโทรไปยัง Wire.beginTransmission () และ Wire.endTransmission ()
Wire.write ()สามารถเขียนเป็น:
- Wire.write (ค่า)
value: ค่าที่จะส่งเป็นไบต์เดียว
- Wire.write (สตริง):
string: สตริงที่จะส่งเป็นชุดไบต์
- Wire.write (ข้อมูลความยาว):
ข้อมูล: อาร์เรย์ของข้อมูลที่จะส่งเป็นไบต์
ความยาว: จำนวนไบต์ที่จะส่ง
4. Wire.beginTransmission (ที่อยู่):
ใช้:ฟังก์ชั่นนี้ใช้เพื่อเริ่มการส่งข้อมูลไปยังอุปกรณ์ I2C ด้วยที่อยู่ของทาสที่กำหนด ต่อจากนั้นสร้างคิวของไบต์สำหรับการส่งกับ การเขียน () ฟังก์ชั่นแล้วส่งพวกเขาโดยการเรียก endTransmission () ฟังก์ชั่น ที่อยู่ 7 บิตของอุปกรณ์จะถูกส่ง
5. Wire.endTransmission ();
ใช้:ฟังก์ชันนี้ใช้เพื่อยุติการส่งไปยังอุปกรณ์ทาสที่เริ่มต้นโดย startTransmission () และส่งไบต์ที่จัดคิวโดย Wire.write ()
6. Wire.onRequest ();
ใช้:ฟังก์ชันนี้ถูกเรียกเมื่อมาสเตอร์ร้องขอข้อมูลโดยใช้ Wire.requestFrom () จากอุปกรณ์ทาส ที่นี่เราสามารถรวม ฟังก์ชัน Wire.write () เพื่อส่งข้อมูลไปยังต้นแบบ
7. Wire.onReceive ();ใช้:ฟังก์ชันนี้จะถูกเรียกเมื่ออุปกรณ์ทาสได้รับข้อมูลจากต้นแบบ ที่นี่เราสามารถรวม Wire.read (); ฟังก์ชั่นอ่านข้อมูลที่ส่งมาจากมาสเตอร์
8. Wire.requestFrom (ที่อยู่ปริมาณ);
ใช้:ฟังก์ชันนี้ใช้ในต้นแบบเพื่อขอไบต์จากอุปกรณ์ทาส ฟังก์ชัน Wire.read () ใช้เพื่ออ่านข้อมูลที่ส่งจากอุปกรณ์ทาส
ที่อยู่: ที่อยู่ 7 บิตของอุปกรณ์ที่จะขอไบต์จาก
ปริมาณ: จำนวนไบต์ที่ต้องการ
ส่วนประกอบที่จำเป็น
- Arduino Uno (2-Nos)
- โมดูลจอแสดงผล LCD 16X2
- โพเทนชิออมิเตอร์ 10K (4-Nos)
- เขียงหั่นขนม
- การเชื่อมต่อสายไฟ
แผนภูมิวงจรรวม
คำอธิบายการทำงาน
ที่นี่สำหรับการสาธิตการสื่อสาร I2C ใน Arduinoเราใช้ Arduino UNO สองตัวพร้อมจอแสดงผล LCD 16X2 สองจอติดกันและใช้โพเทนชิโอมิเตอร์สองตัวที่ arduino ทั้งสองเพื่อกำหนดค่าการส่ง (0 ถึง 127) จาก master ไปยัง slave และ slave ถึง master โดยการเปลี่ยนแปลง โพเทนชิออมิเตอร์
เรารับค่าอนาล็อกอินพุตที่ขา arduino A0 จาก (0 ถึง 5V) โดยใช้โพเทนชิออมิเตอร์และแปลงเป็นค่าอนาล็อกเป็นดิจิตอล (0 ถึง 1023) จากนั้นค่า ADC เหล่านี้จะถูกแปลงเป็น (0 ถึง 127) ต่อไปเนื่องจากเราสามารถส่งข้อมูล 7 บิตผ่านการสื่อสาร I2C เท่านั้น การสื่อสาร I2C เกิดขึ้นผ่านสายไฟสองเส้นที่พิน A4 และ A5 ของ Arduino ทั้งสอง
ค่าที่ LCD ของ Slave Arduino จะเปลี่ยนไปโดยการเปลี่ยน POT ที่ด้านต้นแบบและในทางกลับกัน
การเขียนโปรแกรม I2C ใน Arduino
บทช่วยสอนนี้มีสองโปรแกรมหนึ่งสำหรับ Arduino หลักและอื่น ๆ สำหรับ Arduino ทาส โปรแกรมที่สมบูรณ์แบบสำหรับทั้งสองฝ่ายจะได้รับในตอนท้ายของโครงการนี้กับที่วิดีโอสาธิต
คำอธิบายการเขียนโปรแกรม Master Arduino
1.ก่อนอื่นเราต้องรวมไลบรารี Wireสำหรับใช้ฟังก์ชันการสื่อสาร I2C และไลบรารี LCD สำหรับการใช้ฟังก์ชัน LCD กำหนดพิน LCD สำหรับ LCD 16x2 ด้วย เรียนรู้เพิ่มเติมเกี่ยวกับการเชื่อมต่อ LCD กับ Arduino ที่นี่
# รวม
2. ในการตั้งค่าเป็นโมฆะ ()
- เราเริ่มการสื่อสารแบบอนุกรมที่ Baud Rate 9600
Serial.begin (9600);
- ต่อไปเราจะเริ่มการสื่อสาร I2C ที่พิน (A4, A5)
Wire.begin (); // เริ่มการสื่อสาร I2C ที่พิน (A4, A5)
- ต่อไปเราจะเริ่มต้นโมดูลจอแสดงผล LCD ในโหมด 16X2 และแสดงข้อความต้อนรับและล้างหลังจากห้าวินาที
lcd.begin (16,2); // เริ่มต้นการแสดงผล LCD lcd.setCursor (0,0); // ตั้งค่าเคอร์เซอร์ที่บรรทัดแรกของ Display lcd.print ("Circuit Digest"); // พิมพ์ CIRCUIT DIGEST ใน LCD lcd.setCursor (0,1); // ตั้งค่าเคอร์เซอร์ที่บรรทัดที่สองของ Display lcd.print ("I2C 2 ARDUINO"); // พิมพ์ I2C ARDUINO ใน ความล่าช้าของ LCD (5000); // หน่วงเวลา 5 วินาทีlcd.clear (); // ล้างหน้าจอ LCD
3. ในโมฆะลูป ()
- ก่อนอื่นเราต้องรับข้อมูลจาก Slave ดังนั้นเราจึงใช้ requestFrom () กับที่อยู่ทาส 8 และเราขอหนึ่งไบต์
Wire.requestFrom (8,1);
ค่าที่ได้รับจะอ่านโดยใช้ Wire.read ()
ไบต์ MasterReceive = Wire.read ();
- ต่อไปเราต้องอ่านค่าอนาล็อกจากต้นแบบ arduino POT ที่ติดกับพิน A0
int potvalue = analogRead (A0);
เราแปลงค่านั้นในรูปของหนึ่งไบต์เป็น 0 ถึง 127
ไบต์ MasterSend = แผนที่ (potvalue, 0,1023,0,127);
- ต่อไปเราต้องส่งค่าที่แปลงแล้วดังนั้นเราจึงเริ่มการส่งด้วยทาส arduino พร้อมที่อยู่ 8
Wire.beginTransmission (8); Wire.write (MasterSend); Wire.endTransmission ();
- ต่อไปเราจะแสดงค่าที่ได้รับจากทาส arduino ด้วยความล่าช้า 500 ไมโครวินาทีและเราจะรับและแสดงค่าเหล่านั้นอย่างต่อเนื่อง
lcd.setCursor (0,0); // กำหนด Currsor ที่บรรทัดหนึ่งของ LCD lcd.print (">> Master <<"); // พิมพ์ >> Master << ที่ LCD lcd.setCursor (0,1); // ตั้งค่าเคอร์เซอร์ที่บรรทัดที่สองของ LCD lcd.print ("SlaveVal:"); // พิมพ์ SlaveVal: ใน LCD lcd.print (MasterReceive); // พิมพ์ MasterReceive ใน LCD ที่ได้รับจาก Slave Serial.println ("Master received From Slave"); // พิมพ์ใน Serial Monitor Serial.println (MasterReceive); ล่าช้า (500); lcd.clear ();
คำอธิบายการเขียนโปรแกรม Slave Arduino
1. เช่นเดียวกับมาสเตอร์ก่อนอื่นเราต้องรวมไลบรารี Wireสำหรับใช้ฟังก์ชันการสื่อสาร I2C และไลบรารี LCD สำหรับการใช้ฟังก์ชัน LCD กำหนดพิน LCD สำหรับ LCD 16x2 ด้วย
# รวม
2. ในการตั้งค่าเป็นโมฆะ ()
- เราเริ่มการสื่อสารแบบอนุกรมที่ Baud Rate 9600
Serial.begin (9600);
- ต่อไปเราจะเริ่มการสื่อสาร I2C ที่พิน (A4, A5) ด้วยที่อยู่ทาสเป็น 8 ที่นี่สิ่งสำคัญคือต้องระบุที่อยู่ของทาส
Wire.begin (8);
ต่อไปเราต้องเรียกใช้ฟังก์ชันเมื่อ Slave ได้รับค่าจาก Master และเมื่อ Master ขอค่าจาก Slave
Wire.onReceive (รับเหตุการณ์); Wire.onRequest (requestEvent);
- ต่อไปเราจะเริ่มต้นโมดูลจอแสดงผล LCD ในโหมด 16X2 และแสดงข้อความต้อนรับและล้างหลังจากห้าวินาที
lcd.begin (16,2); // เริ่มต้นการแสดงผล LCD lcd.setCursor (0,0); // ตั้งค่าเคอร์เซอร์ที่บรรทัดแรกของ Display lcd.print ("Circuit Digest"); // พิมพ์ CIRCUIT DIGEST ใน LCD lcd.setCursor (0,1); // ตั้งค่าเคอร์เซอร์ที่บรรทัดที่สองของ Display lcd.print ("I2C 2 ARDUINO"); // พิมพ์ I2C ARDUINO ใน ความล่าช้าของ LCD (5000); // หน่วงเวลา 5 วินาทีlcd.clear (); // ล้างหน้าจอ LCD
3.ต่อไปเรามีสองฟังก์ชั่นหนึ่งสำหรับการร้องขอเหตุการณ์และอีกหนึ่งฟังก์ชันสำหรับรับเหตุการณ์
สำหรับการร้องขอกิจกรรม
เมื่อ Master request value จาก slave ฟังก์ชันนี้จะถูกเรียกใช้งาน ฟังก์ชั่นนี้รับค่าอินพุตจาก Slave POT และแปลงเป็น 7 บิตและส่งค่านั้นไปยัง master
เป็นโมฆะ requestEvent () { int potvalue = analogRead (A0); ไบต์ SlaveSend = แผนที่ (potvalue, 0,1023,0,127); Wire.write (SlaveSend); }
สำหรับกิจกรรมรับ
เมื่อ Master ส่งข้อมูลไปยัง Slave พร้อม Slave Address (8) ฟังก์ชันนี้จะถูกเรียกใช้งาน ฟังก์ชั่นนี้จะอ่านค่าที่ได้รับจากต้นแบบและเก็บในตัวแปรชนิดไบต์
โมฆะ getEvent (int howMany { SlaveReceived = Wire.read (); }
4. ใน Void loop ():
เราแสดงค่าที่ได้รับจากต้นแบบอย่างต่อเนื่องในโมดูลจอแสดงผล LCD
ห่วงเป็นโมฆะ (โมฆะ) { lcd.setCursor (0,0); // กำหนด Currsor ที่บรรทัดหนึ่งของ LCD lcd.print (">> Slave <<"); // พิมพ์ >> Slave << ที่ LCD lcd.setCursor (0,1); // ตั้งค่าเคอร์เซอร์ที่บรรทัดที่สองของ LCD lcd.print ("MasterVal:"); // พิมพ์ MasterVal: ใน LCD lcd.print (SlaveReceived); // พิมพ์ค่า SlaveReceived ใน LCD ที่ได้รับจาก Master Serial.println ("Slave received From Master:"); // พิมพ์ใน Serial Monitor Serial.println (SlaveReceived); ล่าช้า (500); lcd.clear (); }
ด้วยการหมุนโพเทนชิออมิเตอร์ที่ด้านหนึ่งคุณจะเห็นค่าที่แตกต่างกันบน LCD อีกด้านหนึ่ง:
นี่คือวิธีที่การสื่อสาร I2C เกิดขึ้นใน Arduinoที่นี่เราได้ใช้ Arduinos สองตัวเพื่อแสดงให้เห็นไม่เพียง แต่การส่งข้อมูล แต่ยังรับข้อมูลโดยใช้การสื่อสาร I2C ตอนนี้คุณสามารถเชื่อมต่อเซ็นเซอร์ I2C กับ Arduino ได้แล้ว
การเข้ารหัสที่สมบูรณ์สำหรับ Master และ Slave Arduino มีให้ด้านล่างพร้อมวิดีโอสาธิต