Nick Chung gửi vào
- 19109 lượt xem
Qua bài đầu, mình đã giúp các bạn giải quyết được một vấn đề khá quan trọng trong việc sử dụng EEPROM. Bài này sẽ giúp bạn biết cách ghép nhiều module eeprom để tạo ra Super eeprom như đã hứa.
Bây giờ chúng ta bàn về địa chỉ
Trên 1 Bus i2c (2 dây) có thể có tới 128 thiết bị khác nhau cùng dùng chung đường dây.
Lúc này, địa chỉ của mỗi thiết bị sẽ giúp arduino (master) tìm đến và giao tiếp truyền nhận với thiết bị đó (slave). Tất nhiên địa chỉ phải của mỗi thiết bị phải khác nhau.
Dùng chung đường dây có nghĩa là các thiết bị (module) sẽ nối song song với nhau trên đường bus chung, điều này làm tiết kiệm đáng kể lượng dây kết nối với arduino/mcu.
Địa chỉ của ic eeprom trên bus do người dùng thiết lập bằng cách đấu nối các chân A0, A1, A2 với mức điện áp 0v/5v .
Địa chỉ xác định bởi 7 bit
1
|
0
|
1
|
0
|
A2
|
A1
|
A0
|
3 bit đầu là trạng thái của 3 pin
- Bằng 1: Nối pin đó lên điện áp High (5v)
- Bằng 0: Nối pin đó xuống điện áp Low (0v)
Nhà sản xuất đã giới hạn khả năng thiết lập địa chỉ với từng ic:
Bảng 1.1. Các trường hợp cụ thể theo từng dòng IC
Tên ic
|
A2
|
A1
|
A0
|
24c01
|
X
|
X
|
X
|
24c02
|
X
|
X
|
X
|
24c04
|
V
|
V
|
X
|
24c08
|
V
|
X
|
X
|
24c16
|
X
|
X
|
X
|
24c32
|
V
|
V
|
V
|
24c64
|
V
|
V
|
V
|
24c128
|
V
|
V
|
V
|
24c256
|
V
|
V
|
V
|
Với trường hợp X:
Pin không có khả năng thay đổi địa chỉ của ic
Khi đó giá trị tại địa chỉ này mặc định bằng Low(0) bạn được phép để hở chân này, hoặc nối xuống nguồn 0V. Và không được nối chân này lên High(5v).
Với trường hợp V:
Pin khả dụng để thay đổi địa chỉ eeprom bằng cách nối dây.
- Bằng 1: Nối pin đó lên điện áp High (5v)
- Bằng 0: :Nối pin đó xuống điện áp Low (0v)
Trường hợp chung để suy ra địa chỉ: 1010A2A1A0 rồi đổi sang hex.
Bảng 2.1. Ánh xạ giá trị của cặp A0,A1,A2 ra mã hex
A2
|
A1
|
A0
|
Address (hex)=
|
0
|
0
|
0
|
0x50
|
0
|
0
|
1
|
0x51
|
0
|
1
|
0
|
0x52
|
0
|
1
|
1
|
0x53
|
1
|
0
|
0
|
0x54
|
1
|
0
|
1
|
0x55
|
1
|
1
|
0
|
0x56
|
1
|
1
|
1
|
0x57
|
Ví dụ
Tất cả các ic đều có địa chỉ : 0x50, địa chỉ này thường dùng như một địa chỉ mặc định khi chỉ muốn dùng 1 ic trên bus giống như ở bài 1.
XÉT IC 24C04, 24C08, 24C16.
Như ta đã biết mỗi thiết bị trên đường bus chỉ được phép mang một và chỉ một địa chỉ duy nhất.
Chạy code i2c_scanner Kiểm tra địa chỉ của các ic ta được kết quả sau.
Bảng 3.1. Kết quả chạy chương trình i2c_scanner
|
A2
|
A1
|
A0
|
Địa chỉ thu được hiện lên trên cửa sổ Serial.
|
24c04
|
0
|
0
|
0
|
0x50 và 0x51
|
0
|
1
|
0
|
0x52 và 0x53
|
|
1
|
0
|
0
|
0x54 và 0x55
|
|
1
|
1
|
0
|
0X56 và 0x57
|
|
24c08
|
0
|
0
|
0
|
0x50,0x51, 0x52, 0x53
|
|
1
|
0
|
0
|
0x54, 0x55, 0x56, 0x57
|
24c16
|
0
|
0
|
0
|
Từ 0x50 đến 0x57
|
Thật ngạc nhiên khi trên một ic lại có thể có tới nhiều hơn 1 địa chỉ. Vậy ta nên chọn địa chỉ nào để giao tiếp arduino với ic eeprom. ???
- Màu đỏ với hàm ý : Bắt buộc .
- Màu đen : Tùy chọn (1/0)
Giải thích nguyên nhân
Do sự nâng cấp về dung lượng, ic được phân ra làm các trang ô nhớ (Page), mỗi trang có dung lượng 256 ô nhớ. 24c04 có 2 Page, 24c08 có 4 Page, 24c16 có 8 Page.
Do đó chỉ với 1 byte địa chỉ ô nhớ sẽ không thể truy cập đến dung lượng lớn hơn. Người ta giải quyết bằng cách sử dụng chân A0 (hoặc A1, A2) làm chân chọn Page.
Ví dụ ic24c04
Với A0=0, địa chỉ truy cập ô nhớ chạy từ 0->255 thì ô nhớ trên ic là từ 0->255 của Page 1.
Với A0=1, địa chỉ truy cập ô nhớ chạy từ 256->511 thì ô nhớ trên ic là từ 0->255 của Page 2.
Cứ như thế người ta sử dụng nốt các chân A1, A2 làm các chân chọn Page để tăng dung lượng mà vẫn đảm bảo tốc độ giao thức.
Có nghĩa bảng địa chỉ ic eeprom sẽ được hiểu như sau:
Điều này cũng đã được nói rõ trong datasheet .
Đây cũng là lời giải thích cho vấn đề đã nêu: Một ic có thể mang nhiều địa chỉ.
Vậy thì ta sẽ chọn địa chỉ bằng cách cho P=0, như sau:
Bảng 4.1. Ví dụ chọn địa chỉ
|
A2
|
A1
|
A0
|
Địa chỉ thật của ic
|
24c04
|
0
|
0
|
0
|
0x50
|
0
|
1
|
0
|
0x52
|
|
1
|
0
|
0
|
0x54
|
|
1
|
1
|
0
|
0X56
|
|
24c08
|
0
|
0
|
0
|
0x50
|
|
1
|
0
|
0
|
0x54
|
24c16
|
0
|
0
|
0
|
0x50
|
- Màu đỏ với hàm ý : Bắt buộc .
- Màu đen : Tùy chọn (1/0)
- Bạn nên nhớ, mỗi Slave chỉ có một và chỉ một địa chỉ để truy cập mà thôi.
- Không nên để cho các Slave có địa chỉ giống nhau trên cùng một bus.
Về cách thức truy cập của các ic trên cũng khác nhau, bạn có thể theo dõi trong thư viện, mình đã chú thích rất rõ.
Ic 24c32, 24c64, 24c128, 24c256.
Dung lượng ic ngày càng tăng, chân A2,A1,A0 cũng đã dùng hết. Người ta lại tiến hành tăng độ dài chuỗi ô địa chỉ nhớ lên 2 byte.
Lúc này dung lượng có thể lên tới tới 256*256 ô nhớ.
Còn các chân A2, A1, A0 được quay về chức năng nguyên thủy của nó là cài địa chỉ cho ic.
Không còn chân chọn Page, mỗi ic (32,64,128,256) có thể có tới 8 địa khác nhau bằng cách thiết lập như thông thường.
Bảng 5.1. Ánh xạ mã hex của các IC 24c32, 24c64, 24c128, 24c256
IC 24c32, 24c64, 24c128, 24c256
|
|||
A2
|
A1
|
A0
|
Address (hex)=
|
0
|
0
|
0
|
0x50
|
0
|
0
|
1
|
0x51
|
0
|
1
|
0
|
0x52
|
0
|
1
|
1
|
0x53
|
1
|
0
|
0
|
0x54
|
1
|
0
|
1
|
0x55
|
1
|
1
|
0
|
0x56
|
1
|
1
|
1
|
0x57
|
Ok, chúng ta đi vào ví dụ sử dụng
Gỉa sử, bạn muốn sử dụng 3 ic 24c04 trên cùng một đường bus:
Nhìn vào bảng 4.1, bạn sẽ nhặt ra 3 địa chỉ hợp lệ là 0x50 (cho ic1), 0x52 (cho ic2), 0x54 (ic3).
Kiểm tra bằng i2c_scanner:
Cái mình đóng khung đỏ chính là địa chỉ ta đã thiết lập bằng phần cứng của 3 ic, (địa chỉ ảo 0x51, 0x53, 0x55, là của Page 2 có trên mỗi ic. Chúng ta không quan tâm đến nó).
Kiểm tra xong, bây giờ tiến hành đọc/ghi trên bus:
#include <Wire.h> #include <Eeprom24Cxx.h> static Eeprom24C ic1(4, 0x50); static Eeprom24C ic2(4, 0x52); static Eeprom24C ic3(4, 0x54); void setup() { Serial.begin(9600); //ghi const int address = 200; // lưu vào ô 200 ic1.write_1_byte(address, 10); delay(5); ic2.write_1_byte(address, 20); delay(5); ic3.write_1_byte(address, 30); delay(5); //đọc Serial.println("Read byte from EEPROM memory..."); byte d1, d2, d3; d1 = ic1.read_1_byte(address); d2 = ic2.read_1_byte(address); d3 = ic3.read_1_byte(address); //in ra Serial.println(d1); Serial.println(d2); Serial.println(d3); } void loop() { }
Vẫn giữ nguyên 3 ic, mình muốn dùng thêm ic 24c02, 24c08, 24c16, 24c256, 24c64, 24c128
Vì chỉ có tối đa 8 ic eeprom trên 1 bus nên mình sẽ lập 1 bảng để phân bố sao cho các địa chỉ thuộc địa chỉ cho phép và khác các địa chỉ còn lại.
B1: Bỏ ic 24c02 vì đã quá số lượng cho phép.
B2: Nhìn vào bảng 4.1 và 5.1 , mình cần chọn ra các địa chỉ phù hợp nhất
24c16
|
0x50. Đây cũng là địa chỉ duy nhất của ic nên phải ưu tiên chọn trước
|
Next
24c08
|
0x54. (0x50 đã bị dùng)
|
Next
24c04 (ic1)
|
0x52.(50,54 đã bị dùng)
|
24c04 (ic2)
|
0x56.( 50,52,54, đã bị dùng)
|
Còn 4 địa chỉ chưa dùng: 0x51,0x53, 0x55, 0x57
24c064
|
0x51
|
24c128
|
0x53
|
24c256
|
0x57
|
Chúng ta còn dư 1 ic 24c04(ic3) do không còn địa chỉ phù hợp.
B3: ráp mạch, tùy vào địa chỉ mà các bạn nối chân A cho phù hợp.
Do biết được đặc điểm là chỉ có thể có tối đa 8 ic nên mình đã làm một Shield như thế này,
Có 8 đế ic, mỗi đế có sãn địa chỉ khác nhau (0x50->0x57).
#include <Wire.h> #include <Eeprom24Cxx.h> static Eeprom24C ic_16(16, 0x50); static Eeprom24C ic_64(64, 0x51); static Eeprom24C ic_4_1(4, 0x52); static Eeprom24C ic_128(128, 0x53); static Eeprom24C ic_8(8, 0x54); static Eeprom24C ic_4_2(4, 0x56); static Eeprom24C ic_256(256, 0x57); // quản lí các đối tượng bằng mảng. static Eeprom24C ic[7] = { ic_16, ic_64, ic_4_1, ic_128, ic_8, ic_4_2, ic_256 }; void setup() { Serial.begin(9600); //ghi const int address = 100; // lưu vào ô 100 for (byte i = 0; i < 7; i++) { ic[i].write_1_byte(address, (i + 1) * 10); delay(5); } //đọc Serial.println("Read byte from EEPROM memory..."); for (byte i = 0; i < 7; i++) { byte d; d = ic[i].read_1_byte(address); //in ra Serial.println(d); } } void loop() { }
Kết quả
Nhìn vào kết quả, ta có thể khẳng định, arduino đã tìm đến đúng ic mong muốn. Không cái nào trùng cái nào.
Lời khuyên
Nếu bạn là beginner, bạn cảm thấy việc tìm địa chỉ gây khó khăn, mình khuyên bạn chỉ nên sử dụng ic 24c32, 24c64, 24c128, 24c256 (giá mua của nó chỉ cao hơn một chút xíu thôi, bạn hãy đầu tư nhé). Việc cài đặt địa chỉ rất dễ dàng. Bạn cũng chưa cần cố gắng hiểu đến những gì mình đã viết về ic khác (24c16 trở xuống).
Đó là bước làm quen tốt nhất.
Xong rồi đó.
HEHE, từ mục tiêu tìm hiểu cái eeprom trong tivi vứt xó đến khi mình viết được bài viết này là cả một quãng đường đầy thú vị. Ở nước ta, việc sử dụng ic này đã phổ biến rồi. Tuy vậy, tài liệu hướng dẫn vẫn rất hạn chế. Thậm chí là không ai muốn đả động đến phần sử dụng cùng lúc nhiều ic trên bus do có một chút nhập nhằng về cách thiết lập địa chỉ, các bài nước ngoài cũng chỉ nói đến 8 con ic 256 giống nhau, chứ chưa đề cập 8 con khác nhau như bài của mình.
Vấn đề về ic 24cxx cũng đã hết.
Tạm kết tại đây, rất mong sự ủng hộ của các bạn .
Tác giả: Thái Sơn.