Продолжаем изучать работу с микросхемой памяти M25P40VP, установленной на плате uniSensors nRF24 и в этой статье мы познакомимся с чтением и записью строковых данных, таких, как массивы символов (char array) и String.
Read & Write char array
В среде программирования Ардуино работать со строковыми значениями можно при помощи двух типов данных — это массивы символов (char array) и String. Начнём с char array.
Char array — это набор символов (собственно текстовые строки), упакованные и представленные в виде массивов байтов типа char. Каждая такая строка оканчивается байтом нулевого значения, который означает конец строки. Например, если у вас есть строка «line», состоящая из 4-х символов, то полная длина этой строки будет равна 5-и байтам (плюс завершающий ноль).
Теперь давайте создадим скетч, который позволит записывать тестовую текстовую строку в память микросхемы M25P40VP и считывать её обратно. Скетч будет учитывать все особенности работы в Ардуино с данными типа char array и различные нюансы работы с памятью чипа M25P40VP.
Код скетча M25P40 Read & Write char array:
/* M25P40 Read & Write char array */ #include <SPI.h> #include <SPIFlash.h> #define FLASH_SS 8 #define TEST_ADR 0 char charsValue[] = "TestCharArray"; int len = sizeof(charsValue); SPIFlash flash(FLASH_SS); void setup() { Serial.begin(115200); Serial.println(F("M25P40 Read & Write char array start...")); Serial.print(F("Init ")); if (flash.initialize()) {Serial.println(F("OK"));} else {Serial.println(F("FAIL"));} erase(); read_String(TEST_ADR); write_String(TEST_ADR); read_String(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 read_String(uint32_t adr) { char charArray[len + 1]; flash.readBytes(adr, charArray, len); charArray[len] = 0; Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(charArray); } void write_String(uint32_t adr) { flash.writeBytes(adr, charsValue, len); Serial.print(F("Write #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(charsValue); } void loop() { }
Вначале мы задаём адрес тестовой ячейки (ячейки для записи первого символа нашей строки) памяти M25P40VP, в нашем случае это нулевая ячейка.
#define TEST_ADR 0
Затем мы создаём массив символов charsValue и присваиваем ему значение «TestCharArray».
char charsValue[] = "TestCharArray";
Далее мы вычисляем количество символов в нашей тестовой строке и присваиваем это значение переменной len.
int len = sizeof(charsValue);
Далее мы полностью стираем содержимое памяти чипа M25P40VP и читаем содержимое ячеек в которых должна быть записана наша строка (чтобы убедиться, что стирание прошло успешно и ячейки готовы для записи в них новой информации).
erase(); read_String(TEST_ADR);
Затем производим запись тестовой строки, начиная с нулевой ячейки, читаем её из микросхемы и проверяем результат.
write_String(TEST_ADR); read_String(TEST_ADR);
Чтение производится функцией read_String(), которой мы передаём адрес стартовой ячейки в качестве параметра.
void read_String(uint32_t adr) { char charArray[len + 1]; flash.readBytes(adr, charArray, len); charArray[len] = 0; Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(charArray); }
Создаём временный массив charArray размера len + 1.
char charArray[len + 1];
Читаем, начиная с адреса adr, len байтов в массив charArray при помощи функции flash.readBytes().
flash.readBytes(adr, charArray, len);
И дописываем ограничивающий ноль в позицию len временного массива.
charArray[len] = 0;
Далее выводим на печать полученный результат при помощи функции Serial.println().
Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(charArray);
Запись тестовой строки осуществляется при помощи функции write_String().
void write_String(uint32_t adr) { flash.writeBytes(adr, charsValue, len); Serial.print(F("Write #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(charsValue); }
Здесь мы при помощи функции flash.writeBytes() записываем в память микросхемы M25P40VP массив charsValue по адресу adr и длинной len.
flash.writeBytes(adr, charsValue, len);
Далее выводим в Serial информационное сообщение о наших действиях.
Serial.print(F("Write #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(charsValue);
И вот результат работы нашего скетча:
Первая строка
Read #0:яяяяяяяяяяяяяя
которую вывел контроллер на печать и состоящая из нескольких символов «я» — это текстовое представление очищенных ячеек памяти микросхемы M25P40VP, которые после процедуры очистки содержат значения 255 (11111111 в двоичном представлении).
Далее мы видим записываемую строку символов
Write #0: TestCharArray
и успешно прочитанную из памяти M25P40VP строку после проведённой операции записи.
Read #0: TestCharArray
Отлично! Теперь переходим к работе со стандартным для Ардуино представлением текстовых строк — типу String.
Read & Write String
Работа по записи и чтению строковых данных типа String похожа на работу с данными типа char array, правда тут есть ряд нюансов, связанных с организацией этих типов данных в Ардуино и далее мы подробно разберём работу со строковыми данными типа String.
String — это объектный тип данных (подробно описанный в документации Ардуино), предназначенный для хранения и работы со строковыми данными. Кроме собственно хранения строковых значений, этот тип данных имеет множество функций предназначенных для удобной работы со строками текста.
Далее мы создадим и разберём работу скетча для записи и чтения данных типа String из памяти микросхемы M25P40VP. Код скетча M25P40 Read & Write String:
/* M25P40 Read & Write String */ #include <SPI.h> #include <SPIFlash.h> #define FLASH_SS 8 #define TEST_ADR 0 String StringValue = "TestString"; int len = StringValue.length(); SPIFlash flash(FLASH_SS); void setup() { Serial.begin(115200); Serial.println(F("M25P40 Read & Write String start...")); Serial.print(F("Init ")); if (flash.initialize()) {Serial.println(F("OK"));} else {Serial.println(F("FAIL"));} erase(); read_String(TEST_ADR); write_String(TEST_ADR); read_String(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 read_String(uint32_t adr) { String s = ""; char charArray[len]; flash.readBytes(adr, charArray, len); for (int i = 0; i < len; i++) { s += charArray[i]; } Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(s); } void write_String(uint32_t adr) { char char_array[len]; strcpy(char_array, StringValue.c_str()); flash.writeBytes(adr, char_array, len); Serial.print(F("Write #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(StringValue); } void loop() { }
Вначале, как и в случае работы с char array, мы задаём адрес тестовой ячейки (ячейки для записи первого символа нашей строки) памяти M25P40VP, в нашем случае это нулевая ячейка.
#define TEST_ADR 0
Затем мы создаём тестовую строку и присваиваем ей значение «TestString».
String StringValue = "TestString";
Далее мы вычисляем количество символов в нашей тестовой строке при помощи функции length() и присваиваем это значение переменной len.
int len = StringValue.length();
Далее мы полностью стираем содержимое памяти чипа M25P40VP и читаем содержимое ячеек в которых должна быть записана наша строка (чтобы убедиться, что стирание прошло успешно и ячейки готовы для записи в них новой информации).
erase(); read_String(TEST_ADR);
Затем производим запись тестовой строки, начиная с нулевой ячейки, читаем её из микросхемы и проверяем результат.
write_String(TEST_ADR); read_String(TEST_ADR);
Чтение производится функцией read_String(), которой мы передаём адрес стартовой ячейки в качестве параметра.
void read_String(uint32_t adr) { String s = ""; char charArray[len]; flash.readBytes(adr, charArray, len); for (int i = 0; i < len; i++) { s += charArray[i]; } Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(s); }
Создаём переменную s типа String и присваиваем ей пустое значение. Эта переменная понадобится нам далее для получения и хранения прочитанной из памяти M25P40VP строки.
String s = "";
Далее создаём временный массив charArray размера len.
char charArray[len];
Читаем, начиная с адреса adr, len байтов в массив charArray при помощи функции flash.readBytes().
flash.readBytes(adr, charArray, len);
Далее «собираем» прочитанную тестовую строку в переменную s из временного массива charArray.
for (int i = 0; i < len; i++) { s += charArray[i]; }
Далее выводим на печать полученный результат при помощи функции Serial.println().
Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(s);
Запись тестовой строки осуществляется при помощи функции write_String().
void write_String(uint32_t adr) { char char_array[len]; strcpy(char_array, StringValue.c_str()); flash.writeBytes(adr, char_array, len); Serial.print(F("Write #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(StringValue); }
Здесь мы создаём временный массив char_array размера len.
char char_array[len];
При помощи функции strcpy() копируем содержимое переменной StringValue в массив char_array.
strcpy(char_array, StringValue.c_str());
И далее записываем в память микросхемы M25P40VP массив char_array по адресу adr и длинной len.
flash.writeBytes(adr, char_array, len);
Далее выводим в Serial информационное сообщение о наших действиях.
Serial.print(F("Write #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(StringValue);
Вот результат работы нашего скетча:
Всё прошло корректно и именно так, как мы и ожидали — тестовая строка типа String была записана в память микросхемы M25P40VP и успешно считана из неё.
Заключение
На этом уроке мы научились читать и записывать в память микросхемы M25P40VP, установленной на беспроводном контроллере uniSensors nRF24, строковые типы данных char array и String. В следующей статье мы продолжим увлекательное знакомство с чипом 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