Mục lục
- 1
- 1.1
- 2
- 2.1
- 2.2
- 2.3
I. I2C LÀ GÌ?
Tất nhiên là đã có bài viết ra mắt về I2C trên Arduino. vn Tuy nhiên bài viết này mình xin nói về 1 hướng khác. Các bạn chăm sóc hoàn toàn có thể xem lại những bài viết về I2C của những tác giả khác nhé !
Đầu năm 1980 Phillips đã tăng trưởng một chuẩn tiếp xúc nối tiếp 2 dây được gọi là I2C. I2C là tên viết tắt của cụm từ Inter-Intergrated Circuit. Đây là đường Bus tiếp xúc giữa những IC với nhau. I2C mặc dầu được tăng trưởng bới Philips, nhưng nó đã được rất nhiều nhà phân phối IC trên quốc tế sử dụng. I2C trở thành một chuẩn công nghiệp cho những tiếp xúc điều khiển và tinh chỉnh, hoàn toàn có thể kể ra đây một vài tên tuổi ngoài Philips như : Texas Intrument ( TI ), MaximDallas, analog Device, National Semiconductor … Bus I2C được sử dụng làm bus tiếp xúc ngoại vi cho rất nhiều loại IC khác nhau như những loại Vi điều khiển và tinh chỉnh 8051, PIC, AVR, ARM. .. chip nhớ như : RAM tĩnh ( Static Ram ), EEPROM, bộ chuyển đổi tựa như số ( ADC ), số tựa như ( DAC ), IC điểu khiển LCD, LED. ..
Cấu tạo và nguyên lý hoạtđộng
I2C sử dụng hai đường truyền tín hiệu :
- Một đường xung nhịp đồng hồ(SCL) chỉ do Master phát đi ( thông thường ở 100kHz và 400kHz. Mức cao nhất là 1Mhz và 3.4MHz).
- Một đường dữ liệu(SDA) theo 2 hướng.
Có rất nhiều thiết bị có thể cùng được kết nối vào một bus I2C, tuy nhiên sẽ không xảy ra chuyện nhầm lẫn giữa các thiết bị, bởi mỗi thiết bị sẽ được nhận ra bởỉ một địa chỉ duy nhất với một quan hệ chủ/tớ tồn tại trong suốt thời gian kết nối. Mỗi thiết bị có thể hoạt động như là thiết bị nhận hoặc truyền dữ liệu hay có thể vừa truyền vừa nhận. Hoạt động truyền hay nhận còn tùy thuộc vào việc thiết bị đó là chủ (master) hãy tớ (slave).
Bạn đang đọc: Giao tiếp I2C với nhiều module | Cộng đồng Arduino Việt Nam
Một thiết bị hay một IC khi liên kết với bus I2C, ngoài một địa chỉ ( duy nhất ) để phân biệt, nó còn được thông số kỹ thuật là thiết bị chủ hay tớ. Tại sao lại có sự phân biệt này ? Đó là vì trên một bus I2C thì quyền điều khiển và tinh chỉnh thuộc về thiết bị chủ. Thiết bị chủ nắm vai trò tạo xung đồng hồ đeo tay cho toàn mạng lưới hệ thống, khi giữa hai thiết bị chủ-tớ tiếp xúc thì thiết bị chủ có trách nhiệm tạo xung đồng hồ đeo tay và quản trị địa chỉ của thiết bị tớ trong suốt quy trình tiếp xúc. Thiết bị chủ giữ vai trò dữ thế chủ động, còn thiết bị tớ giữ vai trò bị động trong việc tiếp xúc .
Về triết lý lẫn trong thực tiễn I²C sử dụng 7 bit để định địa chỉ, do đó trên một bus hoàn toàn có thể có tới 2 ^ 7 địa chỉ tương ứng với 128 thiết bị hoàn toàn có thể liên kết, nhưng chỉ có 112, 16 địa chỉ còn lại được sử dụng vào mục tiêu riêng. Bit còn lại pháp luật việc đọc hay ghi tài liệu ( 1 là write, 0 là read )
Điểm mạnh của I²C chính là hiệu suất và sự đơn thuần của nó : một khối điều khiển và tinh chỉnh TT hoàn toàn có thể tinh chỉnh và điều khiển cả một mạng thiết bị mà chỉ cần hai lối ra điều khiển và tinh chỉnh .
Ngoài ra I2C còn có chính sách 10 bit địa chỉ tương tự với 1024 địa chỉ, tương tự như như 7 bit, chỉ có 1008 thiết bị hoàn toàn có thể liên kết, còn lại 16 địa chỉ sẽ dùng để sử dụng mục tiêu riêng ( Mình chưa rõ lắm )
Vậy, làm thế nào để nó hoàn toàn có thể tiếp xúc với nhiều thiết bị ?
II. LÀM THẾ NÀO?
Vâng, như mình đã nói ở trên, Mỗi thiết bị có 1 địa chỉ được cài sẵn hoặc 1 địa chỉ thiết bị duy nhất để thiết bị chủ ( Master ) hoàn toàn có thể tiếp xúc. 2 chân SDA VÀ SCL là 2 chân của tiếp xúc I2C, trong đó chân SCL là chân Clock, có tính năng đồng điệu hóa việc truyền tài liệu giữa những thiết bị, và việc tạo ra xung clock đó là do thiết bị chủ ( Master ). Chân còn lại là chân SDA là chân truyền tài liệu ( DATA ). 2 chân này luôn hoạt động giải trí ở chính sách mở, thế cho nên để sử dụng được cần phải có trở kéo. tức là nối + 5 v => trở => I2C bởi những thiết bị trên bus i2c hoạt động giải trí ở mức thấp. Giá trị thường được sử dụng cho những điện trở là từ 2K cho vận tốc vào thời gian 400 kbps, và 10K cho vận tốc thấp hơn khoảng chừng 100 kbps .
Hãy tưởng tượng bạn là nhân viên cấp dưới phát bưu phẩm, đến 1 thành phố trên tay có bưu phẩm cần chuyển phát. Tính năng của bạn hoàn toàn có thể phát và nhận bưu phẩm để chuyển đi cho cả thành phố, tuy nhiên, yếu tố quan trọng là bạn cần phải có địa chỉ. mỗi 1 thiết bị sẽ có 1 địa chỉ riêng để thiết bị chủ hoàn toàn có thể truy vấn để lấy tài liệu
Hải Đăng PPK
Ví dụ cảm biến gia tốc ADXL345
Có 1 địa chỉ duy nhất cho riêng module và đồng thời bổ xung bên trong có 3 địa chỉ riêng không liên quan gì đến nhau cho những trục X, Y, Z. Nếu tất cả chúng ta cần đọc những tài liệu từ trục X, trước hết tất cả chúng ta cần đến địa chỉ chính của Module, sau đó mới đến địa chỉ của trục X. Việc tìm tên những địa chỉ này những bạn cần tìm trong datasheet của linh phụ kiện. Đây là datasheet của cảm ứng tần suất ADXL345 Mở ra đọc tại mục Register map những bạn hoàn toàn có thể thấy địa chỉ của trục X là 0x32 và 0x33
0x32 DATAX0 X-Axis Data 0
0x33 DATAX1 X-Axis Data 1
Trong ví dụ dưới đây mình sẽ đưa ra 1 trường hợp về việc liên kết arduino với 2 cảm ứng ( Cảm biến tần suất 10 bậc tự do GY – 80 và Cảm biến tần suất 6 bậc tự do GY521 ), cả 2 cảm ứng đều sử dụng tiếp xúc I2C
Cảm biến gia tốc GY-521
Cảm biến gia tốc GY-80
Dưới đây là cách kết nối 2 module với arduino, các bạn có thể thấy hơi mâu thuẫn so với ban đầu mình nói, tại sao không có điện trở nào kéo ở đây? Thực tế thì bên trong module đã có điện trở kéo, vì thế chúng ta không cần kéo gì nữa cả
Bây giờ để tiếp xúc với chúng, ta cần phải biết được địa chỉ của nó là gì, so với mỗi 1 cảm ứng trên 1 module kia sẽ có 1 địa chỉ riêng. Các bạn cần phải tìm chúng trong datasheet của mỗi loại. Ở đây mình đưa ra những địa chỉ của những cảm ứng để những bạn tiện theo dõi
Đối với GY-80, có 4 địa chỉ : 0x53 cho cảm ứng tần suất, 0x69 cho 3 trục con quay, 0x1 E 3 trục Từ trường và 0x77 cho cảm ứng áp lực đè nén và nhiệt kế
Đối với GY-521, chỉ có một địa chỉ và đó là 0x68. Các bạn cũng hoàn toàn có thể kiểm tra và xác lập được địa chỉ của chúng bằng cách sử dụng bản sketch mẫu I2C Scanner. Nạp code đó vào và nó sẽ tự cho những bạn biết những địa chỉ có trên thiết bị .
Sau khi đã tìm thấy địa chỉ của những thiết bị, tất cả chúng ta cũng cần phải tìm ra địa chỉ của những thanh ghi bên trong của chúng để đọc tài liệu. Ví dụ, nếu tất cả chúng ta muốn đọc tài liệu cho trục X từ những cảm ứng 3 trục tần suất của GY-80, tất cả chúng ta cần phải tìm địa chỉ nơi tài liệu của trục X được tàng trữ. Bằng cách đọc datasheet của những cảm ứng của GY-80 và ở đây là datasheet của cảm ứng 3 trục tần suất ADXL345 mà mình đã nêu ở phần đầu bài viết, tất cả chúng ta hoàn toàn có thể thấy rằng tài liệu cho trục X được tàng trữ trong hai thanh ghi, DATAX0 với một địa chỉ 0x32 và DATAX1 với một địa chỉ 0x33 .
Bây giờ tất cả chúng ta chỉ việc code và hãy nghiên cứu và điều tra xem code đã làm những gì ?
#include int ADXLAddress = 0x53; // Địa chỉ của cảm biến gia tốc trong module GY80#define X_Axis_Register_DATAX0 0x32 // địa chỉ của data0 trục X trong cảm biến gia tốc ADXL345 trong module GY-80#define X_Axis_Register_DATAX1 0x33 //địa chỉ của data1 trục X trong cảm biến gia tốc ADXL345 trong module GY-80#define Power_Register 0x2D // thanh ghi điều khiển năng lượng cung cấpint X0,X1,X_out;void setup() { Wire.begin(); // Khởi tạo thư viện WIRE Serial.begin(9600); delay(100); // kích hoạt tính năng đo lường Wire.beginTransmission(ADXLAddress);//bắt đầu việc truyền tải yêu cầu tới các cảm biến Wire.write(Power_Register); // Cho phép đo Wire.write(8); Wire.endTransmission();}void loop() { Wire.beginTransmission(ADXLAddress); // Bắt đầu truyền đến cảm biếnr //Thu thập dữ liệu từ các thanh ghi Wire.write(X_Axis_Register_DATAX0); Wire.write(X_Axis_Register_DATAX1); Wire.endTransmission(); // Kết thúc việc truyền dữ liệu từ 2 thanh ghi Wire.requestFrom(ADXLAddress,2); // Yêu cầu truyền 2 byte từ 2 thanh ghi if(Wire.available()<=2) { // X0 = Wire.read(); // Đọc dữ liệu từ thanh ghi X1 = Wire.read(); } Serial.print("X0= "); Serial.print(X0); Serial.print(" X1= "); Serial.println(X1);}
Việc lấy tài liệu từ những cảm ứng trên module khác cũng tựa như. Như vậy những bạn đã biết cách sử dụng tiếp xúc I2C. Và rõ ràng 2 module này có vẻ như không được nhiều bạn chăm sóc sử dụng lắm bởi giá tiền cũng như là về yếu tố những bạn cần ứng dụng đến không nhiều. Vì thế mình xin liên tục đưa ra ví dụ thứ 2 mà khá nhiều bạn còn do dự. Đó là việc sử dụng LCD 1602 module i2c và module thời hạn thực DS1307 với arduino uno .
Trước khi đọc tiếp phần này, mình lại 1 lần nữa mong ước những bạn đọc datasheet của linh phụ kiện .
Ở đây, so với LCD1602 dùng module I2C. địa chỉ tùy thuộc vào jump những bạn cắm trên module i2c. Các bạn hoàn toàn có thể đọc datasheet của LCD này tại đây Mình lấy ví dụ địa chỉ OPEN là 0x27 Hoặc nó hoàn toàn có thể biến hóa từ 0X20 – 0X27
Với module thời gian thực DS1307 các bạn có thể đọc datasheet tại đây. Địa chỉ của module DS1307 là 0x68. Làm thế nào để biết nó là 0X68 thì các bạn hãy đọc lại phần đầu bài viết, phần I2C SCANNER.. Bên trong DS1307 sẽ có các địa chỉ để đọc các giá trị giờ, phút, giây…
Xem thêm: PTU là gì
Như vậy để liên kết 2 module cùng dùng i2c những bạn chỉ cần gọi địa chỉ của LCD là 0x27, địa chỉ của DS1307 là 0X68 là hoàn toàn có thể sử dụng đồng thời 2 module trên cùng 2 chân SDA, SCL của Arduino
#include #include "RTClib.h"#include LiquidCrystal_I2C lcd(0x20,16,2); // 0x27 là địa chỉ của lcd 16x2RTC_DS1307 RTC;void setup () { lcd.init(); lcd.backlight(); //đèn nền bật // cài đặt số cột và số dòng lcd.begin(16, 2); // in logo lên màn hình lcd.print("www.arduino.vn"); lcd.setCursor(0, 1); lcd.print("haidangppk"); delay (2500); lcd.clear(); // Serial.begin(9600); Wire.begin();Wire.beginTransmission(0x68);// địa chỉ của ds1307Wire.write(0x07); // Wire.write(0x10); // Wire.endTransmission(); RTC.begin(); if (! RTC.isrunning()) { Serial.println("RTC is NOT running!"); RTC.adjust(DateTime(__DATE__, __TIME__)); }}void loop () { DateTime now = RTC.now(); lcd.setCursor(6, 0); lcd.print(now.hour(), DEC); lcd.print(":"); lcd.print(now.minute(), DEC); lcd.print(":"); lcd.print(now.second(), DEC); lcd.print(" "); lcd.setCursor(5, 1); lcd.print(now.day(), DEC); lcd.print("/"); lcd.print(now.month(), DEC); lcd.print("/"); lcd.print(now.year(), DEC); lcd.print(""); delay(1000);}
Bài viết của mình hoàn toàn có thể có sai sót, mong những bạn góp ý. Chúc những bạn thành công xuất sắc !
Trần Hải Đăng