
Продолжаем знакомство с работой микросхемы памяти M25P40VP, установленной на беспроводном контроллере uniSensors nRF24, и в этой статье разберём запись и чтение разных типов данных.
Read & Write word
На прошлом уроке мы научились записывать и читать из памяти микросхемы M25P40VP байты и массивы байтов, теперь мы разберём пример работы с числами типа word. Это беззнаковый тип данных (uint16_t), состоящий из двух байтов и принимающий значения от 0 до 65535.
В тестовом скетче мы запишем число типа word в память M25P40VP и считаем его для проверки корректности записи (предварительно очистив всю память чипа).
Код скетча M25P40 Read & Write word:
/*
M25P40 Read & Write word
*/
#include <SPI.h>
#include <SPIFlash.h>
#define FLASH_SS 8
#define TEST_ADR 0
#define TEST_VAL 65000
SPIFlash flash(FLASH_SS);
void setup() {
Serial.begin(115200);
Serial.println(F("M25P40 Read & Write word start..."));
Serial.print(F("Init "));
if (flash.initialize()) {Serial.println(F("OK"));}
else {Serial.println(F("FAIL"));}
erase();
readWord(TEST_ADR);
writeWord(TEST_ADR, TEST_VAL);
readWord(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 readWord(uint32_t adr) {
byte bytes[2];
flash.readBytes(adr, bytes, 2);
word wordValue = (bytes[0] << 8) | bytes[1] & 0xFF;
Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(wordValue);
}
void writeWord(uint32_t adr, word w) {
byte bytes[2];
bytes[0] = highByte(w);
bytes[1] = lowByte(w);
flash.writeBytes(adr, bytes, 2);
Serial.print(F("Write #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(w);
}
void loop() {
}
Вначале мы задаём адрес тестовой ячейки памяти M25P40VP, в нашем случае это нулевая ячейка.
#define TEST_ADR 0
Затем мы определяем тестовое число из диапазона, поддерживаемого типом word.
#define TEST_VAL 65000
Далее следует блок, определяющий функционал нашего скетча. Мы стираем память чипа, читаем содержимое тестовой ячейки, записываем в неё новое значение и снова читаем и проверяем результат.
erase(); readWord(TEST_ADR); writeWord(TEST_ADR, TEST_VAL); readWord(TEST_ADR);
Чтение производится функцией readWord(), которой мы передаём адрес тестовой ячейки в качестве параметра.
void readWord(uint32_t adr) {
byte bytes[2];
flash.readBytes(adr, bytes, 2);
word wordValue = (bytes[0] << 8) | bytes[1] & 0xFF;
Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(wordValue);
}
В ней мы объявляем массив bytes[] для получения и хранения 2-х байт тестового числа типа word. Читаем 2 байта из памяти M25P40VP в виде 2-байтового массива.
flash.readBytes(adr, bytes, 2);
Упаковываем эти 2 байта в число типа word.
word wordValue = (bytes[0] << 8) | bytes[1] & 0xFF;
И выводим на печать полученный результат.
Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(wordValue);
Вот результат работы нашего скетча:

Значение 65535, прочитанное сразу после стирания памяти микросхемы M25P40VP — это максимально возможное значение для типа word и определяется оно числами 0xFF, которыми заполняются ячейки памяти при стирании.
Далее мы видим успешные запись и считывание тестового числа 65000 типа word.
Read & Write unsigned long
Теперь по аналогии с предыдущим примером давайте научимся записывать и считывать из памяти M25P40VP большие беззнаковые числа типа unsigned long. Это тоже беззнаковый тип данных (uint32_t), состоящий уже из четырёх байтов и принимающий значения от 0 до 4294967295.
Код скетча M25P40 Read & Write unsigned long:
/*
M25P40 Read & Write unsigned long
*/
#include <SPI.h>
#include <SPIFlash.h>
#define FLASH_SS 8
#define TEST_ADR 0
#define TEST_VAL 4222111000
union {
unsigned long ul;
byte b[4];
} ulb;
SPIFlash flash(FLASH_SS);
void setup() {
Serial.begin(115200);
Serial.println(F("M25P40 Read & Write unsigned long start..."));
Serial.print(F("Init "));
if (flash.initialize()) {Serial.println(F("OK"));}
else {Serial.println(F("FAIL"));}
erase();
readULong(TEST_ADR);
writeULong(TEST_ADR, TEST_VAL);
readULong(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 invert() {
byte bytes[4];
bytes[0] = ulb.b[0];
bytes[1] = ulb.b[1];
bytes[2] = ulb.b[2];
bytes[3] = ulb.b[3];
ulb.b[0] = bytes[3];
ulb.b[1] = bytes[2];
ulb.b[2] = bytes[1];
ulb.b[3] = bytes[0];
}
void readULong(uint32_t adr) {
byte bytes[4];
flash.readBytes(adr, ulb.b, 4);
invert();
Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(ulb.ul);
}
void writeULong(uint32_t adr, unsigned long ul) {
ulb.ul = ul;
invert();
flash.writeBytes(adr, ulb.b, 4);
Serial.print(F("Write #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(ul);
}
void loop() {
}
Вначале мы задаём адрес тестовой ячейки памяти M25P40VP, в нашем случае это снова нулевая ячейка.
#define TEST_ADR 0
Затем мы определяем тестовое число из диапазона, поддерживаемого типом unsigned long (от 0 до 4294967295).
#define TEST_VAL 4222111000
Также мы создаём объединение (union) для совместного хранения в памяти различных типов данных — 4-байтового числа ul типа unsigned long и 4-байтового массива b[4]. Это нам понадобится в дальнейшем для записи, чтения и приведения различных типов данных.
union {
unsigned long ul;
byte b[4];
} ulb;
Далее следует блок, определяющий функционал нашего скетча. Мы стираем память чипа, читаем содержимое тестовой ячейки, записываем в неё новое значение и снова читаем и проверяем результат.
erase(); readULong(TEST_ADR); writeULong(TEST_ADR, TEST_VAL); readULong(TEST_ADR);
Чтение производится функцией readULong(), которой мы передаём адрес тестовой ячейки в качестве параметра.
void readULong(uint32_t adr) {
flash.readBytes(adr, ulb.b, 4);
invert();
Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(ulb.ul);
}
Здесь мы используем функцию flash.readBytes() чтения массива (из 4-х байт) из памяти M25P40VP по заданному адресу и «массивное» представление объединённого 4-байтового числа ulb.b[].
flash.readBytes(adr, ulb.b, 4);
Поскольку порядок байтов, выдаваемых функцией flash.readBytes() противоположен порядку байтов в представлении чисел типа unsigned long, мы дополнительно инвертируем этот порядок в объединении ulb при помощи функции invert().
void invert() {
byte bytes[4];
bytes[0] = ulb.b[0];
bytes[1] = ulb.b[1];
bytes[2] = ulb.b[2];
bytes[3] = ulb.b[3];
ulb.b[0] = bytes[3];
ulb.b[1] = bytes[2];
ulb.b[2] = bytes[1];
ulb.b[3] = bytes[0];
}
Далее выводим на печать полученный результат при помощи объединённой версии ulb.ul типа unsigned long.
Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(ulb.ul);
Вот результат работы нашего тестового скетча:

Сразу после операции стирания первые 4 байта (#0, #1, #2, #3) содержат значения 0xFF, поэтому мы прочитали максимально возможное значение 4294967295, а затем мы успешно записали и прочитали из первых четырёх ячеек памяти M25P40VP тестовое число 4222111000.
Заключение
В этой статье мы научились работать (читать и записывать) беззнаковые типы данных word и unsigned long в память микросхемы M25P40VP, установленной на беспроводном контроллере uniSensors nRF24. В следующей статье мы продолжим увлекательное знакомство с чипом M25P40VP и разберём работу со знаковыми типами данных.
Ссылки по теме
Обзор контроллера 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
Работа с памятью M25P40. Часть 14. Пишем библиотеку для M25P40 (2)
Работа с памятью M25P40. Часть 15. Пишем библиотеку для M25P40 (3)
Где купить?
uniSensors nRF24 в магазине «Electromicro»
Техническая поддержка
Мы внимательно относимся к потребностям наших клиентов и осуществляем техническую поддержку всей выпускаемой продукции. Вы можете написать нам письмо с вашим вопросом или позвонить по телефону и специалист нашей компании проконсультирует вас и поможет решить вашу проблему.
- Емейл для вопросов по нашей продукции: electromicro@bk.ru
- Наш телефон: +7 (495) 997-37-74



