Продолжаем знакомство с работой микросхемы памяти 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