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

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

В прошлой статье мы рассмотрели «упаковку» в библиотеку и использование некоторых «системных» функций работы с чипом M25P40VP, в этой статье мы рассмотрим перенос в библиотеку my25p40 некоторых функций для работы с различными типами данных, а также приведём полный код самой библиотеки, содержащийся в файлах my25p40.h и my25p40.cpp.

Начнём с функций readWord() и writeWord(), предназначенных для чтения и записи в память микросхемы M25P40VP данных типа word (беззнаковых двухбайтовых в диапазоне от 0 до 65535).

Функция writeWord()

Вот код этой функции, который мы использовали в оригинальном скетче M25P40 Read & Write Word:

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);
}

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

// Word

void my25p40::writeWord(uint32_t adr, word w) {
  byte bytes[2];
  bytes[0] = highByte(w);
  bytes[1] = lowByte(w);
  writeBytes(adr, bytes, 2);
}

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

  flash.writeWord(TEST_ADR, TEST_VAL);
  flash.writeInfo(TEST_ADR, String(TEST_VAL));

Функция readWord()

Аналогично для функции 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);
}

Библиотечная функция:

word my25p40::readWord(uint32_t adr) {
  byte bytes[2];
  readBytes(adr, bytes, 2);
  word wordValue = (bytes[0] << 8) | bytes[1] & 0xFF;
  return wordValue;
}

И пример использования:

  flash.readInfo(TEST_ADR, String(flash.readWord(TEST_ADR)));

Мы разобрали функции работы с данными типа word, библиотека содержит функции работы с остальными популярными типами данных (long, float, String и т. д.), вы можете самостоятельно разобрать их работу по аналогии с рассмотренными функциями работы с данными типа word.

Далее мы приведём полный код библиотеки my25p40.h.

Код файла my25p40.h

Теперь приведём полный код заголовочного файла my25p40.h:

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

#define FLASH_SECTOR_SIZE 65536

union uib_t {byte b[2]; int i;};
union ulb_t {byte b[4]; unsigned long ul;};
union  lb_t {byte b[4]; long lg;};
union flb_t {byte b[4]; float fl;};

extern uib_t uib;
extern ulb_t ulb;
extern  lb_t  lb;
extern flb_t flb;

class my25p40 : public SPIFlash {
  private:

  public:
    explicit my25p40(uint8_t slaveSelectPin, uint16_t jedecID=0) : SPIFlash(slaveSelectPin, jedecID=0) { };
    
    void checkBusy();
    
    void initInfo();
    void readInfo(uint32_t adr, String s);
    void writeInfo(uint32_t adr, String s);
    
    void erase();
    void erase64K(byte sec);
    
    void writeWord(uint32_t adr, word w);
    word readWord(uint32_t adr);
    
    void writeULong(uint32_t adr, unsigned long ul);
    unsigned long readULong(uint32_t adr);
    
    void writeInt(uint32_t adr, int i);
    int readInt(uint32_t adr);
    
    void writeLong(uint32_t adr, long lg);
    long readLong(uint32_t adr);
    
    void writeFloat(uint32_t adr, float fl);
    float readFloat(uint32_t adr);
    
    void writeChars(uint32_t adr, char chs[], byte len);
    void readChars(uint32_t adr, char *buf, byte len);
    
    void writeString(uint32_t adr, String s);
    String readString(uint32_t adr, byte len);
};

#endif // #ifndef MY25P40_H

Код файла 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"

// Busy

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

// Info

void my25p40::initInfo() {
  Serial.print(F("Init "));
  if (initialize()) {Serial.println(F("OK"));}
                     else {Serial.println(F("FAIL"));}
}

void my25p40::readInfo(uint32_t adr, String s) {
  Serial.print(F("Read #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(s);
}

void my25p40::writeInfo(uint32_t adr, String s) {
  Serial.print(F("Write #")); Serial.print(adr); Serial.print(F(": ")); Serial.println(s);
}

// Erase

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

uint32_t sectorAdr(byte i) {
  return FLASH_SECTOR_SIZE * i;
}

void my25p40::erase64K(byte sec) {
  uint32_t adr = sectorAdr(sec);
  Serial.print(F("Sector "));
  Serial.print(sec);
  Serial.print(F(" ("));
  Serial.print(adr);
  Serial.print(F(" + 64K) erase..."));
  
  blockErase64K(adr);
  checkBusy();
}

// Word

void my25p40::writeWord(uint32_t adr, word w) {
  byte bytes[2];
  bytes[0] = highByte(w);
  bytes[1] = lowByte(w);
  writeBytes(adr, bytes, 2);
}

word my25p40::readWord(uint32_t adr) {
  byte bytes[2];
  readBytes(adr, bytes, 2);
  word wordValue = (bytes[0] << 8) | bytes[1] & 0xFF;
  return wordValue;
}

// Unsigned long

ulb_t ulb;

void invertULong() {
  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 my25p40::writeULong(uint32_t adr, unsigned long ul) {
  ulb.ul = ul;
  invertULong();
  writeBytes(adr, ulb.b, 4);
}

unsigned long my25p40::readULong(uint32_t adr) {
  readBytes(adr, ulb.b, 4);
  invertULong();
  return ulb.ul;
}

// Int

uib_t uib;

void invertInt() {
  byte bytes[2];
  bytes[0] = uib.b[0];
  bytes[1] = uib.b[1];
  
  uib.b[0] = bytes[1];
  uib.b[1] = bytes[0];
}

void my25p40::writeInt(uint32_t adr, int i) {
  uib.i = i;
  invertInt();
  writeBytes(adr, uib.b, 2);
}

int my25p40::readInt(uint32_t adr) {
  readBytes(adr, uib.b, 2);
  invertInt();
  return uib.i;
}

// Long

lb_t lb;

void invertLb() {
  byte bytes[4];
  bytes[0] = lb.b[0];
  bytes[1] = lb.b[1];
  bytes[2] = lb.b[2];
  bytes[3] = lb.b[3];
  
  lb.b[0] = bytes[3];
  lb.b[1] = bytes[2];
  lb.b[2] = bytes[1];
  lb.b[3] = bytes[0];
}

void my25p40::writeLong(uint32_t adr, long lg) {
  lb.lg = lg;
  invertLb();
  writeBytes(adr, lb.b, 4);
}

long my25p40::readLong(uint32_t adr) {
  readBytes(adr, lb.b, 4);
  invertLb();
  return lb.lg;
}

// Float

flb_t flb;

void invertFloat() {
  byte bytes[4];
  bytes[0] = flb.b[0];
  bytes[1] = flb.b[1];
  bytes[2] = flb.b[2];
  bytes[3] = flb.b[3];
  
  flb.b[0] = bytes[3];
  flb.b[1] = bytes[2];
  flb.b[2] = bytes[1];
  flb.b[3] = bytes[0];
}

void my25p40::writeFloat(uint32_t adr, float fl) {
  flb.fl = fl;
  invertFloat();
  writeBytes(adr, flb.b, 4);
}

float my25p40::readFloat(uint32_t adr) {
  readBytes(adr, flb.b, 4);
  invertFloat();
  return flb.fl;
}

// Char array

void my25p40::writeChars(uint32_t adr, char chs[], byte len) {
  writeBytes(adr, chs, len);
}


void my25p40::readChars(uint32_t adr, char *buf, byte len) {
  readBytes(adr, buf, len);
  buf[len] = 0;
}

// String

void my25p40::writeString(uint32_t adr, String s) {
  int len = s.length() + 1;
  char char_array[len];
  strcpy(char_array, s.c_str());
  writeBytes(adr, char_array, len);
}

String my25p40::readString(uint32_t adr, byte len) {
  String s = "";
  char charArray[len];
  
  readBytes(adr, charArray, len);
  
  for (int i = 0; i < len; i++) {
    s += charArray[i];
  }
  
  return s;
}

#endif // #ifndef MY25P40_CPP

Заключение

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

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

Вы также можете использовать в ваших проектах на контроллерах uniSensors nRF24 (или любых других, имеющих на борту чип 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)

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

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

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

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