MX25L8005 флэш-память (Arduino)

MX25L8005 представляет собой последовательную флэш-память CMOS размером 8 388 608 бит, которая содержит адресное пространство от 0 до 1 048 576 байт. Управление памятью осуществляется при помощи шины SPI.

На платформе Arduino использую флэш-память можно использовать для хранения больших массивов данных которые периодически запрашиваются при работе контроллера, для сбора информации с различных датчиков с последующей сортировкой и выводом информации.

Подключение флэш-памяти к плате Arduino Nano (Uno), LGT8F328p:

Флэш-память содержит 256 секторов по 4 кБ или 16 блоков по 64 кБ. Перед записью данных в память необходимо ее стереть. Стирание памяти осуществляется по секторам или по блокам, запись и чтение данных производится побайтно.

Помимо стиранием памяти по секторам или по блокам возможна полное стирание памяти.

Перед стиранием памяти необходимо дать команду разрешения записи, а после стирания памяти дать команду запрета записи. Аналогично нужно поступать при записи или чтении памяти.

Разрешение записи

  SPI.beginTransaction(mySet);
  digitalWrite(, LOW);
  SPI.transfer(0x06);
  digitalWrite(, HIGH);
  SPI.endTransaction();

Запрет записи

  SPI.beginTransaction(mySet);
  digitalWrite(, LOW);
  SPI.transfer(0x04);
  digitalWrite(, HIGH);
  SPI.endTransaction();

Отправка команды стирания сектора

Отправляем команду 0х20 для стирания сектора и указываем номер сектора 1. При этом номер сектора содержит адресацию в 24 бита, а так как секторов всего 256 (0…255), то отправляем три байта адреса 0x00 0x00 0x01.

  SPI.beginTransaction(mySet);
  digitalWrite(, LOW);
  SPI.transfer(0x20);
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  SPI.transfer(0x01);
  digitalWrite(, HIGH);
  SPI.endTransaction();

Отправка команды стирания блока

Отправляем команду 0х52 для стирания блока и указываем номер блока 1. При этом номер блока содержит адресацию в 24 бита, а так как блоков всего 16 (0…15), то отправляем три байта адреса 0x00 0x00 0x01.

  SPI.beginTransaction(mySet);
  digitalWrite(, LOW);
  SPI.transfer(52);
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  SPI.transfer(0x01);
  digitalWrite(, HIGH);
  SPI.endTransaction();

Запись данных

Запись данных осуществляется побайтно, отправляем команду для записи 0x02, далее указываем начальный адрес ячейки памяти с которого будет осуществляться запись, для примера для записи возьмем ячейку под номером 16500 или 0x004074 в шеснадцатиричной системе. Адрес должен так же быть 24-х битным, поэтому отправляем три байта 0x00 0x40 0x74.

Далее отправляем три байта data_0… data_2. Соответственно запись будет осуществлена по адресам 16500…16502.

  SPI.beginTransaction(mySet);
  digitalWrite(, LOW);
  SPI.transfer(0x02);
  SPI.transfer(0x00);
  SPI.transfer(0x40);
  SPI.transfer(0x74);
  SPI.transfer(data_0);
  SPI.transfer(data_1);
  SPI.transfer(data_2);
  digitalWrite(, HIGH);
  SPI.endTransaction();

Чтение данных

Чтение данных осуществляется побайтно, отправляем команду для чтения 0x03, далее указываем начальный адрес ячейки памяти с которого будет осуществляться чтение, для примера для записи возьмем ячейку под номером 16500 или 0x004074 в шеснадцатиричной системе. Адрес должен так же быть 24-х битным, поэтому отправляем три байта 0x00 0x40 0x74.

Далее отправляем ноль и получаем значение байта data_0, снова отправляем ноль и получаем значение байта data_1 и тд. Соответственно чтение будет осуществлено по адресам 16500…16502.

  SPI.beginTransaction(mySet);
  digitalWrite(, LOW);
  SPI.transfer(0x03);
  SPI.transfer(0x00);
  SPI.transfer(0x40);
  SPI.transfer(0x74);
  byte data_0 = SPI.transfer(0);
  byte data_1 = SPI.transfer(0);
  byte data_2 = SPI.transfer(0);
  digitalWrite(, HIGH);
  SPI.endTransaction();

Чтение как и запись может осуществляться по одному байту, например прочтем ячейку памяти под номером 0x18.

  SPI.beginTransaction(mySet);
  digitalWrite(, LOW);
  SPI.transfer(0x03);
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  SPI.transfer(0x18);
  byte data = SPI.transfer(0);
  digitalWrite(, HIGH);
  SPI.endTransaction();

Ниже показан пример скетча в котором стирается сектор 0, далее записывается массив из шести чисел, а в цикле loop() записанные в память значения выводятся в монитор порта. Запись и чтение осуществляет начиная с адреса 400 и по одному байту:

#include <SPI.h>

const int SSPin = 10;

SPISettings mySet(500000, MSBFIRST, SPI_MODE0);

byte arr[]={0x18, 0x22, 0xA0, 0xAF, 0x20, 0xA8};

void setup() {
  Serial.begin(9600);
  pinMode(SSPin, OUTPUT);
  SPI.begin(); 
  sector_clean(0);delay(1000);// 0...255 sectors (1sector=4k_byte)
 // block_clean(0);delay(2000);// 0...15 block (1block=64k_byte)
 // chip_clean();delay(20000);
  
  for(int i=0;i<6;i++){
  write_flash(i+400,arr[i]);
  }
}

void loop() { 
  for(int i=0;i<6;i++){
  Serial.print(read_flash(i+400),HEX);Serial.print(" ");
  }
  Serial.println();
  delay(1000); 
}

byte read_flash(long addr){
  byte addr_2 = (addr >> 16) & 0xFF;
  byte addr_1 = (addr >> 8) & 0x00FF;
  byte addr_0 = addr & 0x0000FF;
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(0x03);
  SPI.transfer(addr_2);
  SPI.transfer(addr_1);
  SPI.transfer(addr_0);
  byte data = SPI.transfer(0);
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();
  return data;
  }

void write_flash(long addr, byte data_byte){
  spi_rw(0x06);
  byte addr_2 = (addr >> 16) & 0xFF;
  byte addr_1 = (addr >> 8) & 0x00FF;
  byte addr_0 = addr & 0x0000FF;
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(0x02);
  SPI.transfer(addr_2);
  SPI.transfer(addr_1);
  SPI.transfer(addr_0);
  SPI.transfer(data_byte);
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();
  spi_rw(0x04);
  }

void sector_clean(byte addr){
  spi_rw(0x06);
  spi_command(0x20,0);
  spi_rw(0x04);
  }  

void block_clean(byte addr){
  spi_rw(0x06);
  spi_command(0x52,0);
  spi_rw(0x04);
  }   

void chip_clean(){
  spi_rw(0x06);
  spi_rw(0x60);
  spi_rw(0x04);
  } 

////////////////////////////////////////////////////////////////////
void spi_rw(byte data_rw){
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(data_rw);
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();
  }  

 void spi_command(byte data_command,byte addr){
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(data_command);
  SPI.transfer(0);
  SPI.transfer(0);
  SPI.transfer(addr);
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();
  }       


http://rcl-radio.ru/wp-content/uploads/2023/04/MX25L8005, 3V, 8Mb.pdf

Добавить комментарий

Войти с помощью: