กับ Arduino สามารถสร้างโครงการจำนวนมาก อย่างที่คุณเคยเห็นถ้าคุณอ่าน Hwlibre การเขียนโปรแกรมไมโครคอนโทรลเลอร์ด้วยวิธีง่ายๆ. แต่ระหว่างการเชื่อมต่อแบบอนาล็อกและดิจิตอลของบอร์ดนี้ hardware libreมีบางอย่างที่ผู้เริ่มต้นหลายคนยังไม่ค่อยรู้จัก เช่น ศักยภาพที่แท้จริงของการเชื่อมต่อ PWM, SPI, พิน RX และ TX ของพอร์ตอนุกรม หรือบัส I2C เอง ดังนั้น ด้วยรายการนี้ อย่างน้อยคุณก็จะสามารถรู้ทุกสิ่งที่คุณต้องการเกี่ยวกับ I2C เป็นอย่างน้อย
กับ บัส I2C คุณสามารถเชื่อมต่อและใช้อุปกรณ์ของบุคคลที่สามจำนวนมากที่มีโปรโตคอลประเภทนี้เพื่อสื่อสารกับบอร์ด Arduino ระหว่างนั้นคุณสามารถเชื่อมต่อเครื่องวัดความเร่งจอแสดงผลตัวนับเข็มทิศและวงจรรวมอื่น ๆ อีกมากมายด้วยสิ่งประดิษฐ์ของ Philips นี้
I2C คืออะไร?
I2C หมายถึงวงจรรวมนั่นคือวงจรรวม เป็นบัสสื่อสารข้อมูลแบบอนุกรมที่พัฒนาขึ้นในปี 1982 โดย บริษัท Philips Semiconductors ซึ่งปัจจุบันคือ NXP Semiconductors หลังจากกำจัดส่วนนี้แล้ว ในตอนแรกมันถูกสร้างขึ้นสำหรับโทรทัศน์ของแบรนด์นี้เพื่อสื่อสารชิปภายในหลาย ๆ ตัวด้วยวิธีง่ายๆ แต่ตั้งแต่ปี 1990 I2C ได้แพร่กระจายและถูกใช้โดยผู้ผลิตหลายราย
ปัจจุบันใช้โดยผู้ผลิตชิปหลายสิบราย สำหรับหลายฟังก์ชั่น Atmel ผู้สร้างไมโครคอนโทรลเลอร์สำหรับบอร์ด Arduino ได้เปิดตัวการกำหนด TWI (Two Wired Interface) เพื่อวัตถุประสงค์ในการออกใบอนุญาตแม้ว่าจะเหมือนกับ I2C ก็ตาม แต่ในปี 2006 สิทธิบัตรเดิมหมดอายุและไม่อยู่ภายใต้ลิขสิทธิ์อีกต่อไปดังนั้นจึงมีการนำคำว่า I2C มาใช้ซ้ำ (เฉพาะโลโก้เท่านั้นที่ยังคงได้รับการคุ้มครอง แต่การใช้งานหรือการใช้คำดังกล่าวจะไม่ถูก จำกัด )
รายละเอียดทางเทคนิคของบัส I2C
El บัส I2C ได้กลายเป็นมาตรฐานอุตสาหกรรมและ Arduino ได้นำมาใช้ สำหรับการสื่อสารกับอุปกรณ์ต่อพ่วงที่ต้องการ ต้องใช้เพียงสองเส้นหรือสายเคเบิลสำหรับการทำงานหนึ่งเส้นสำหรับสัญญาณนาฬิกา (CLK) และอีกเส้นสำหรับส่งข้อมูลแบบอนุกรม (SDA) นี่เป็นข้อได้เปรียบเมื่อเทียบกับการสื่อสารอื่น ๆ เมื่อเทียบกับบัส SPI แม้ว่าการทำงานของมันจะค่อนข้างซับซ้อนกว่าเนื่องจากต้องใช้วงจรเพิ่มเติม
บนรถบัสคันนี้ อุปกรณ์แต่ละเครื่องที่เชื่อมต่อมีที่อยู่ ใช้เพื่อเข้าถึงอุปกรณ์เหล่านี้ทีละเครื่อง ที่อยู่นี้ได้รับการแก้ไขโดยฮาร์ดแวร์แก้ไข 3 บิตสุดท้ายผ่านจัมเปอร์หรือสวิตช์ DIP แม้ว่าซอฟต์แวร์จะทำได้เช่นกัน อุปกรณ์แต่ละเครื่องจะมีที่อยู่ที่ไม่ซ้ำกันแม้ว่าอุปกรณ์หลายเครื่องอาจมีที่อยู่เดียวกันและอาจจำเป็นต้องใช้บัสรองเพื่อหลีกเลี่ยงความขัดแย้งหรือเปลี่ยนแปลงหากเป็นไปได้
นอกจากนี้บัส I2C ยังมี สถาปัตยกรรมประเภท Master-Slave นั่นคือ master-slave ซึ่งหมายความว่าเมื่อเริ่มต้นการสื่อสารโดยอุปกรณ์หลักก็จะสามารถส่งหรือรับข้อมูลจากทาสของมันได้ ทาสจะไม่สามารถเริ่มต้นการสื่อสารได้มีเพียงนายเท่านั้นที่สามารถทำได้และทาสไม่สามารถพูดคุยกันได้โดยตรงหากไม่มีการแทรกแซงของเจ้านาย
หากคุณมี ครูหลายคนบนรถบัสมีเพียงคนเดียวเท่านั้นที่สามารถทำหน้าที่เป็นครูได้ในเวลาเดียวกัน แต่ก็ไม่คุ้มค่าเนื่องจากการเปลี่ยนครูต้องใช้ความซับซ้อนสูงจึงเกิดขึ้นไม่บ่อยนัก
โปรดทราบว่าไฟล์ master ให้สัญญาณนาฬิกาเพื่อซิงโครไนซ์อุปกรณ์ทั้งหมดบนบัส. ซึ่งไม่จำเป็นต้องให้ทาสแต่ละคนมีนาฬิกาเป็นของตัวเอง
โปรโตคอลบัส I2C ยังเล็งเห็นถึงการใช้ตัวต้านทานแบบดึงขึ้นในสายแรงดันไฟฟ้า (Vcc) แม้ว่าตัวต้านทานเหล่านี้มักจะไม่ใช้กับ Arduino ดึงขึ้นเนื่องจากการเขียนโปรแกรมไลบรารี เนื่องจาก Wire เปิดใช้งานภายในด้วยค่า 20-30 k สิ่งนี้อาจอ่อนเกินไปสำหรับบางโปรเจ็กต์ดังนั้นขอบที่เพิ่มขึ้นของสัญญาณจะช้าลงดังนั้นจึงสามารถใช้ความเร็วต่ำและระยะการสื่อสารที่สั้น เพื่อแก้ไขว่าคุณอาจต้องตั้งค่าตัวต้านทานแบบดึงขึ้นภายนอกตั้งแต่ 1k ถึง 4k7
สัญญาณ
La กรอบการสื่อสาร ซึ่งสัญญาณบัส I2C ประกอบด้วยบิตหรือสถานะ (ที่ใช้ใน Arduino เนื่องจากมาตรฐาน I2C อนุญาตให้ผู้อื่น):
- 8 บิต 7 ของ ที่อยู่ ของอุปกรณ์ทาสที่คุณต้องการเข้าถึงเพื่อส่งหรือรับข้อมูลจากอุปกรณ์นั้น ด้วย 7 บิตสามารถสร้างที่อยู่ที่แตกต่างกันได้ถึง 128 รายการเพื่อให้สามารถเข้าถึงอุปกรณ์ 128 เครื่องในทางทฤษฎี แต่สามารถเข้าถึงได้เพียง 112 เครื่องเนื่องจากมีการสงวนไว้ 16 รายการสำหรับการใช้งานพิเศษ และบิตเพิ่มเติมที่ระบุว่าคุณต้องการหรือไม่ ส่งหรือรับ ข้อมูลอุปกรณ์ทาส
- ยังมีอยู่ บิตตรวจสอบความถูกต้องหากไม่ได้ใช้งานการสื่อสารจะไม่สามารถใช้งานได้
- จากนั้น ไบต์ข้อมูล ที่พวกเขาต้องการส่งหรือรับโดยทาส อย่างที่คุณทราบแต่ละไบต์ประกอบด้วย 8 บิต โปรดทราบว่าสำหรับข้อมูลที่ส่งหรือรับทุกๆ 8 บิตหรือ 1 ไบต์จำเป็นต้องมีการตรวจสอบความถูกต้องที่อยู่ ฯลฯ เพิ่มเติมอีก 18 บิตซึ่งหมายความว่าบัสมีความเร็ว จำกัด มาก
- บิตสุดท้ายของ การตรวจสอบ ของการสื่อสาร
นอกจากนี้ความถี่สัญญาณนาฬิกาสำหรับ การส่งสัญญาณคือ 100 Mhz ตามมาตรฐาน แม้ว่าจะมีโหมดที่เร็วกว่าที่ 400 Mhz
ข้อดีและข้อเสียของบัส I2C
ลา ความได้เปรียบ เสียง:
- ความง่าย โดยใช้เพียงสองบรรทัด
- มันมี กลไกที่จะทราบว่าสัญญาณมาถึงหรือไม่ เมื่อเทียบกับโปรโตคอลการสื่อสารอื่น ๆ
ลา ข้อเสีย เสียง:
- ความเร็ว การส่งผ่านที่ค่อนข้างต่ำ
- ไม่ใช่ฟูลดูเพล็กซ์นั่นคือคุณไม่สามารถส่งและรับพร้อมกันได้
- ไม่ใช้ความเท่าเทียมกัน หรือกลไกการตรวจสอบประเภทอื่น ๆ เพื่อให้ทราบว่าบิตข้อมูลที่ได้รับนั้นถูกต้องหรือไม่
I2C บน Arduino
En Arduino ขึ้นอยู่กับรุ่นพินที่สามารถเปิดใช้งานเพื่อใช้บัส I2C นี้แตกต่างกันไป ตัวอย่างเช่น:
- Arduino UNO, นาโน, มินิโปร: A4 ใช้สำหรับ SDA (ข้อมูล) และ A5 สำหรับ SCK (นาฬิกา)
- Arduino Mega: พิน 20 สำหรับ SDA และ 21 สำหรับ SCK
จำไว้ว่าคุณต้องใช้ ใช้ประโยชน์จากห้องสมุด ลวด h สำหรับรหัส Arduino IDE ของคุณแม้ว่าจะมีรหัสอื่นเช่น I2C y i2cdevlib. คุณสามารถอ่านเอกสารของห้องสมุดเหล่านี้หรือบทความของเราเกี่ยวกับโครงการที่คุณสนใจเพื่อขอรับรหัสว่าจะตั้งโปรแกรมอย่างไร
จะทราบที่อยู่ของอุปกรณ์ที่จะใช้กับ I2C ได้อย่างไร?
เพียงคำเตือนสุดท้ายนั่นคือเมื่อคุณซื้อ IC จากผู้ผลิตในยุโรปญี่ปุ่นหรืออเมริกาคุณ ระบุทิศทาง ที่คุณควรใช้สำหรับอุปกรณ์ ในทางกลับกันบางครั้งภาษาจีนไม่ลงรายละเอียดหรือไม่ถูกต้องจึงใช้ไม่ได้ ซึ่งสามารถแก้ไขได้อย่างง่ายดายด้วยเครื่องสแกนที่อยู่เพื่อให้ทราบว่าคุณควรอ้างถึงทิศทางใดในแบบร่าง
La ชุมชน arduino ได้สร้างสิ่งนี้ รหัสเพื่อสแกนที่อยู่และระบุที่อยู่ ด้วยวิธีง่ายๆ แม้ว่าฉันจะแสดงรหัสให้คุณที่นี่:
#include "Wire.h" extern "C" { #include "utility/twi.h" } void scanI2CBus(byte from_addr, byte to_addr, void(*callback)(byte address, byte result) ) { byte rc; byte data = 0; for( byte addr = from_addr; addr <= to_addr; addr++ ) { rc = twi_writeTo(addr, &data, 0, 1, 0); callback( addr, rc ); } } void scanFunc( byte addr, byte result ) { Serial.print("addr: "); Serial.print(addr,DEC); Serial.print( (result==0) ? " Encontrado!":" "); Serial.print( (addr%4) ? "\t":"\n"); } const byte start_address = 8; const byte end_address = 119; void setup() { Wire.begin(); Serial.begin(9600); Serial.print("Escaneando bus I2C..."); scanI2CBus( start_address, end_address, scanFunc ); Serial.println("\nTerminado"); } void loop() { delay(1000); }