Hướng dẫn sử dụng ic eeprom 24Cxx của Atmel và thư viện

Mô tả dự án: 

 Bấy lâu nay bạn đã sử dụng sai eeprom của arduino? ..Một ngày bạn sử dụng eeprom bao nhiêu lần? Có bao giờ bạn lo lắng tới tuổi thọ của EEPROM ?smiley

EEPROM là còn được hiểu như một thẻ nhớ có thể lưu trữ dữ liệu ngay cả khi mất điện.

Bộ nhớ EEPROM có sẵn của arduino có số lần ghi/xóa 100000 lần,  nếu dùng hết số lần ghi cho phép, eeprom sẽ hỏng. Để khắc phục điều này, chúng ta cần sử dụng một ic eeprom ngoại vi thay vì sử dụng eeprom của arduino.

Tuổi thọ của eeprom.

Tuổi thọ của eeprom trên các dòng AVR từ 10000 đến 100000 lần xóa/ghi, đó là con số do nhà sản xuất đưa ra.

Trong quá trình xóa/ghi dữ liệu,  các ô nhớ của eeprom sẽ bị “ bào mòn”  dần, một cách tương đối, khi vượt quá giới hạn trên, dữ liệu không còn được lưu trữ chính xác nữa. Các bạn đều biết, dữ liệu mà sai một li, thì kết quả đi một dặm. Do đó quan ngại và giải quyết vấn đề về độ bền của eeprom trên arduino là vô cùng quan trọng.

Hướng giải quyết: Sử dụng ic eeprom.

Cùng tìm hiểu nào!

Đầu tiên bạn nên nhớ vài điều này:

  • Ô nhớ trên eeprom bị bào mòn dần khi ta thực hiện thao tác ghi dữ liệu hoặc xóa dữ liệu.
  • Nếu chỉ đọc dữ liệu thì không ảnh hưởng đến tuổi thọ của eeprom.
  • Không sớm thì muộn bạn cũng cần phải biết cách sử dụng eeprom ngoại vi thay vì eeprom có sẵn trên arduino.

Giới thiệu về memory ic – eeprom. 24cxx và cách sử dụng

Về chức năng và cách thức ghi dữ liệu giống với eeprom trên arduino. Nó thường đi kèm với mọi loại thiết bị số ngày nay để lưu trữ các cài đặt trên thiết bị. IC epprom 24Cxx ở nước ta rất dễ tìm mua và nó cũng rất phổ biến trong làng arduino/mcu trên thế giới.  Sử dụng dễ dàng, giá thành hợp lí. 

Dòng ic 24Cxx của atmel  sử dụng chuẩn kết nối 2 dây I2

Có nhiều chủng loại tùy theo dung lượng cho bạn lựa chọn: 24c01, 24c02, 24c04,..vv

Số lần ghi/xóa là 1 triệu lần, gấp cả chục lần arduino.

Vì là ic ngoại vi nên bạn có thể dễ dàng thay thế, nâng cấp, vận chuyển, và cả cộng gộp sức mạnh của các eeprom.

PINOUT

A0
3 chân này để đặt địa chỉ
A1
A2
GND
 Nối xuống 0v
5V
Nối lên 5v
WP (write protect)
Cho phép ghi dữ liệu: Nối chân này xuống 0v
Không cho phép ghi dữ liệu: Nối lên 5v.
 
SCL (Serial Clock)
 2 chân cho giao tiếp i2c.
SDA (Serial DATA)

Giao tiếp với arduino

Chuẩn bị phần cứng:

Thư viện

Đây là thư viện đa năng, nó được dùng cho mọi loại ic eeprom 24cxx.

Tải về tại đây: Link

Nối dây

Tạo một module i2c như thế này:

C1: Với arduino thường

 

Trên arduino r3, 2 chân A4 và A5 được nối ra 2 jack chuyên biệt. SDA và SCK.

Sử dụng thư viện

Thủ tục khai báo

#include <Wire.h>//b1
#include <Eeprom24Cxx.h>//b2
static Eeprom24C eeprom(4,0x50);// b3

B1, B2: cài 2 thư viện. (bạn có thể bỏ đi dòng #include <Wire.h>)

B3:

Static
Eeprom24C
eeprom
4
0x50
Biến tĩnh
Tên class
Tạo và quản lí đối tượng  có tên “eeprom”
Mã ic: 04
Địa chỉ của ic.

Mã ic nói lên dung lượng của ic eeprom đó (số Page của ô nhớ).

Ta từng biết arduino atm128 có thể lưu 512 biến byte, atm328 có thể lưu 1024 biến byte.

ATmega 48A/PA
ATmega 88A/PA – 168A/PA
ATmega328/P
ATmega 640/V-1280/V-1281/V-2560/V-2561/V
256 bytes
512 bytes
1 Kbytes
4 Kbytes

Công thức để tính dung lượng của eeprom là : Số byte=( 1024 * mã ic)/8=128 * mã ic.

Bảng 1. Bảng tra dung lượng chip nhớ 24cx

Tên ic
Mã  (số page)
Dung lượng
24c01
1
128 bytes
24c02
2
256 bytes
24c04
4
512 bytes
24c08
8
1024 bytes
24c16
16
2048 bytes
24c32
32
4096 bytes
24c64
64
8192 bytes
24c128
128
16384 bytes
24c256
256
32768 bytes

Vân vân…

Địa chỉ của ic

Tất cả các ic đều có địa chỉ: 0x50. Khi ta nối các chân A0,A1,A2 xuống Low(0v).

Địa chỉ để làm gì?? Nó giúp arduino tìm đến chip eeprom trong giao tiếp i2c thui. 

Ghi dữ liệu

void write_1_byte(unsigned int  memory_address, byte data); 

Ex: eeprom.write(500,123);

Ghi vào byte thứ 500 giá trị bằng 123

Đọc dữ liệu

byte read_1_byte(unsigned int  memory_address); 

Ex: byte data= eeprom.read(500); Serial.println(data);

Bảng 2. Tra cứu địa chỉ đánh số dung lượng

Tên ic
Dung lượng
memory_address
24c01
128 bytes
0->127
24c02
256 bytes
0->255
24c04
512 bytes
0->511
24c08
1024 bytes
0->1023
24c16
2kb
0->2047
24c32
4kb
0->4095
24c64
8kb
0->8191
24c128
16kb
0->16383
24c256
32kb
0->32767
24c512
65,5 kb
0->65635

Ví dụ mẫu

Code test đầy đủ: ic 24c04

Các bạn lưu ý nhớ chọn đúng mã ic trên eeprom của bạn nhé.

#include <Wire.h>
#include <Eeprom24Cxx.h>
static Eeprom24C eeprom(4,0x50);// mình chọn 24c04.

void setup()
{
    Serial.begin(9600);
    const int address = 500;
    eeprom.write_1_byte(address, 123); 
    delay(5);
    
    
    byte data = eeprom.read_1_byte(address);
    Serial.print("Read byte = ");
    Serial.print(data);
    Serial.println("");
}

void loop()
{

}

Trạng thái ô nhớ

Cách lưu số lớn hơn kiểu byte ( >255) vào eeprom

Như ví dụ trên, số 123 (0->255) cần 8bit để lưu trữ, giờ để lưu một số lớn hơn 255 ( từ 16 bit trở lên) thì ta sẽ làm như sau:

Gỉa sử mình cần lưu số 345 vào eeprom ở ô địa chỉ 500. 

#include <Wire.h>
#include <Eeprom24Cxx.h>
#define type_ic 4
static Eeprom24C eeprom(type_ic,0x50);
void setup()
{     
    Serial.begin(9600);
    unsigned int a=345;
}
void loop()
{}

Đầu tiên ta biết số 345 được biểu diễn nhị phân là 0x0000000101011001.

B1: Ghi

Tách lấy 8bit cao (00000001) lưu vào ô địa chỉ 500.

Tách 8 bít thấp (01011001) lưu vào ô 501.

B2: đọc

Code thực thi

#include <Wire.h>
#include <Eeprom24Cxx.h>
#define type_ic 4
static Eeprom24C eeprom(type_ic, 0x50);
void setup()
{
    Serial.begin(9600);
    unsigned int a = 345;
    //ghi

    byte cao_8 = ((a >> 8) & 0xFF);
    eeprom.write_1_byte(500, cao_8);
    delay(5);
    byte thap_8 = (a & 0xFF);
    eeprom.write_1_byte(500 + 1, thap_8);
    delay(5);

    // đọc
    byte doc_cao_8, doc_thap_8;
    doc_cao_8 = eeprom.read_1_byte(500); // 0000,0001
    doc_thap_8 = eeprom.read_1_byte(501); // 0101,1001
    unsigned int doc_a; // khai báo// 0000,0000,0000,0000
    doc_a = (doc_cao_8 << 8); //0000,0001,0000,0000
    doc_a = doc_a | doc_thap_8; //0000,0001,0101,1001
    Serial.print(doc_a);
}
void loop()
{
}

Một điều cần lưu ý

  • Số muốn lưu phải là nguyên dương.
  • Gỉa sử địa chỉ mà chúng ta muốn lưu là ô 500, khi dùng để lưu một biến có cỡ 2byte thì ô 501 nghiễm nhiên đã bị sử dụng để lưu 8 bit còn lại, do đó, mặc định bạn không được dùng ô 501 để làm địa chỉ lưu , mà phải bắt đầu từ ô 502, bạn nhớ nhé.
  • Phải xem sét việc ghi nhiều byte có đang ghi trùng lên các ô khác hay không.  Ví dụ ô 500 đã có dũ liệu,Ta dùng ô 488 để lưu 4 byte, việc này sẽ ghi đè dữ liệu vào ô  500, gây sai lệch.
  • Kích cỡ lưu trữ của biến trên arduino và arduino mega khác nhau, Ví dụ kiểu double  trên uno là 4 bytes nhưng trên arduino due là 8 bytes, do đó kích cỡ để lưu cũng khác. 

Đây là toàn bộ hàm hỗ trợ ghi theo kiểu dữ liệu mong muốn.

  • void write_1_byte( unsigned int address, byte data);
  • byte read_1_byte(  unsigned int address);
  • uint16_t read_2_byte(  unsigned int address);
  • void write_2_byte( unsigned int address, uint16_t data);
  • void  write_4_byte( unsigned int address, uint32_t data);
  • uint32_t read_4_byte(  unsigned int address);
  • void write_8_byte( unsigned int address, uint64_t data);
  • uint64_t read_8_byte(  unsigned int address);

Như đã đề cập, các kiểu dữ liệu trên các dòng arduino có thể không giống nhau, để biết kiểu dữ liệu (trên arduino của bạn ) chiếm bao nhiêu byte, chúng ta dùng hàm sizeof();

Ví dụ: kiểu “unsigned int” trên arduino uno r3 chiếm 2 byte.

void setup()
{
    Serial.begin(9600);
    unsigned int a = 4002;
    Serial.print(sizeof(a));
}
void loop()
{
}

 

Code test lưu các số trên arduino uno r3

#include <Wire.h>
#include <Eeprom24Cxx.h>
#define type_ic 4
static Eeprom24C eeprom(type_ic, 0x50);
void setup()
{
    Serial.begin(9600);
    byte a = 255;
    unsigned int b = 62770;
    unsigned long c = 4000000000; //4 tỷ
    eeprom.write_1_byte(0, a);
    eeprom.write_2_byte(10, b);
    eeprom.write_4_byte(40, c);

    Serial.println(eeprom.read_1_byte(0));
    Serial.println(eeprom.read_2_byte(10));
    Serial.println(eeprom.read_4_byte(40));
}
void loop()
{
}

Thư viện này còn có thể làm điều tương tự trên eeprom của arduino.

Bạn truy cập các phương thức với tên thực thể là: AVR_EEPROM.

Đồng thời không khai báo ic eeprom, thư viện sẽ tự hiểu là chúng ta đang muốn dùng eeprom trên arduino.

  • void write_1_byte( unsigned int address, byte data);
  • byte read_1_byte(  unsigned int address);
  • uint16_t read_2_byte(  unsigned int address);
  • void write_2_byte( unsigned int address, uint16_t data);
  • void  write_4_byte( unsigned int address, uint32_t data);
  • uint32_t read_4_byte(  unsigned int address);
  • void write_8_byte( unsigned int address, uint64_t data);
  • uint64_t read_8_byte(  unsigned int address);
#include <Wire.h>
#include <Eeprom24Cxx.h>
void setup()
{ // viết và ghi dữ liệu lên eeprom của arduino
    Serial.begin(9600);
    byte a = 255;
    unsigned int b = 62770;
    unsigned long c = 4000000000; //4 tỷ
    AVR_EEPROM.write_1_byte(0, a);
    AVR_EEPROM.write_2_byte(10, b);
    AVR_EEPROM.write_4_byte(40, c);

    Serial.println(AVR_EEPROM.read_1_byte(0));
    Serial.println(AVR_EEPROM.read_2_byte(10));
    Serial.println(AVR_EEPROM.read_4_byte(40));
}
void loop()
{
}

Hoàn thiện kĩ năng

100.000 lần ghi/xóa của arduino hay 1 triệu lần của ic 24Cxx đều là con số lớn. Lớn đến vậy mà chuyện ghi/xóa vô tội vạ cũng khiến bạn phải thường xuyên thay thế 1 ic eeprom mới.

Mình xin gợi ý một vài thủ thuật để nâng cao tuổi thọ và tốc độ cho ic eeprom:

  • Vì bạn có thể đọc thoải mái dữ liệu mà không làm giảm tuổi thọ, nên trước khi ghi, bạn hãy kiểm tra xem dữ liệu đưa vào, nếu trùng khớp với dữ liệu cũ thì không cần ghi. (Cái này thư viện đã hỗ trợ rồi devil).
  • Nếu được, bạn hãy thường xuyên thay đổi vị trí ghi, để san sẻ số lần ghi cho các ô nhớ khác, nó giúp ta tránh việc phải vứt cả ic eeprom chỉ vì một hai ô nhớ bị hỏng. 
  • PIN số 7 (wp) trên ic giúp ta ngăn việc ghi dữ liệu bằng cách nối chân này lên HIGH (5v).
  • Để tốc độ được nhanh, nếu phải liên tục đọc lại dữ liệu ở cùng một ô nhớ trên eeprom, bạn hãy khai báo một biến, gán cho nó giá trị tại ô nhớ cần đọc, rồi chỉ đọc trên biến đó thôi.
  • Phải delay ít nhất 5 mili giây(ms) sau khi ghi để đảm bảo dữ liệu được lưu hoàn toàn.
  • Bạn không cần thiết phải ghi dữ liệu lên eeprom, hãy lưu tạm dữ liệu vào ram (khai báo một biến rồi thực hiện tính toán như bình thường cho biến đó), khi thật sự cần thiết thì mới cho lưu eeprom. Cách này thường dùng để tránh mất mát dữ liệu đang tính toán khi có sự cố mất điện. Cái này bạn có thể tìm hiểu thêm.

Vọc vạch..

Bạn muốn dung lượng cao hơn??

Tất nhiên là có ic cho bạn 24c1024. (1mb)

IC eeprom 24Cxx tháo máy !!!

Do mình viết lại thư viện, để đảm bảo tính chất lượng, nên đã mình đặt mua các loại ic khác nhau về để test trước khi đăng lên arduino.vn. Tuy nhiên trước đó, mình đã từng vọc loại ic eeprom này ở khá nhiều thiết bị khác nhau

Tivi có chú 24c04, tivi nào cũng có cả, mình nghĩ chúng để lưu các cài đặt của người dùng .

Cái main tivi cũ kĩ này cũng có cái để vọc đấy^^

Trên thanh ram có ic 24C02.

Trên card mạng có để lưu địa chỉ MAC, bạn nào có ý định thay địa chỉ MAC để thành HACKER thì đúng bài rồi ..hehe  (Cái này mình không khuyến khích đâu nhé devil).

Trong cái ổ VCD của máy tính có chú 93c865 cơ ^^

 

Hầm hố nhất đây: 39sf512 (4mb), at49f001(1mb)

Module Ic thời gian thực cũng có nhé.

Tất nhiên các eeprom trên đều đã có “tuổi”, nếu không tin tưởng nên mua mới ic thay vì dùng lại như trên.

Tự chế một module.

Vì ic nhỏ gọn, nên có thể bạn sẽ cần dùng nó giống như một usb eeprom. Hãy chế theo cách của bạn.

ở phiên bản này, mình có thêm led và tranzitor PNP -D8550 đèn sẽ sáng khi có tín hiệu mức thấp, báo là đang có truyền dẫn data.

Download thư viện.

Tải lên lần 1      ( 9:16 pm16/12/2016 ):

https://drive.google.com/file/d/0BzMEcyRK_uUFUl9tUHRZVVBYOHc/view?usp=sharing

Thư viện này hỗ trợ eeprom ic 24Cxx từ 24c01->24c512. 

Với những bạn gặp lỗi này : Arduino/libraries/Eeprom24Cxx/Eeprom24Cxx.cpp:131: error: 'EEPROM' was not declared in this scope

Là do bản IDE của bạn chưa có thư viện "EEPROM.h" Có 2 cách giải quyết:

  1. Bạn hãy cập nhật bản IDE mới nhất cho máy tính của mình.
  2. Hoặc bạn tải thêm thư viện EEPROM.h tại địa chỉ : https://drive.google.com/file/d/0BzMEcyRK_uUFbjF2SXhlY3NOanM/view?usp=sharing

 

Hãy liên hệ với mình nếu thư viện có bất cứ lỗi cài đặt nào.

BUS IC

Dòng ic 24cxx có địa chỉ nằm trong khoảng 1010A2 A1A( 0x50->0x57), có nghĩa là ta có thể có tới 8 ic eeprom dùng chung một bus i2c. Vậy bạn có muốn độ eeprom thành super eeprom không??laughwink. Hãy đón đọc bài tiếp theo nhé. Bài 2: Sử dụng cùng lúc nhiều ic eeprom 24Cxx trên bus

Cái kết có hậu

Có lẽ sau khi ta sử dụng được ic này rồi, hẳn sẽ thấy nó không quá khó. Đặc biệt hơn, chúng ta sẽ không còn phụ thuộc vào cái eeprom của arduino, và tất nhiên là bạn đã lên level rồi đấy.

Hi vọng bài viết hữu ích và bạn thấy thích bài viết này.laugh

Tác giả:  Thái Sơn.

lên
25 thành viên đã đánh giá bài viết này hữu ích.
Các dự án được truyền cảm hứng

Select any filter and click on Apply to see results

Các bài viết cùng tác giả

Giới thiệu module thu phát RF CC2530 tầm xa (plus CC2591) của Zigbee.

Mình mới đặt hàng được module RF này, đây là module truyền sóng 2.4 GHZ, khoảng cách rất xa, sử dụng giao tiếp Serial (TX-RX) rất thông dụng, cắm vào là chạy….Rất phù hợp với các dự án robot thám hiểm, thăm dò, tình báo,…..

lên
37 thành viên đã đánh giá bài viết này hữu ích.

AVR-Xuất xung với tần số và độ rộng theo ý muốn

Tiếp tục chuỗi bài: Điều khiển pin bằng ngôn ngữ chính thống. 

Bài viết này sẽ giúp bạn tạo một xung PWM có tần số và độ rộng xung theo ý muốn. 

lên
29 thành viên đã đánh giá bài viết này hữu ích.