Giới thiệu
Trong hướng dẫn này, bạn sẽ tìm hiểu tất cả về giao thức truyền thông I2C, lý do bạn muốn sử dụng nó và cách nó được triển khai.
Giao thức Mạch tích hợp liên kết (I2C) là giao thức nhằm cho phép nhiều mạch tích hợp kỹ thuật số "peripheral" ("chip") giao tiếp với một hoặc nhiều chip "controller". Giống như Giao diện ngoại vi nối tiếp (SPI), nó chỉ dành cho liên lạc khoảng cách ngắn trong một thiết bị. Giống như Giao diện nối tiếp không đồng bộ (chẳng hạn như RS-232 hoặc UART), nó chỉ yêu cầu hai dây tín hiệu để trao đổi thông tin.
Tại sao nên sử dụng I2C?
Để tìm hiểu lý do tại sao một người có thể muốn giao tiếp qua I2C, trước tiên bạn phải so sánh nó với các tùy chọn có sẵn khác để xem nó khác biệt như thế nào.
Có gì sai với cổng UART nối tiếp?
Bởi vì các cổng nối tiếp không đồng bộ (không có dữ liệu clock được truyền đi), các thiết bị sử dụng chúng phải đồng ý trước về tốc độ dữ liệu. Hai thiết bị cũng phải có xung nhịp gần giống nhau và sẽ giữ nguyên như vậy--sự khác biệt quá mức giữa tốc độ xung nhịp ở hai đầu sẽ khiến dữ liệu bị cắt xén hoặc sai.
Các cổng nối tiếp không đồng bộ yêu cầu chi phí phần cứng--UART ở một trong hai đầu tương đối phức tạp và khó triển khai chính xác trong phần mềm nếu cần. Ít nhất một bit START và STOP là một phần của mỗi khung dữ liệu, nghĩa là cần có 10 bit thời gian truyền cho mỗi 8 bit dữ liệu được gửi, điều này sẽ ảnh hưởng đến tốc độ dữ liệu.
Một cốt lõi khác trong các cổng nối tiếp không đồng bộ là chúng vốn dĩ phù hợp với giao tiếp giữa hai và chỉ hai thiết bị. Mặc dù có thể kết nối nhiều thiết bị với một cổng nối tiếp duy nhất, nhưng xung đột bus (trong đó hai thiết bị cố gắng điều khiển cùng một đường cùng lúc) luôn là một vấn đề và phải được xử lý cẩn thận để tránh làm hỏng các thiết bị được đề cập, thường thông qua phần cứng bên ngoài.
Cuối cùng, tốc độ dữ liệu là một vấn đề. Mặc dù không có giới hạn về mặt lý thuyết đối với giao tiếp nối tiếp không đồng bộ, hầu hết các thiết bị UART chỉ hỗ trợ một bộ tốc độ truyền cố định nhất định và tốc độ cao nhất trong số này thường là khoảng 230400 bit mỗi giây.
Có chuyện gì với SPI vậy?
Hạn chế rõ ràng nhất của SPI là số lượng chân cần thiết. Việc kết nối một bộ điều khiển [1] với một thiết bị ngoại vi [1] bằng bus SPI cần có 4 đường dây, mỗi thiết bị ngoại vi bổ sung yêu cầu thêm một chân I/O chọn chip trên bộ điều khiển. Sự gia tăng nhanh chóng của các kết nối chân cắm khiến nó không được ưa chuộng trong các tình huống phải kết nối nhiều thiết bị với một bộ điều khiển. Ngoài ra, số lượng kết nối lớn cho mỗi thiết bị có thể khiến tín hiệu định tuyến trở nên khó khăn hơn trong các tình huống bố trí PCB chật hẹp.
SPI chỉ cho phép một bộ điều khiển trên bus, nhưng nó hỗ trợ số lượng thiết bị ngoại vi tùy ý (chỉ phụ thuộc vào khả năng điều khiển của các thiết bị được kết nối với bus và số lượng chân chọn chip có sẵn).
SPI phù hợp với các kết nối song công hoàn toàn (gửi và nhận dữ liệu đồng thời) tốc độ dữ liệu cao, hỗ trợ tốc độ xung nhịp lên tới 10 MHz (và do đó là 10 triệu bit mỗi giây) cho một số thiết bị và tốc độ tăng dần theo cấp số nhân. Phần cứng ở hai đầu thường là một thanh ghi dịch chuyển rất đơn giản, cho phép thực hiện dễ dàng trong phần mềm.
I2C - Điều tuyệt vời nhất của cả hai thế giới!
I2C chỉ yêu cầu hai dây, giống như nối tiếp không đồng bộ, nhưng hai dây đó có thể hỗ trợ tới 1008 thiết bị ngoại vi. Ngoài ra, không giống như SPI, I2C có thể hỗ trợ hệ thống đa bộ Controller, cho phép nhiều bộ Controller [1] giao tiếp với tất cả các thiết bị Peripheral [1] trên bus (mặc dù các thiết bị điều khiển không thể nói chuyện với nhau qua bus và phải luân phiên nhau sử dụng các tuyến bus).
Tốc độ dữ liệu giảm giữa nối tiếp không đồng bộ và SPI; hầu hết các thiết bị I2C có thể giao tiếp ở tần số 100kHz hoặc 400kHz. Có một số chi phí với I2C; cứ 8 bit dữ liệu được gửi đi thì phải truyền thêm một bit dữ liệu (bit "ACK/NACK" mà chúng ta sẽ thảo luận sau).
Phần cứng cần thiết để triển khai I2C phức tạp hơn SPI nhưng ít hơn so với phần cứng nối tiếp không đồng bộ. Nó có thể được thực hiện khá đơn giản trong phần mềm.
Tóm tắt lịch sử của I2C
I2C ban đầu được Philips phát triển vào năm 1982 cho nhiều loại chip Philips. Thông số kỹ thuật ban đầu chỉ cho phép liên lạc 100kHz và chỉ cung cấp cho các địa chỉ 7 bit, giới hạn số lượng thiết bị trên bus ở mức 112 (có một số địa chỉ dành riêng sẽ không bao giờ được sử dụng cho các địa chỉ I2C hợp lệ ) . Năm 1992, thông số kỹ thuật công khai đầu tiên được xuất bản, bổ sung chế độ nhanh 400kHz cũng như không gian địa chỉ 10 bit mở rộng. Phần lớn thời gian (ví dụ: trong thiết bị ATMega328 trên nhiều bo mạch tương thích với Arduino), hỗ trợ thiết bị cho I2C kết thúc tại thời điểm này. Có ba chế độ bổ sung được chỉ định:
- fast-mode plus, at 1MHz
- high-speed mode, at 3.4MHz
- ultra-fast mode, at 5MHz
Ngoài "vanilla" I2C, Intel đã giới thiệu một biến thể vào năm 1995 có tên " System Management Bus" (SMBus) . SMBus là định dạng được kiểm soát chặt chẽ hơn, nhằm tối đa hóa khả năng dự đoán liên lạc giữa các IC hỗ trợ trên bo mạch chủ PC. Sự khác biệt đáng kể nhất giữa SMBus là nó giới hạn tốc độ từ 10kHz đến 100kHz, trong khi I2C có thể hỗ trợ các thiết bị từ 0kHz đến 5 MHz. SMBus bao gồm chế độ clock timeout khiến các hoạt động tốc độ thấp trở nên bất hợp pháp, mặc dù nhiều thiết bị SMBus vẫn sẽ hỗ trợ chế độ này để tối đa hóa khả năng tương tác với các hệ thống I2C nhúng.
I2C ở cấp độ phần cứng
Tín hiệu
Mỗi bus I2C bao gồm hai tín hiệu: SDA và SCL. SDA (Dữ liệu nối tiếp) là tín hiệu dữ liệu và SCL (Clock nối tiếp) là tín hiệu đồng hồ. Tín hiệu clock luôn được tạo ra bởi bộ điều khiển bus hiện tại; một số thiết bị ngoại vi đôi khi có thể buộc clock ở mức thấp để trì hoãn việc bộ điều khiển gửi thêm dữ liệu (hoặc cần thêm thời gian để chuẩn bị dữ liệu trước khi bộ điều khiển cố gắng hết giờ). Điều này được gọi là "clock stretching" và được mô tả trên trang giao thức.
Không giống như kết nối UART hay SPI, trình điều khiển bus I2C là "open drain", nghĩa là chúng có thể kéo đường tín hiệu tương ứng xuống mức thấp, nhưng không thể đẩy nó lên mức cao. Do đó, không thể xảy ra tranh chấp bus khi một thiết bị đang cố gắng đẩy đường bus lên cao trong khi một thiết bị khác cố gắng kéo nó xuống thấp, loại bỏ khả năng gây hư hỏng cho trình điều khiển hoặc tiêu tán điện năng quá mức trong hệ thống. Mỗi đường tín hiệu có một điện trở kéo lên trên đó, để khôi phục tín hiệu về mức cao khi không có thiết bị nào xác nhận tín hiệu ở mức thấp.
Lưu ý hai điện trở kéo lên trên hai đường truyền.