Sử dụng Ic SRAM 23LC1024 bằng Driver với thư viện SRAM_MANAGER cho arduino

Mô tả dự án: 

Ở 2 bài trước, chúng ta đã biết cách giao tiếp và lưu trữ cơ bản trên 2 loại SRAM. Sau gần 6 tháng làm việc với SRAM trong các dự án, hôm nay mình sẽ chia sẻ 1 driver do mình thiết kế, nó dùng để hỗ trợ quản lý SRAM 23lc1024, đem đến cách dùng RAM ngoài thân thiện hơn cho lập trình viên.

Cần 1 driver cho SRAM 23lc1024 ?

Hẳn là khi giao tiếp với các SRAM ngoài, chúng ta luôn phải cảnh giác đến việc tìm địa chỉ đọc ghi cho các biến, phải phân chia sao cho dữ liệu của các biến không bị chồng chéo lên nhau, phải dồn dữ liệu về 1 khu để đảm bảo thừa nhiều nhất các ô liên tục chưa sử dụng, với mỗi dự án, bạn lại phải lập 1 kế hoạch từ đầu để quản lý SRAM. ..indecision

Từ những bất tiện này, thư viện SRAM_MANAGER đã được tạo ra. angel

           

Ví dụ khi sử dụng thư viện

Ví dụ Cấp phát động 1 mảng ARRAY kiểu Int với 10 phần tử rồi đọc/ghi  lên mảng:

Lập trình thường  Lập trình với IC SRAM
void setup()
{
    Serial.begin(9600);

    int Write = 1234;
    int Read = 0;

    int* ARRAY_a = new int[10]; //cấp phát
    ARRAY_a[5] = Write; // ghi
    Read = ARRAY_a[5]; // đọc

    Serial.println(Read);
    delete[] ARRAY_a; // thu hồi
}
void loop() {}

 

#include "SRAM_MANAGER.h"
void setup()
{
    Serial.begin(9600);
    SETTING_SRAM_DRIVER(12, false);

    int Write = 1234;
    int Read = 0;

    Sram_new(int, ARRAY_b, 10); // cấp phát
    Sram_write(ARRAY_b, 5, Write); // ghi
    Sram_read(ARRAY_b, 5, Read); // đọc

    Serial.println(Read);
    Sram_delete(ARRAY_b); // thu hồi
}
void loop() {}

 

Kết quả cho cả hai trường hợp đều giống nhau. Sự khác biệt chỉ ở chỗ ARRAY_a sẽ lưu trên RAM arduino, ARRAY_b sẽ lưu trên RAM ngoài .

Điều này có ý nghĩa gì ?  Điều mình muốn nhấn mạnh ở đây là sự đơn giản trong cách dùng RAM ngoài ở ví dụ B.

Bạn sẽ không phải lo lắng đến việc tìm địa chỉ cho mảng ARRAY_b. Lập trình ví dụ A cần n dòng thì ví dụ B cũng chỉ cần n dòng !wink

Nếu bạn chưa biết cấp phát động là gì thì hãy tìm hiểu tại đây nhé:

https://cpp.daynhauhoc.com/8/4-cap-phat-bo-nho-dong/

Giới thiệu mô hình Driver cho SRAM.

Gồm 2 phần:  Master Slave.

  • Master : là arduino của bạn, thực hiện một công việc nào đó cần nhiều bộ nhớ RAM , đòi hỏi phải cấu hình thêm RAM ngoài.
  • Slave : Là 1 module Driver, nó gồm 2 phần là Chip điều khiển ATMEGA328 và SRAM 23LC1024.
  • Master truyền nhận dữ liệu với Slave thông qua giao tiếp I2C.

   

Một mô hình thực tế trông như thế này : 

Thiết kế phần cứng

Bạn cần chuẩn bị

  • Master: 1 arduino bất kỳ (từ atmega 8 trở lên).
  • Slave: 1 arduino pro mini hoặc UNO R3 (hoặc vi khiển atmega328 được nạp sẵn bootloader).
  • IC Sram 23lc1024 : số lượng 2 (hoặc không cần laugh). 

Sơ đồ mạch

Các bạn chú ý : arduino pro mini và UNO r3 đều sử dụng chip atmega328, chức năng và cách đánh số các pin đều giống hệt nhau,  nên cách nối dây cũng không có gì thay đổi khi bạn chọn arduino pro mini là Slave.

Sơ qua về mạch

  • Master (arduino trên) và Slave (arduino dưới) giao tiếp với nhau bằng kết nối I2C qua cổng Data-Clock (Pin A4-A5). 2 điện trở 10k nối với dây bus i2c và nguồn 5v làm điện trở kéo.
  • Pin 6 (Flag output) trên Slavepin 12 (Flag input) trên Master được nối với nhau.
  • Pin 4, 5 (digital) trên Slave nối với 2 bóng LED hiển thị trạng thái của 2 IC Sram tương ứng, LED sẽ sáng nếu bạn nối mạch đúng, nếu không thấy đèn sáng thì phải kiểm tra lại mạch .
  • Pin 13, 12, 11 trên Slave là SCK-MISO-MOSI của giao tiếp SPI .
  • Pin 2, 3 trên Slave là 2 pin chọn chip (Select Chip) của  giao tiếp SPI.
  • Với 2 ic 23lc1024 , bạn sẽ có 260144 byte RAM.

Hình dưới sử dụng Slave là arduino UNO cho dễ nhìn. (nhấn vào ảnh để xem với kích thước lớn hơn).

  

Nếu như bạn không có SRAM 23lc1024  thì chỉ cần nối như mạch dưới là đủ, đây là phiên bản BETA của chương trình, Slave sẽ lấy chính RAM của Atmega328 làm 1 thanh RAM ảo có kích cỡ 1200 byte . Mình nghĩ là bạn nên chọn phiên bản này vào mục đích thí nghiệm trước .

Mạch sử dụng ic SRAM của mình

 

Phần mềm

Với Master

Bạn hãy tải và cài thư viện hỗ trợ cho arduino tại đây:

https://drive.google.com/open?id=0BzMEcyRK_uUFVnVJaTg4YWxKT1k

Sau đó bạn nạp code hex cho arduino theo hướng dẫn trong video 

 

Sau khi lắp mạch và cài thư viện thành công, chúng ta sẽ lập trình cho arduino Master. 

Cấp phát 1 vùng nhớ động

Lập trình thường   Lập trình với IC SRAM
<kiểu dữ liệu> *(Tên mảng) = new <kiểu dữ liệu> [cỡ mảng];

 

Cách 1:
Sram_new( <kiểu dữ liệu>,Tên mảng , cỡ mảng);
Cách 2:
uint32_t *<tên>=new uint32_t;
Sram_add(<kiểu dữ liệu>, tên, cỡ mảng);

 

Ví dụ :
int *A = new int[10];
uint32_t *B=new uint32_t[20];
float *C=new float[30];

 

 

 

Ví dụ cách 1:
Sram_new(int, A, 10);
Sram_new(uint32_t, B, 20);
Ví dụ cách 2:
uint32_t *C=new uint32_t;
Sram_add(float , C, 30);

 

 

Các kiểu dữ liệu thường dùng ;

Kiểu Gía trị biểu diễn Số byte lưu trữ
byte ,uint8_t,char, unsigned char  0 -> 255   1 byte
int16_t , int  -32768 -> 32767  2 byte
uint16_t, unsigned int , char16_t 0 -> 65535  2 byte.
int32_t, long   -2147483684 ->2147483683  4byte
uint32_t, unsigned long  0-> 4294967295 4 byte
float,double -3.4028235E+38 đến 3.4028235E+38.   4 byte

Chú ý : Slave là chip atmega328  8 bit, nên nó sẽ không cho phép lưu kiểu DOUBLE ở dạng 8byte giống như trên arduino DUE.

 Hàm Sram_new() khi được gọi sẽ tự động 2 thao tác là cấp phát 1 con trỏ địa chỉ 32bit và đặt giá trị của nó vào vùng HEAP trên SRAM ngoài. Do đó mỗi khi cấp phát 1 mảng, Master sẽ mất 4 byte lưu trữ cho con trỏ ! Đừng vội lo lắng, nó chỉ và chỉ duy nhất lấy đi 4 byte , 4 byte này sẽ được giải phóng khi bạn tiến hành thu hồi lại bộ nhớ bằng hàm Sram_delete(); 

 

 

Đọc /ghi dữ liệu và thu hồi bộ nhớ

Cấp phát động 1 mảng ARRAY kiểu Int với 10 phần tử rồi đọc/ghi  lên mảng:

Lập trình thường Lập trình với IC SRAM
Để gán :
Tên[index]=giá trị gán.
Đẻ đọc :
Biến cần gán = Tên[index];
Thu hồi RAM:
delete[] Tên_mảng;

 

Để gán:
Sram_write(Tên, index, giá trị gán);
Để đọc:
Sram_read(Tên, index, Biến cần gán);
Thu hồi RAM :
Sram_delete(Tên_mảng);

 

void setup()
{
    Serial.begin(9600);

    int Write = 1234;
    int Read = 0;

    int* ARRAY_a = new int[10]; //cấp phát
    ARRAY_a[5] = Write; // ghi
    Read = ARRAY_a[5]; // đọc

    Serial.println(Read);
    delete[] ARRAY_a; // thu hồi
}
void loop() {}
#include "SRAM_MANAGER.h"
void setup()
{
    Serial.begin(9600);
    SETTING_SRAM_DRIVER(12, false);

    int Write = 1234;
    int Read = 0;

    Sram_new(int, ARRAY_b, 10); // cấp phát
    Sram_write(ARRAY_b, 5, Write); // ghi
    Sram_read(ARRAY_b, 5, Read); // đọc

    Serial.println(Read);
    Sram_delete(ARRAY_b); // thu hồi
}
void loop() {}

Sau khi cấp phát và thực hiện tính toán, nếu như không dùng đến mảng đó nữa,ta sẽ phải thu hồi RAM bằng cách xóa mảng đó đi.

Nếu như bạn cấp phát trong 1 vòng lặp đệ quy mà  quên không xóa nó đi trước khi ra khỏi hàm thì bạn sẽ gặp lỗi tràn bộ nhớ ""ERROR overstack array too big "

Với Master (lập trình với RAM ngoài) thì 4 byte cấp cho con trỏ sẽ được giải phóng, dung lượng trên SRAM ngoài cũng được giải phóng đúng bằng lượng đã cấp phát !

Cấp phát, thu hồi

Bạn sẽ không thể cấp phát 2 mảng và thu hồi có tên giống nhau trong cùng 1 khối lệnh(biến cục bộ) hoặc ngoài hàm (biến toàn cục).

Ví dụ : 2 chương trình sau sẽ bị lỗi .

Lập trình thường Lập trình với IC SRAM 
// Chương trình này bị lỗi
void setup()
{
    int* a = new int[200];
    delete[] a;
    int* a = new int[200];
    delete[] a;
}
void loop()
{
}
// Chương trình này bị lỗi
#include "SRAM_MANAGER.h"
void setup()
{
    SETTING_SRAM_DRIVER(12, false);

    Sram_new(int, a, 200);
    Sram_delete(a);
    Sram_new(int, a, 200);
    Sram_delete(a);
}
void loop()
{
}

Tuy nhiên bạn có thể cấp phát nhiều mảng có tên giống nhau ở các hàm riêng biệt và bắt buộc phải DELETE mảng đó  trước khi ra khỏi hàm. (trước lệnh return)

Lập trình thường Lập trình với IC SRAM 
void setup()
{
}
void FUNC1()
{
    int* a = new int[200];
    // làm gì đó ở đây
    delete[] a;
    return;
}
void FUNC2()
{
    boolean B = true;
    int* a = new int[200];
    if (B == true) {
        delete[] a;
        return;
    }
    // làm gì đó ở đây
    delete[] a;
    return;
}
void loop()
{
}

 

#include "SRAM_MANAGER.h"
void setup()
{
    Serial.begin(9600);
    SETTING_SRAM_DRIVER(12, false);
}
void FUNC1()
{
    Sram_new(int, a, 200);
    // làm gì đó ở đây
    Sram_delete(x1);
    return;
}
void FUNC2()
{
    boolean B = true;
    Sram_new(int, a, 200);
    if (B == true) {
        Sram_delete(x1);
        return;
    }
    // làm gì đó ở đây
    Sram_delete(x1);
    return;
}
void loop()
{
}

 

 

Sử dụng như 1 biến toàn cục để có thể gọi ở bất cứ đâu trong chương trình , giống với  Sram_new(), Sram_add() dùng để thêm mới 1 biến con trỏ đã được khai báo trước đó.   

Lập trình thường Lập trình với IC SRAM
int* a = new int[10];
void setup()
{
    Serial.begin(9600);
    FUNC1();
}
void FUNC1()
{
    int Write = 1234;
    a[5] = Write;
}
void FUNC2()
{
    int Read = a[5];
    Serial.println(Read);
}
void loop()
{
    FUNC2();
}
#include "SRAM_MANAGER.h"
uint32_t* a = new uint32_t;
void setup()
{
    Serial.begin(9600);
    SETTING_SRAM_DRIVER(12, false);

    Sram_add(int, a, 10);
    FUNC1();
}
void FUNC1()
{
    int w1 = 1234;
    Sram_write(a, 5, w1);
}
void FUNC2()
{
    int Read = 0;
    Sram_read(a, 5, Read);
    Serial.println(Read);
}
void loop()
{
    FUNC2();
    delay(1000);
}

 

Nhiều hơn 1 mảng

Dùng như biến toàn cục

Lập trình thường  Lập trình với IC SRAM
int* a = new int[10];
long* b = new long[10];
float* c = new float[10];

void setup()
{
    Serial.begin(9600);
    FUNC1();
}
void FUNC1()
{
    int w1 = 1234;
    long w2 = 123456;
    float w3 = 67.0808;
    a[5] = w1;
    b[5] = w2;
    c[5] = w3;
}
void FUNC2()
{
    int r1 = a[5];
    long r2 = a[5];
    float r3 = a[5];
    Serial.println(r1);
    Serial.println(r2);
    Serial.println(r3);
}
void loop()
{
    FUNC2();
}
#include "SRAM_MANAGER.h"
uint32_t* a = new uint32_t;
uint32_t* b = new uint32_t;
uint32_t* c = new uint32_t;

void setup()
{
    Serial.begin(9600);
    SETTING_SRAM_DRIVER(12, false);

    Sram_add(int, a, 10);
    Sram_add(long, b, 10);
    Sram_add(float, c, 10);
    FUNC1();
}

void FUNC1()
{
    int w1 = 1234;
    long w2 = 123456;
    float w3 = 67.0808;
    Sram_write(a, 5, w1);
    Sram_write(b, 5, w2);
    Sram_write(c, 5, w3);
}
void FUNC2()
{
    int r1;
    Sram_read(a, 5, r1);
    long r2;
    Sram_read(b, 5, r2);
    float r3;
    Sram_read(c, 5, r3);
    Serial.println(r1);
    Serial.println(r2);
    Serial.println(r3);
}
void loop()
{
    FUNC2();
    delay(1000);
}

Dùng như biến cục bộ

Lâp trình thường Lập trình với IC SRAM

int w, r;

void setup()
{
    Serial.begin(9600);
}
void FUNC1()
{
    int* a = new int[10];
    w = 123;
    a[5] = w;
    r = a[5];
    Serial.println(r);
    delete[] a;
}
void FUNC2()
{
    int* a = new int[10];
    w = 456;
    a[5] = w;
    r = a[5];
    Serial.println(r);
    delete[] a;
}

void loop()
{
    FUNC1();
    FUNC2();
}
#include "SRAM_MANAGER.h"
int w, r;

void setup()
{
    Serial.begin(9600);
    SETTING_SRAM_DRIVER(12, false);
}
void FUNC1()
{
    Sram_new(int, a, 10);
    w = 123;
    Sram_write(a, 5, w);
    Sram_read(a, 5, r);
    Serial.println(r);
    Sram_delete(a);
}
void FUNC2()
{
    Sram_new(int, a, 10);
    w = 456;
    Sram_write(a, 5, w);
    Sram_read(a, 5, r);
    Serial.println(r);
    Sram_delete(a);
}

void loop()
{
    FUNC1();
    FUNC2();
}

Các hàm kiểm tra thông tin mảng

Hàm Sram_get_size_of( uint32_t Name, uint32_t size);

Dùng để lấy kích cỡ (số byte) của kiểu dữ liệu mà nó lưu trữ.

Ví dụ

void loop()
{
    Sram_new(float, x, 100);
    uint32_t size_of;
    Sram_get_size_of(x, size_of);
    Serial.print(" sizeof_x=");
    Serial.println(size_of);
    Sram_delete(x1);
}

Kết quả sizeof_x=4 (byte);

Một vài hàm khác

Chú ý :kiểu trả về của các hàm này là uint32_t (unsigned long). 

Serial.print("ram_size=");
Serial.println(get_ram_size()); // số byte của RAM
Serial.print("ram_free=");
Serial.println(get_ram_free()); // số byte chưa dùng
Serial.print("heap_used=");
Serial.println(get_heap_used()); // số byte vùng HEAP đã dùng
Serial.print("stack_used=");
Serial.println(get_stack_used()); // số byte vùng STACK đã dùng
Serial.print("count_array=");
Serial.println(get_count_array()); // số lượng (biến) mảng đang quản lý

 

Hàm SETTING_SRAM_DRIVER()

Hàm này nên đặt ở vị trí đầu tiên của chương trình.

SETTING_SRAM_DRIVER(int flag_pin,boolean ignore_error);
  • flag_pin: pin đặt cờ dữ liệu.
  • ignore_error:
    • đặt là false : dừng và thông báo khi có lỗi
    • đặt là true : vẫn chạy tiếp khi có lỗi

Các lưu ý

  • Gọi hàm này 1 lần duy nhất trong hàm setting()
  • Tất cả các hàm sử lý như Sram_new, Sram_addSram_write, v.v phải được đặt sau hàm SETTING_SRAM_DRIVER();
  • Khi gọi hàm SETTING_SRAM_DRIVER(), tất cả dữ liệu trên RAM sẽ bị xóa !

Các hàm cài đặt khác

Gọi sau hàm SETTING_SRAM_DRIVER():

set_mode_1_ic(); // nếu dùng 1 ic 23lc1024 131 kByte
set_mode_2_ic(); //nếu dùng 2 ic (262 kByte)
sram_clear();  // xóa toàn bộ dữ liệu trên RAM
get_version(); // kiểm tra phiên bản

Các thông báo lỗi trên cửa sổ Serial khi ứng dụng đang chạy.

Chú ý

Để xem được thông báo lỗi bạn cần mở cổng Serial.begin();

Lỗi "ERROR overstack array too big "

Đó là khi dung lượng của Stack không còn đủ chỗ trống để thêm 1 mảng mới. Bạn cần kiểm tra lại dung lượng còn dư (bằng hàm get_ram_free()) trước khi tạo mảng có kích cỡ lớn. Hiện tượng tràn bộ nhớ cũng có thể do bạn quên không thu hồi bộ nhớ sau khi thoát hàm.

#include "SRAM_MANAGER.h"
void setup() {
  Serial.begin(9600);
SETTING_SRAM_DRIVER(12,false);
}
void loop() {
   Sram_new(uint8_t,x1,1000);//ok 
   Sram_new(uint8_t,x2,1000); //ok
   Sram_new(uint8_t,x3,100000000);// lỗi ở đây 
   Sram_delete(x1);
   Sram_delete(x2);
   Sram_delete(x3);

}
/*
hoặc 
void loop() {
   Sram_new(int,x1,5000);// bộ nhớ sẽ đầy sau 1 khoảng thời gian do không được thu hồi 

}

*/

 

 

 

Lỗi "ERROR not fit size of datatype "

Kiểu dữ liệu của biến đệm đọc/ghi không khớp với kiểu lưu trữ. 

#include "SRAM_MANAGER.h"
void setup() {
Serial.begin(9600);
SETTING_SRAM_DRIVER(12,false);
}
void loop() {
Sram_new(int,x1,10);//ok 
float Write=12;// lỗi ở đây
Sram_write(x1, 5,Write);
Sram_delete(x1);

}

 

 

 

Lỗi "ERROR pointer outof array size"

Bạn đã gọi phần tử nằm ngoài vùng chứa của mảng.

#include "SRAM_MANAGER.h"
void setup() {
Serial.begin(9600);
SETTING_SRAM_DRIVER(12,false);
}
void loop() {
Sram_new(int,x1,10);//cỡ mảng 10
int Write=12;
Sram_write(x1, 30,Write);// Lỗi ở đây,ghi vào phàn tử 30
Sram_delete(x1);
}

 

 

 

Lỗi "ERROR not found name_ request"

Bạn đã yêu cầu 1 tên không còn tồn tại hoặc kết nối SPI giữa Slave và IC SRAM bị đứt.


#include "SRAM_MANAGER.h"

void setup() {
  Serial.begin(9600);
SETTING_SRAM_DRIVER(12,false);
}
void loop() {
   Sram_new(int,x1,50);
   Sram_delete(x1);
   int W=100;
   Sram_write(x1,10,W);//lỗi ở đây

}

 

 

Một vài câu hỏi

Hỏi: "SRAM có bị phân mảnh hay không, tôi có phải quan tâm đến nó hay không ?"

Cũng như bao bộ nhớ RAM khác, sau khi bạn thu hồi 1 vùng nhớ có địa chỉ nằm trong khoảng giữa của 2 mảng còn lại thì hiện tượng phân mảnh sẽ xuất hiện.

Tuy nhiên, bạn không cần phải quan tâm đến vấn đề này, Driver sẽ tự động sắp xếp lại các mảng trong SRAM để đảm bảo luôn có 1 vùng nhớ chưa sử dụng( liên tục) lớn nhất có thể.

Bạn có thẻ chạy code sau trên hệ thống 2 IC SRAM.

// phiên bản chạy trên 2 IC SRAM
#include "SRAM_MANAGER.h"
void setup()
{
    Serial.begin(9600);
    SETTING_SRAM_DIVER(12, false);
}

void loop()
{
    Sram_new(uint8_t, x1, 300);
    Sram_new(uint8_t, x2, 500);
    Sram_new(uint8_t, x3, 100);
    Sram_delete(x1);
    Sram_delete(x2);
    Sram_delete(x3);

    Sram_new(uint8_t, x4, 400);
    Sram_delete(x4);
    Sram_new(uint8_t, x5, 600);
    Sram_delete(x5);
    Sram_new(uint8_t, x6, 100);
    Sram_delete(x6);

    Sram_new(uint8_t, x7, 100);
    Sram_new(uint8_t, x8, 100);
    Sram_delete(x7);
    Sram_new(uint8_t, x9, 100);
    Sram_delete(x9);
    Sram_delete(x8);
    Serial.println("OK");
}

 

"Tại sao lại là Chip Driver ?"

Vì công việc chống phân mảnh rất tốt thời gian nên ta cần 1 Chip chuyên dụng.

"Có thể nhúng Driver lên Master được hay không ?"

Có thể , nhưng ít nhất thì hệ thống của bạn phải chạy được đa nhiệm, nếu không đa nhiệm thì  tốc độ xử lý phải thực sự vượt trội (100Mhz trở lên).

" Tốc độ đọc ghi  ?"

 Ngoài vấn đề về tốc độ của arduino chỉ là 16Mhz thì giải thuật cũng là 1 nguyên nhân thứ 2.

Khảo sát tốc độ đọc ghi : 

Thời gian để ghi vào 40000 ô nhớ là 27.543 s
Thời gian để đọc 40000 ô là 23.448 s

 Khai báo 1 mảng 10000 phần tử   rồi đọc ghi liên tiếp, ta thu được bảng sau.

Kiểu lưu trữ Tổng thời gian ghi Tổng thời gian đọc
4 byte 27.543 s 23.448 s
2 byte 24.881 s 22.800 s
1 byte 23.589 s  22.538 s

"Tốc độ chống phân mảnh ? "

 Driver chống phân mảnh bằng cách copy và paste toàn bộ dữ liệu của các mảng sao cho chúng xếp khít nhau một cách liên tục trên Stack, do đó nếu phía sau mảng bạn delete là một mảng lớn thì bạn sẽ phải đợi 1 khoảng thời gian rất dài và bằng đúng thời gian đọc +ghi , thời gian này có thể lên đến hàng phút !

"Cải thiện thời gian chống phân mảnh "

 Tuy nhiên thời gian chống mảnh lại có thể chỉ mất vài milli giây nếu như bạn xóa có thứ tự :

Quy tắc là chúng ta sẽ chỉ xóa mảng cuối cùng , ví dụ tạo lần lượt mảng 3 mảng : int a[10000] , int b[10000] , int c[10000].

  •  Nếu bạn xóa a thì sẽ phải đợi 88s
  • Nếu bạn xóa b thì phải đợi 44s
  • Nếu bạn xóa c thì phải đợi 0s.

Sau khi xóa c nếu bạn xóa a thì phải đợi 44s , (hoặc đợi 0s nếu xóa b)

 "Phiên bản không có chức năng chống phân mảnh ?"

  • ưu điểm : bạn có thể xóa bất kỳ mảng nào với thời gian 0s !
  • Nhược điểm : Khi muốn cấp phát 1 vùng nhớ thì dung lượng cấp phát phải nhỏ hơn hoặc bằng vùng chứa liên tục (chưa sử dụng). Việc này đôi khi sẽ khiến bạn không thể cấp phát mảng byte[100] mặc dù Free_ram là 10000 byte ! 

 "Chống phân mảnh theo sở thích "

Mình sẽ kết hợp ưu điểm của 2 loại trên , khi đó bạn sẽ có thể kích hoạt chế độ chống phân mảnh nếu cần, việc này sẽ tiết kiệm nhiều thời gian hơn. Chức năng này sẽ có trong version sau này !

lên
7 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

Bộ điều khiển PID - ứng dụng phần 2 - xe dò line dùng thuật toán PID

Tiép nối bài viết về xe dò line cảm ơn Đỗ Hữu Toàn đã viết hộ mình phần 4. hôm nay mình sẽ làm cho chiếc xe dò line đi mượt và có hồn hơn 

lên
34 thành viên đã đánh giá bài viết này hữu ích.
Các bài viết cùng tác giả

Các hàm kiểm tra tính đúng đắn của việc nhập xuất trên Arduino

Bài viết này bổ xung các tập lệnh liên quan đến kiểm tra nhập xuất kí tự được cập nhật trên arduino.cc

 

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

GAME-ST7565 - Làm game PONG với Arduino

PONG – một game đơn giản, funny và đòi hỏi chút kiên nhẫn. Hôm nay mình sẽ hướng dẫn các bạn làm game này trên lcd ST7565 bằng Arduino .

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