logo
+7 (495) 997-37-74
Москва, ул.Международная, 15

Работа с памятью M25P40. Часть 3. Read и Write Byte и Arrays

В этой статье мы продолжим знакомство с микросхемой Flash памяти M25P40VP, установленной на беспроводном контроллере uniSensors nRF24, и разберём работу функций записи и чтения байтов из этого чипа.

Read & Write byte

Сценарий этого скетча очень простой: вначале мы полностью стираем содержимое Flash памяти чипа M25P40VP, далее записываем тестовое значение байта в одну из ячеек памяти микросхемы и затем производим считывание байта по этому же адресу для контроля правильности записи.

Код тестового скетча M25P40 Read & Write byte:

/*
  M25P40 Read & Write byte
*/

#include <SPI.h>
#include <SPIFlash.h>

#define FLASH_SS 8

#define TEST_ADR 0
#define TEST_VAL 4

SPIFlash flash(FLASH_SS);

void setup() {
  Serial.begin(115200);
  Serial.println(F("M25P40 Read & Write byte start..."));

  Serial.print(F("Init "));
  if (flash.initialize()) {Serial.println(F("OK"));}
                     else {Serial.println(F("FAIL"));}
  
  erase();
  readTest();
  writeTest();
  readTest();
}

String hexy(byte b) {
  String s = F("0x");
  if (b < 16) {s += '0';}
  String s2 = String(b, HEX);
  s2.toUpperCase();
  return s + s2;
}

void checkBusy() {
  uint32_t stt = millis();
  while (flash.busy()) { }
  uint32_t del = millis() - stt;
  if (del) {
    Serial.print(F(" (")); Serial.print(del); Serial.print(F(" ms)"));
  }
  Serial.println();
}

void erase() {
  Serial.print(F("Full erase..."));
  flash.chipErase();
  checkBusy();
}

void readTest() {
  byte res = flash.readByte(TEST_ADR);
  Serial.print(F("Read adr #")); Serial.print(TEST_ADR); Serial.print(F(": ")); Serial.print(hexy(res));
  checkBusy();
}

void writeTest() {
  flash.writeByte(TEST_ADR, TEST_VAL);
  Serial.print(F("Write adr #")); Serial.print(TEST_ADR); Serial.print(F(": ")); Serial.print(hexy(TEST_VAL));
  checkBusy();
}

void loop() {
  
}

Вначале объявляем значение адреса тестовой ячейки памяти. В нашем случае это нулевая ячейка M25P40VP. Вы можете выбрать любой номер ячейки из диапазона от 0 до 524227.

#define TEST_ADR 0

Затем объявляем тестовое значение байта, которое мы будем записывать во Flash память. В нашем случае это 4 (или 0x04 в шестнадцатеричном формате).

#define TEST_VAL 4

Далее следует участок кода, который определяет весь функционал скетча: мы стираем всё содержимое чипа M25P40VP, читаем содержимое нулевой ячейки памяти, записываем в неё тестовое число и снова читаем для того, чтобы убедиться в корректности записи и работы нашего скетча.

  erase();
  readTest();
  writeTest();
  readTest();

Функцию erase() мы рассматривали в предыдущей статье, здесь я только замечу, что мы производим замер задержки выполнения при помощи функции checkBusy() (тоже подробно описанной в предыдущей статье).

void erase() {
  Serial.print(F("Full erase..."));
  flash.chipErase();
  checkBusy();
}

Чтение байта из тестовой (в данном случае нулевой) ячейки памяти осуществляется функцией readTest().

void readTest() {
  byte res = flash.readByte(TEST_ADR);
  Serial.print(F("Read adr #")); Serial.print(TEST_ADR); Serial.print(F(": ")); Serial.print(hexy(res));
  checkBusy();
}

Само чтение осуществляет библиотечная функция readByte().

  byte res = flash.readByte(TEST_ADR);

Далее полученное значение выводится в Serial. Функция hexy() форматирует числа в шестнадцатеричном формате.

String hexy(byte b) {
  String s = F("0x");
  if (b < 16) {s += '0';}
  String s2 = String(b, HEX);
  s2.toUpperCase();
  return s + s2;
}

Запись тестового значения осуществляется функцией writeTest().

void writeTest() {
  flash.writeByte(TEST_ADR, TEST_VAL);
  Serial.print(F("Write adr #")); Serial.print(TEST_ADR); Serial.print(F(": ")); Serial.print(hexy(TEST_VAL));
  checkBusy();
}

А точнее библиотечной функцией writeByte() по заданному адресу в памяти M25P40VP.

  flash.writeByte(TEST_ADR, TEST_VAL);

Функция checkBusy() везде осуществляет контроль длительности проведения операции. Вот результат работы нашего тестового скетча:

Как вы видите, после полного стирания памяти чипа значение нулевой ячейки равно 0xFF и далее мы смогли успешно записать число 0x04 в эту ячейку (и прочитать его).

Read & Write array

Теперь давайте немного усложним задачу и попробуем прочитать и записать массив байтов в память микросхемы M25P40VP. Для работы с массивами байтов в библиотеке SPIFlash существуют функции readBytes() и writeBytes(), разберём подробнее их работу.

Код скетча M25P40 Read & Write array:

/*
  M25P40 Read & Write array
*/

#include <SPI.h>
#include <SPIFlash.h>

#define FLASH_SS 8

SPIFlash flash(FLASH_SS);

#define TEST_ADR 0

void setup() {
  Serial.begin(115200);
  Serial.println(F("M25P40 Read & Write array start..."));

  Serial.print(F("Init "));
  if (flash.initialize()) {Serial.println(F("OK"));}
                     else {Serial.println(F("FAIL"));}
  erase();
  testArray(TEST_ADR);
}

void checkBusy() {
  uint32_t stt = millis();
  while (flash.busy()) { }
  uint32_t del = millis() - stt;
  if (del) {
    Serial.print(F(" (")); Serial.print(del); Serial.print(F(" ms)"));
  }
  Serial.println();
}

void erase() {
  Serial.print(F("Full erase..."));
  flash.chipErase();
  checkBusy();
}

void printArray(byte* data, byte len) {
  for (byte i = 0; i < len; i++) {
    if (data[i] < 16) {Serial.print('0');}
    Serial.print(data[i], HEX);
    if (i < len - 1) {Serial.print(' ');}
  }
}

void testArray(uint32_t adr) {
  byte data[10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
  byte  res[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

  flash.readBytes (adr, res, 10);
  Serial.print(F("Before: ")); printArray(res, 10); Serial.println();

  Serial.println(F("Write array..."));
  flash.writeBytes(adr, data, 10);
  
  flash.readBytes (adr, res, 10);
  Serial.print(F("After:  ")); printArray(res, 10); Serial.println();
}

void loop() {
  
}

Вначале задаём начальный адрес в памяти для работы с массивом байтов. В нашем случае, для простоты, это нулевая ячейка.

#define TEST_ADR 0

Затем стираем всё содержимое чипа и приступаем к тестированию чтения и записи массива байтов.

  erase();
  testArray(TEST_ADR);

Выводить на печать содержимое тестового массива мы будем при помощи функции printArray().

void printArray(byte* data, byte len) {
  for (byte i = 0; i < len; i++) {
    if (data[i] < 16) {Serial.print('0');}
    Serial.print(data[i], HEX);
    if (i < len - 1) {Serial.print(' ');}
  }
}

Вся основная работа скетча производится в функции testArray().

void testArray(uint32_t adr) {
  byte data[10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
  byte  res[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

  flash.readBytes (adr, res, 10);
  Serial.print(F("Before: ")); printArray(res, 10); Serial.println();

  Serial.println(F("Write array..."));
  flash.writeBytes(adr, data, 10);
  
  flash.readBytes (adr, res, 10);
  Serial.print(F("After:  ")); printArray(res, 10); Serial.println();
}

Вначале мы объявляем 10-байтовый массив data[] и заполняем его тестовыми значениями. Это те байты, которые нам нужно будет далее записать в память микросхемы M25P40VP.

  byte data[10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};

Также мы объявляем (тоже 10-байтовый) массив res[] для получения и хранения результата чтения из памяти M25P40VP и заполняем его нулевыми значениями.

  byte  res[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

Далее мы читаем содержимое первых 10-и байтов памяти нашей Flash микросхемы.

  flash.readBytes (adr, res, 10);

И выводим их на печать. Поскольку чтение производится сразу после процедуры стирания памяти, то мы ожидаем, что все байты будут равны 0xFF.

  Serial.print(F("Before: ")); printArray(res, 10); Serial.println();

Далее записываем тестовый массив data[] во Flash память.

  Serial.println(F("Write array..."));
  flash.writeBytes(adr, data, 10);

И читаем результат из первых 10-и ячеек памяти M25P40VP.

  flash.readBytes (adr, res, 10);
  Serial.print(F("After:  ")); printArray(res, 10); Serial.println();

Вот результат работы нашего тестового скетча:

Всё происходит в точности с нашими теоретическими выкладками: задержка полного стирания микросхемы составляет чуть больше 3-х секунд (подробнее об этом см. предыдущую статью), сразу после операции стирания первые 10 байтов содержат значения 0xFF, а прочитанные после нашей записи байты полностью соответствуют нашему тестовому массиву, то есть операция записи массива байтов прошла успешно.

Заключение

В этой статье мы рассмотрели чтение и запись в память микросхемы M25P40VP как отдельных байтов, так и целых массивов. В следующей статье мы продолжим знакомство с M25P40VP и разберём работу с различными типами данных (их чтение и запись).

Ссылки по теме

Обзор контроллера uniSensors nRF24

Спецификации uniSensors nRF24

Программирование uniSensors nRF24

Работа с памятью M25P40. Часть 1. Спецификации и библиотека

Работа с памятью M25P40. Часть 2. Sleep, Wakeup, Erase и Busy

Работа с памятью M25P40. Часть 3. Read и Write Byte и Arrays

Работа с памятью M25P40. Часть 4. Работа с беззнаковыми типами данных

Работа с памятью M25P40. Часть 5. Работа со знаковыми типами данных

Работа с памятью M25P40. Часть 6. Read и Write Float

Работа с памятью M25P40. Часть 7. Read и Write Char array и String

Работа с памятью M25P40. Часть 8. Работа с секторами

Работа с памятью M25P40. Часть 9. Выборочное стирание секторов

Работа с памятью M25P40. Часть 10. Копирование секторов

Работа с памятью M25P40. Часть 11. Восстановление (backup) секторов

Работа с памятью M25P40. Часть 12. Работа с блоками памяти

Работа с памятью M25P40. Часть 13. Пишем библиотеку для работы с M25P40

Где купить?

uniSensors nRF24 в магазине «Electromicro»

Техническая поддержка

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

  • Емейл для вопросов по нашей продукции: electromicro@bk.ru
  • Наш телефон: +7 (495) 997-37-74

Аналогичные товары