logo
+7 (951) 999-89-94
428003, г. Чебоксары, ул. Федора Гладкова, д.9, оф.319

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

В своей работе с микросхемой M25P40VP мы использовали библиотеку SPIFlash. Но, как вы могли заметить, в этой библиотеке реализованы только базовые функции коммуникации с чипом M25P40VP и работать с ней не очень удобно — все нужные нам функции по записи и чтению нужных нам типов данных нам приходилось реализовывать «вручную» прямо в скетчах.

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

И назовём мы нашу будущую библиотеку «My M25P40» (my25p40).

Архитектура библиотеки

Для решения нашей проблемы и написания собственной библиотеки M25P40VP возможны 3 варианта:

1. Написание собственной библиотеки работы с M25P40VP с нуля.

2. Модернизация и изменение исходной библиотеки SPIFlash.

3. Создание отдельного дополнения (обёртки) базовой библиотеки SPIFlash.

В принципе право на жизнь имеют все три варианта и каждый из них имеет свои достоинства и недостатки, разберём их подробнее:

1. Это, безусловно, самый правильный вариант, но он для своей реализации требует определённой квалификации и серьёзных временных и трудозатрат.

2. Тоже неплохой и вполне рабочий вариант, из недостатков тут можно назвать зависимость от базовой версии (которая взята за основу) исходной библиотеки.

3. С одно стороны немного «замороченный» вариант, но обеспечивающий независимость от базовой версии исходной библиотеки (при условии соблюдения авторами синтаксической совместимости в новых версиях) и быстрота разработки — от нас требуется только дописать нужные нам функции-обёртки.

Как вы уже догадались, мы будем создавать свою библиотеку в виде обёртки исходной библиотеки SPIFlash. Заодно вы сможете посмотреть как это делается и отметить для себя множество нюансов подобной реализации библиотеки.

Каркас библиотеки my25p40

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

my25p40

Внутри главной папки будут находиться два каталога:

examples — для примеров использования библиотеки

src — собственно файлы самой библиотеки

В «корне» библиотеки будут находиться 2 файла:

keywords.txt — файл, содержащий названия функций библиотеки для выделения их в среде Arduino IDE

library.properties — основные выходные данные библиотеки

В папке src будут находиться 2 файла библиотеки my25p40:

my25p40.h — заголовочный файл библиотеки my25p40

my25p40.cpp — сами функции библиотеки

Важный момент: поскольку мы решили реализовывать нашу библиотеку в виде обёртки исходной библиотеки SPIFlash, то в папку src мы помещаем саму библиотеку SPIFlash.

На этом мы заканчиваем рассмотрение структуры папок и файлов библиотеки и переходим к рассмотрению содержимого самих файлов.

library.properties

Как уже было замечено выше, library.properties — это файл, который содержит основные выходные данные нашей библиотеки. Вот его содержимое:

name=my25p40
version=0.1
author=EM
maintainer=em
sentence=My m25p40 Library
paragraph=
category=Memory
url=http://electromicro.ru/
architectures=*

Смысл и содержание надписей понятно из их обозначений ключевыми словами.

keywords.txt

Файл keywords.txt содержит названия функций нашей библиотеки для выделения их (цветом) в среде Arduino IDE.

#######################################
# Syntax Coloring Map
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################

my25p40	KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################

readWord	KEYWORD2
readInt	KEYWORD2
readULong	KEYWORD2
readLong	KEYWORD2
readFloat	KEYWORD2
readChars	KEYWORD2
readString	KEYWORD2
writeWord	KEYWORD2
writeInt	KEYWORD2
writeULong	KEYWORD2
writeLong	KEYWORD2
writeFloat	KEYWORD2
writeChars	KEYWORD2
writeString	KEYWORD2
checkBusy	KEYWORD2
initInfo	KEYWORD2
readInfo	KEYWORD2
writeInfo	KEYWORD2
erase	KEYWORD2
erase64K	KEYWORD2

#######################################
# Instances (KEYWORD2)
#######################################


#######################################
# Constants (LITERAL1)
#######################################

О самих функциях и их назначении будет рассказано немного ниже.

my25p40.h

my25p40.h — это заголовочный файл библиотеки my25p40. Вот его каркас (который мы дополним необходимым содержимым чуть ниже).

/*
  My m25p40 Library
  version 0.1
  2021, electromicro.ru
  License: GNU GPL 2.1
*/

#ifndef MY25P40_H
#define MY25P40_H

#include <Arduino.h>
#include "SPIFlash/SPIFlash.h"

...
...
…


#endif // #ifndef MY25P40_H

Он содержит:

  • Блок названия, версии, копирайта и лицензии библиотеки
  • Блок защиты от повторного подключения библиотеки (#ifndef MY25P40_H...)
  • Подключённые библиотеки (Arduino и SPIFlash)

my25p40.cpp

my25p40.cpp — это файл реализации функций нашей библиотеки, пока пустой каркас этого файла:

/*
  My m25p40 Library
  version 0.1
  2021, electromicro.ru
  License: GNU GPL 2.1
*/

#ifndef MY25P40_CPP
#define MY25P40_CPP

#include "my25p40.h"

...
...
…


#endif // #ifndef MY25P40_CPP

Он содержит:

  • Блок названия, версии, копирайта и лицензии библиотеки
  • Блок защиты от повторного подключения библиотеки (#ifndef MY25P40_CPP...)
  • Подключение заголовочного файла (my25p40.h)

Как вы видите структура файлов my25p40.h и my25p40.cpp довольно проста, осталось только наполнить эти файлы нужными нам функциями с нужным нам функционалом.

Функции библиотеки my25p40

Теперь давайте разберём состав функций, которые мы должны реализовать в нашей библиотеке. Все эти дополнительные функции можно разбить на 4 группы:

  • Системные
  • Информационные
  • Стирание памяти
  • Работа (запись и чтение) с различными типами данных

Теперь подробно рассмотрим каждую из этих групп.

Системные

void checkBusy() — это специальная функция для отслеживания «занятости» чипа M25P40VP при проведении им различных операций (см. предыдущие статьи цикла).

Информационные

void initInfo() — вывод диагностических сообщений при инициализации чипа M25P40VP.

void readInfo(uint32_t adr, String s) — вывод информации о чтении данных.

void writeInfo(uint32_t adr, String s) — вывод информации о записи данных.

Стирание памяти

void erase() — функция полного стирания чипа M25P40VP с выводом соответствующего сообщения.

void erase64K(byte sec) — функция посекторного стирания памяти с выводом соответствующего сообщения.

Работа с различными типами данных

void writeWord(uint32_t adr, word w) — запись по определённому адресу данных типа word.

word readWord(uint32_t adr) — чтение по определённому адресу данных типа word.

void writeULong(uint32_t adr, unsigned long ul) — запись данных типа unsigned long.

unsigned long readULong(uint32_t adr) — чтение данных типа unsigned long.

void writeInt(uint32_t adr, int i) — запись данных типа int.

int readInt(uint32_t adr) — чтение данных типа int.

void writeLong(uint32_t adr, long lg) — запись данных типа long.

long readLong(uint32_t adr) — чтение данных типа long.

void writeFloat(uint32_t adr, float fl) — запись данных типа float.

float readFloat(uint32_t adr) — чтение данных типа float.

void writeChars(uint32_t adr, char chs[], byte len) — запись данных типа char[].

void readChars(uint32_t adr, char *buf, byte len) — чтение данных типа char[].

void writeString(uint32_t adr, String s) — запись данных типа String.

String readString(uint32_t adr, byte len) — чтение данных типа String.

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

Приведём здесь наглядный пример пример использования библиотеки my25p40 и того, насколько упрощается работа с чипом M25P40VP при её использовании. Сначала пример работы с чипом M25P40VP при помощи стандартной библиотеки SPIFlash из одной из наших предыдущих статей:

/*
  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:

/*
  my25p40 Library Read & Write Word
*/

#include <SPI.h>
#include <my25p40.h>

#define FLASH_SS 8

#define TEST_ADR 0
#define TEST_VAL 65000

my25p40 flash(FLASH_SS);

void setup() {
  Serial.begin(115200);
  Serial.println(F("my25p40 Library Read & Write Word start..."));

  flash.initInfo();
  flash.erase();
  
  flash.readInfo(TEST_ADR, String(flash.readWord(TEST_ADR)));
  
  flash.writeWord(TEST_ADR, TEST_VAL);
  flash.writeInfo(TEST_ADR, String(TEST_VAL));
  
  flash.readInfo(TEST_ADR, String(flash.readWord(TEST_ADR)));
}

void loop() {
  
}

Как вы видите размер кода и его сложность изменились кардинально: теперь для реализации основного функционала скетча нужны всего 6 строк:

flash.initInfo();
  flash.erase();
  
  flash.readInfo(TEST_ADR, String(flash.readWord(TEST_ADR)));
  
  flash.writeWord(TEST_ADR, TEST_VAL);
  flash.writeInfo(TEST_ADR, String(TEST_VAL));
  
  flash.readInfo(TEST_ADR, String(flash.readWord(TEST_ADR)));

вместо примерно 30 в базовом варианте — выигрыш в 5 раз!

Заключение

На этом уроке мы разобрали базовые принципы создания нашей собственной библиотеки для работы с чипом 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

Работа с памятью M25P40. Часть 14. Пишем библиотеку для M25P40 (2)

Работа с памятью M25P40. Часть 15. Пишем библиотеку для M25P40 (3)

Где купить?

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

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

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

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

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